aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorJeff Garzik <jeff@garzik.org>2006-06-22 22:11:56 -0400
committerJeff Garzik <jeff@garzik.org>2006-06-22 22:11:56 -0400
commit71d530cd1b6d97094481002a04c77fea1c8e1c22 (patch)
treee786da7145d83c19a594adf76ed90d52c51058b1 /sound
parentd7a80dad2fe19a2b8c119c8e9cba605474a75a2b (diff)
parentd588fcbe5a7ba8bba2cebf7799ab2d573717a806 (diff)
Merge branch 'master' into upstream
Conflicts: drivers/scsi/libata-core.c drivers/scsi/libata-scsi.c include/linux/pci_ids.h
Diffstat (limited to 'sound')
-rw-r--r--sound/Kconfig2
-rw-r--r--sound/Makefile2
-rw-r--r--sound/aoa/Kconfig17
-rw-r--r--sound/aoa/Makefile4
-rw-r--r--sound/aoa/aoa-gpio.h81
-rw-r--r--sound/aoa/aoa.h131
-rw-r--r--sound/aoa/codecs/Kconfig32
-rw-r--r--sound/aoa/codecs/Makefile3
-rw-r--r--sound/aoa/codecs/snd-aoa-codec-onyx.c1113
-rw-r--r--sound/aoa/codecs/snd-aoa-codec-onyx.h76
-rw-r--r--sound/aoa/codecs/snd-aoa-codec-tas-gain-table.h209
-rw-r--r--sound/aoa/codecs/snd-aoa-codec-tas.c654
-rw-r--r--sound/aoa/codecs/snd-aoa-codec-tas.h47
-rw-r--r--sound/aoa/codecs/snd-aoa-codec-toonie.c141
-rw-r--r--sound/aoa/core/Makefile5
-rw-r--r--sound/aoa/core/snd-aoa-alsa.c98
-rw-r--r--sound/aoa/core/snd-aoa-alsa.h16
-rw-r--r--sound/aoa/core/snd-aoa-core.c162
-rw-r--r--sound/aoa/core/snd-aoa-gpio-feature.c399
-rw-r--r--sound/aoa/core/snd-aoa-gpio-pmf.c246
-rw-r--r--sound/aoa/fabrics/Kconfig12
-rw-r--r--sound/aoa/fabrics/Makefile1
-rw-r--r--sound/aoa/fabrics/snd-aoa-fabric-layout.c1109
-rw-r--r--sound/aoa/soundbus/Kconfig14
-rw-r--r--sound/aoa/soundbus/Makefile3
-rw-r--r--sound/aoa/soundbus/core.c250
-rw-r--r--sound/aoa/soundbus/i2sbus/Makefile2
-rw-r--r--sound/aoa/soundbus/i2sbus/i2sbus-control.c192
-rw-r--r--sound/aoa/soundbus/i2sbus/i2sbus-control.h37
-rw-r--r--sound/aoa/soundbus/i2sbus/i2sbus-core.c387
-rw-r--r--sound/aoa/soundbus/i2sbus/i2sbus-interface.h187
-rw-r--r--sound/aoa/soundbus/i2sbus/i2sbus-pcm.c1021
-rw-r--r--sound/aoa/soundbus/i2sbus/i2sbus.h112
-rw-r--r--sound/aoa/soundbus/soundbus.h202
-rw-r--r--sound/aoa/soundbus/sysfs.c43
-rw-r--r--sound/arm/sa11xx-uda1341.c16
-rw-r--r--sound/core/control.c31
-rw-r--r--sound/core/device.c6
-rw-r--r--sound/core/hwdep.c1
-rw-r--r--sound/core/info.c178
-rw-r--r--sound/core/info_oss.c3
-rw-r--r--sound/core/init.c78
-rw-r--r--sound/core/isadma.c6
-rw-r--r--sound/core/memory.c5
-rw-r--r--sound/core/misc.c6
-rw-r--r--sound/core/oss/mixer_oss.c2
-rw-r--r--sound/core/oss/pcm_oss.c529
-rw-r--r--sound/core/pcm.c90
-rw-r--r--sound/core/pcm_compat.c4
-rw-r--r--sound/core/pcm_lib.c725
-rw-r--r--sound/core/pcm_memory.c14
-rw-r--r--sound/core/pcm_misc.c24
-rw-r--r--sound/core/pcm_native.c113
-rw-r--r--sound/core/rawmidi.c3
-rw-r--r--sound/core/seq/oss/seq_oss.c1
-rw-r--r--sound/core/seq/seq.c22
-rw-r--r--sound/core/seq/seq_clientmgr.c12
-rw-r--r--sound/core/seq/seq_device.c3
-rw-r--r--sound/core/seq/seq_dummy.c6
-rw-r--r--sound/core/seq/seq_info.c11
-rw-r--r--sound/core/seq/seq_lock.c2
-rw-r--r--sound/core/seq/seq_memory.c3
-rw-r--r--sound/core/seq/seq_midi.c11
-rw-r--r--sound/core/seq/seq_ports.c5
-rw-r--r--sound/core/seq/seq_virmidi.c4
-rw-r--r--sound/core/sound.c109
-rw-r--r--sound/core/sound_oss.c9
-rw-r--r--sound/core/timer.c6
-rw-r--r--sound/drivers/dummy.c4
-rw-r--r--sound/drivers/mpu401/mpu401.c4
-rw-r--r--sound/drivers/mpu401/mpu401_uart.c186
-rw-r--r--sound/drivers/mtpav.c14
-rw-r--r--sound/drivers/opl3/opl3_lib.c19
-rw-r--r--sound/drivers/opl3/opl3_oss.c3
-rw-r--r--sound/drivers/opl3/opl3_seq.c4
-rw-r--r--sound/drivers/opl3/opl3_synth.c4
-rw-r--r--sound/drivers/opl4/opl4_lib.c12
-rw-r--r--sound/drivers/opl4/opl4_seq.c4
-rw-r--r--sound/drivers/serial-u16550.c4
-rw-r--r--sound/drivers/virmidi.c4
-rw-r--r--sound/drivers/vx/vx_core.c32
-rw-r--r--sound/drivers/vx/vx_hwdep.c3
-rw-r--r--sound/i2c/i2c.c17
-rw-r--r--sound/i2c/l3/uda1341.c4
-rw-r--r--sound/isa/gus/gus_irq.c2
-rw-r--r--sound/isa/gus/gus_mem.c6
-rw-r--r--sound/isa/gus/gus_synth.c4
-rw-r--r--sound/isa/gus/interwave.c4
-rw-r--r--sound/isa/opl3sa2.c12
-rw-r--r--sound/isa/opti9xx/miro.c2
-rw-r--r--sound/isa/sb/emu8000.c22
-rw-r--r--sound/isa/sb/emu8000_patch.c2
-rw-r--r--sound/isa/sb/sb16.c2
-rw-r--r--sound/isa/sb/sb16_csp.c2
-rw-r--r--sound/isa/sb/sb8_midi.c20
-rw-r--r--sound/isa/sscape.c3
-rw-r--r--sound/isa/wavefront/wavefront.c2
-rw-r--r--sound/oss/Kconfig4
-rw-r--r--sound/pci/Kconfig9
-rw-r--r--sound/pci/ac97/ac97_codec.c61
-rw-r--r--sound/pci/ac97/ac97_patch.c19
-rw-r--r--sound/pci/ac97/ac97_pcm.c10
-rw-r--r--sound/pci/ac97/ac97_proc.c5
-rw-r--r--sound/pci/ac97/ak4531_codec.c2
-rw-r--r--sound/pci/ad1889.c2
-rw-r--r--sound/pci/ali5451/ali5451.c4
-rw-r--r--sound/pci/als4000.c4
-rw-r--r--sound/pci/atiixp.c2
-rw-r--r--sound/pci/atiixp_modem.c2
-rw-r--r--sound/pci/au88x0/au88x0.c12
-rw-r--r--sound/pci/au88x0/au88x0_mpu401.c11
-rw-r--r--sound/pci/au88x0/au88x0_xtalk.c29
-rw-r--r--sound/pci/azt3328.c234
-rw-r--r--sound/pci/azt3328.h36
-rw-r--r--sound/pci/bt87x.c8
-rw-r--r--sound/pci/ca0106/ca0106.h4
-rw-r--r--sound/pci/ca0106/ca0106_main.c57
-rw-r--r--sound/pci/ca0106/ca0106_mixer.c181
-rw-r--r--sound/pci/ca0106/ca0106_proc.c17
-rw-r--r--sound/pci/cmipci.c10
-rw-r--r--sound/pci/cs4281.c16
-rw-r--r--sound/pci/cs46xx/cs46xx.c4
-rw-r--r--sound/pci/cs46xx/cs46xx_lib.c5
-rw-r--r--sound/pci/cs46xx/dsp_spos.c7
-rw-r--r--sound/pci/cs46xx/dsp_spos_scb_lib.c1
-rw-r--r--sound/pci/cs5535audio/Makefile4
-rw-r--r--sound/pci/cs5535audio/cs5535audio.c41
-rw-r--r--sound/pci/cs5535audio/cs5535audio.h8
-rw-r--r--sound/pci/cs5535audio/cs5535audio_pcm.c24
-rw-r--r--sound/pci/cs5535audio/cs5535audio_pm.c123
-rw-r--r--sound/pci/emu10k1/emu10k1.c8
-rw-r--r--sound/pci/emu10k1/emu10k1_main.c69
-rw-r--r--sound/pci/emu10k1/emu10k1x.c3
-rw-r--r--sound/pci/emu10k1/emumixer.c54
-rw-r--r--sound/pci/emu10k1/emuproc.c27
-rw-r--r--sound/pci/emu10k1/io.c4
-rw-r--r--sound/pci/emu10k1/memory.c8
-rw-r--r--sound/pci/emu10k1/p17v.h111
-rw-r--r--sound/pci/emu10k1/tina2.h8
-rw-r--r--sound/pci/emu10k1/voice.c4
-rw-r--r--sound/pci/ens1370.c2
-rw-r--r--sound/pci/es1938.c3
-rw-r--r--sound/pci/es1968.c5
-rw-r--r--sound/pci/fm801.c5
-rw-r--r--sound/pci/hda/Makefile2
-rw-r--r--sound/pci/hda/hda_codec.c41
-rw-r--r--sound/pci/hda/hda_intel.c20
-rw-r--r--sound/pci/hda/hda_patch.h3
-rw-r--r--sound/pci/hda/hda_proc.c6
-rw-r--r--sound/pci/hda/patch_analog.c61
-rw-r--r--sound/pci/hda/patch_atihdmi.c165
-rw-r--r--sound/pci/hda/patch_realtek.c30
-rw-r--r--sound/pci/hda/patch_sigmatel.c82
-rw-r--r--sound/pci/ice1712/aureon.c26
-rw-r--r--sound/pci/ice1712/aureon.h1
-rw-r--r--sound/pci/ice1712/ews.c3
-rw-r--r--sound/pci/ice1712/ice1712.c43
-rw-r--r--sound/pci/ice1712/ice1712.h5
-rw-r--r--sound/pci/ice1712/ice1724.c5
-rw-r--r--sound/pci/ice1712/pontis.c8
-rw-r--r--sound/pci/intel8x0.c10
-rw-r--r--sound/pci/intel8x0m.c4
-rw-r--r--sound/pci/korg1212/korg1212.c2
-rw-r--r--sound/pci/maestro3.c3
-rw-r--r--sound/pci/mixart/mixart.c1
-rw-r--r--sound/pci/pcxhr/pcxhr.c4
-rw-r--r--sound/pci/riptide/riptide.c6
-rw-r--r--sound/pci/rme32.c14
-rw-r--r--sound/pci/rme96.c44
-rw-r--r--sound/pci/rme9652/hdsp.c7
-rw-r--r--sound/pci/rme9652/hdspm.c2
-rw-r--r--sound/pci/rme9652/rme9652.c4
-rw-r--r--sound/pci/sonicvibes.c8
-rw-r--r--sound/pci/trident/trident.c3
-rw-r--r--sound/pci/trident/trident_main.c22
-rw-r--r--sound/pci/trident/trident_memory.c3
-rw-r--r--sound/pci/trident/trident_synth.c4
-rw-r--r--sound/pci/via82xx.c12
-rw-r--r--sound/pci/via82xx_modem.c2
-rw-r--r--sound/pci/ymfpci/ymfpci.c3
-rw-r--r--sound/pci/ymfpci/ymfpci_main.c2
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf_core.c2
-rw-r--r--sound/pcmcia/vx/vxp_ops.c2
-rw-r--r--sound/pcmcia/vx/vxpocket.c2
-rw-r--r--sound/ppc/Makefile2
-rw-r--r--sound/ppc/pmac.c44
-rw-r--r--sound/ppc/pmac.h3
-rw-r--r--sound/ppc/powermac.c21
-rw-r--r--sound/ppc/toonie.c378
-rw-r--r--sound/sparc/amd7930.c8
-rw-r--r--sound/sparc/cs4231.c13
-rw-r--r--sound/sparc/dbri.c12
-rw-r--r--sound/synth/emux/emux.c12
-rw-r--r--sound/synth/emux/emux_proc.c1
-rw-r--r--sound/synth/emux/emux_seq.c3
-rw-r--r--sound/synth/emux/emux_synth.c5
-rw-r--r--sound/synth/emux/soundfont.c6
-rw-r--r--sound/usb/usbaudio.c15
-rw-r--r--sound/usb/usbaudio.h7
-rw-r--r--sound/usb/usbmidi.c202
-rw-r--r--sound/usb/usbmixer.c70
-rw-r--r--sound/usb/usx2y/usx2yhwdeppcm.c2
202 files changed, 10031 insertions, 2156 deletions
diff --git a/sound/Kconfig b/sound/Kconfig
index b65ee4701f98..e0d791a98452 100644
--- a/sound/Kconfig
+++ b/sound/Kconfig
@@ -58,6 +58,8 @@ source "sound/pci/Kconfig"
58 58
59source "sound/ppc/Kconfig" 59source "sound/ppc/Kconfig"
60 60
61source "sound/aoa/Kconfig"
62
61source "sound/arm/Kconfig" 63source "sound/arm/Kconfig"
62 64
63source "sound/mips/Kconfig" 65source "sound/mips/Kconfig"
diff --git a/sound/Makefile b/sound/Makefile
index f352bb235968..a682ea30f0c9 100644
--- a/sound/Makefile
+++ b/sound/Makefile
@@ -4,7 +4,7 @@
4obj-$(CONFIG_SOUND) += soundcore.o 4obj-$(CONFIG_SOUND) += soundcore.o
5obj-$(CONFIG_SOUND_PRIME) += oss/ 5obj-$(CONFIG_SOUND_PRIME) += oss/
6obj-$(CONFIG_DMASOUND) += oss/ 6obj-$(CONFIG_DMASOUND) += oss/
7obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ synth/ usb/ sparc/ parisc/ pcmcia/ mips/ 7obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ synth/ usb/ sparc/ parisc/ pcmcia/ mips/ aoa/
8 8
9ifeq ($(CONFIG_SND),y) 9ifeq ($(CONFIG_SND),y)
10 obj-y += last.o 10 obj-y += last.o
diff --git a/sound/aoa/Kconfig b/sound/aoa/Kconfig
new file mode 100644
index 000000000000..a85194fe0b06
--- /dev/null
+++ b/sound/aoa/Kconfig
@@ -0,0 +1,17 @@
1menu "Apple Onboard Audio driver"
2 depends on SND!=n && PPC
3
4config SND_AOA
5 tristate "Apple Onboard Audio driver"
6 depends on SOUND && SND_PCM
7 ---help---
8 This option enables the new driver for the various
9 Apple Onboard Audio components.
10
11source "sound/aoa/fabrics/Kconfig"
12
13source "sound/aoa/codecs/Kconfig"
14
15source "sound/aoa/soundbus/Kconfig"
16
17endmenu
diff --git a/sound/aoa/Makefile b/sound/aoa/Makefile
new file mode 100644
index 000000000000..d8de3e7df48d
--- /dev/null
+++ b/sound/aoa/Makefile
@@ -0,0 +1,4 @@
1obj-$(CONFIG_SND_AOA) += core/
2obj-$(CONFIG_SND_AOA) += codecs/
3obj-$(CONFIG_SND_AOA) += fabrics/
4obj-$(CONFIG_SND_AOA_SOUNDBUS) += soundbus/
diff --git a/sound/aoa/aoa-gpio.h b/sound/aoa/aoa-gpio.h
new file mode 100644
index 000000000000..3a61f3115573
--- /dev/null
+++ b/sound/aoa/aoa-gpio.h
@@ -0,0 +1,81 @@
1/*
2 * Apple Onboard Audio GPIO definitions
3 *
4 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
5 *
6 * GPL v2, can be found in COPYING.
7 */
8
9#ifndef __AOA_GPIO_H
10#define __AOA_GPIO_H
11#include <linux/workqueue.h>
12#include <linux/mutex.h>
13#include <asm/prom.h>
14
15typedef void (*notify_func_t)(void *data);
16
17enum notify_type {
18 AOA_NOTIFY_HEADPHONE,
19 AOA_NOTIFY_LINE_IN,
20 AOA_NOTIFY_LINE_OUT,
21};
22
23struct gpio_runtime;
24struct gpio_methods {
25 /* for initialisation/de-initialisation of the GPIO layer */
26 void (*init)(struct gpio_runtime *rt);
27 void (*exit)(struct gpio_runtime *rt);
28
29 /* turn off headphone, speakers, lineout */
30 void (*all_amps_off)(struct gpio_runtime *rt);
31 /* turn headphone, speakers, lineout back to previous setting */
32 void (*all_amps_restore)(struct gpio_runtime *rt);
33
34 void (*set_headphone)(struct gpio_runtime *rt, int on);
35 void (*set_speakers)(struct gpio_runtime *rt, int on);
36 void (*set_lineout)(struct gpio_runtime *rt, int on);
37
38 int (*get_headphone)(struct gpio_runtime *rt);
39 int (*get_speakers)(struct gpio_runtime *rt);
40 int (*get_lineout)(struct gpio_runtime *rt);
41
42 void (*set_hw_reset)(struct gpio_runtime *rt, int on);
43
44 /* use this to be notified of any events. The notification
45 * function is passed the data, and is called in process
46 * context by the use of schedule_work.
47 * The interface for it is that setting a function to NULL
48 * removes it, and they return 0 if the operation succeeded,
49 * and -EBUSY if the notification is already assigned by
50 * someone else. */
51 int (*set_notify)(struct gpio_runtime *rt,
52 enum notify_type type,
53 notify_func_t notify,
54 void *data);
55 /* returns 0 if not plugged in, 1 if plugged in
56 * or a negative error code */
57 int (*get_detect)(struct gpio_runtime *rt,
58 enum notify_type type);
59};
60
61struct gpio_notification {
62 notify_func_t notify;
63 void *data;
64 void *gpio_private;
65 struct work_struct work;
66 struct mutex mutex;
67};
68
69struct gpio_runtime {
70 /* to be assigned by fabric */
71 struct device_node *node;
72 /* since everyone needs this pointer anyway... */
73 struct gpio_methods *methods;
74 /* to be used by the gpio implementation */
75 int implementation_private;
76 struct gpio_notification headphone_notify;
77 struct gpio_notification line_in_notify;
78 struct gpio_notification line_out_notify;
79};
80
81#endif /* __AOA_GPIO_H */
diff --git a/sound/aoa/aoa.h b/sound/aoa/aoa.h
new file mode 100644
index 000000000000..378ef1e9879b
--- /dev/null
+++ b/sound/aoa/aoa.h
@@ -0,0 +1,131 @@
1/*
2 * Apple Onboard Audio definitions
3 *
4 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
5 *
6 * GPL v2, can be found in COPYING.
7 */
8
9#ifndef __AOA_H
10#define __AOA_H
11#include <asm/prom.h>
12#include <linux/module.h>
13/* So apparently there's a reason for requiring driver.h to be included first! */
14#include <sound/driver.h>
15#include <sound/core.h>
16#include <sound/asound.h>
17#include <sound/control.h>
18#include "aoa-gpio.h"
19#include "soundbus/soundbus.h"
20
21#define MAX_CODEC_NAME_LEN 32
22
23struct aoa_codec {
24 char name[MAX_CODEC_NAME_LEN];
25
26 struct module *owner;
27
28 /* called when the fabric wants to init this codec.
29 * Do alsa card manipulations from here. */
30 int (*init)(struct aoa_codec *codec);
31
32 /* called when the fabric is done with the codec.
33 * The alsa card will be cleaned up so don't bother. */
34 void (*exit)(struct aoa_codec *codec);
35
36 /* May be NULL, but can be used by the fabric.
37 * Refcounting is the codec driver's responsibility */
38 struct device_node *node;
39
40 /* assigned by fabric before init() is called, points
41 * to the soundbus device. Cannot be NULL. */
42 struct soundbus_dev *soundbus_dev;
43
44 /* assigned by the fabric before init() is called, points
45 * to the fabric's gpio runtime record for the relevant
46 * device. */
47 struct gpio_runtime *gpio;
48
49 /* assigned by the fabric before init() is called, contains
50 * a codec specific bitmask of what outputs and inputs are
51 * actually connected */
52 u32 connected;
53
54 /* data the fabric can associate with this structure */
55 void *fabric_data;
56
57 /* private! */
58 struct list_head list;
59 struct aoa_fabric *fabric;
60};
61
62/* return 0 on success */
63extern int
64aoa_codec_register(struct aoa_codec *codec);
65extern void
66aoa_codec_unregister(struct aoa_codec *codec);
67
68#define MAX_LAYOUT_NAME_LEN 32
69
70struct aoa_fabric {
71 char name[MAX_LAYOUT_NAME_LEN];
72
73 struct module *owner;
74
75 /* once codecs register, they are passed here after.
76 * They are of course not initialised, since the
77 * fabric is responsible for initialising some fields
78 * in the codec structure! */
79 int (*found_codec)(struct aoa_codec *codec);
80 /* called for each codec when it is removed,
81 * also in the case that aoa_fabric_unregister
82 * is called and all codecs are removed
83 * from this fabric.
84 * Also called if found_codec returned 0 but
85 * the codec couldn't initialise. */
86 void (*remove_codec)(struct aoa_codec *codec);
87 /* If found_codec returned 0, and the codec
88 * could be initialised, this is called. */
89 void (*attached_codec)(struct aoa_codec *codec);
90};
91
92/* return 0 on success, -EEXIST if another fabric is
93 * registered, -EALREADY if the same fabric is registered.
94 * Passing NULL can be used to test for the presence
95 * of another fabric, if -EALREADY is returned there is
96 * no other fabric present.
97 * In the case that the function returns -EALREADY
98 * and the fabric passed is not NULL, all codecs
99 * that are not assigned yet are passed to the fabric
100 * again for reconsideration. */
101extern int
102aoa_fabric_register(struct aoa_fabric *fabric);
103
104/* it is vital to call this when the fabric exits!
105 * When calling, the remove_codec will be called
106 * for all codecs, unless it is NULL. */
107extern void
108aoa_fabric_unregister(struct aoa_fabric *fabric);
109
110/* if for some reason you want to get rid of a codec
111 * before the fabric is removed, use this.
112 * Note that remove_codec is called for it! */
113extern void
114aoa_fabric_unlink_codec(struct aoa_codec *codec);
115
116/* alsa help methods */
117struct aoa_card {
118 struct snd_card *alsa_card;
119};
120
121extern int aoa_snd_device_new(snd_device_type_t type,
122 void * device_data, struct snd_device_ops * ops);
123extern struct snd_card *aoa_get_card(void);
124extern int aoa_snd_ctl_add(struct snd_kcontrol* control);
125
126/* GPIO stuff */
127extern struct gpio_methods *pmf_gpio_methods;
128extern struct gpio_methods *ftr_gpio_methods;
129/* extern struct gpio_methods *map_gpio_methods; */
130
131#endif /* __AOA_H */
diff --git a/sound/aoa/codecs/Kconfig b/sound/aoa/codecs/Kconfig
new file mode 100644
index 000000000000..90cf58f68630
--- /dev/null
+++ b/sound/aoa/codecs/Kconfig
@@ -0,0 +1,32 @@
1config SND_AOA_ONYX
2 tristate "support Onyx chip"
3 depends on SND_AOA
4 ---help---
5 This option enables support for the Onyx (pcm3052)
6 codec chip found in the latest Apple machines
7 (most of those with digital audio output).
8
9#config SND_AOA_TOPAZ
10# tristate "support Topaz chips"
11# depends on SND_AOA
12# ---help---
13# This option enables support for the Topaz (CS84xx)
14# codec chips found in the latest Apple machines,
15# these chips do the digital input and output on
16# some PowerMacs.
17
18config SND_AOA_TAS
19 tristate "support TAS chips"
20 depends on SND_AOA
21 ---help---
22 This option enables support for the tas chips
23 found in a lot of Apple Machines, especially
24 iBooks and PowerBooks without digital.
25
26config SND_AOA_TOONIE
27 tristate "support Toonie chip"
28 depends on SND_AOA
29 ---help---
30 This option enables support for the toonie codec
31 found in the Mac Mini. If you have a Mac Mini and
32 want to hear sound, select this option.
diff --git a/sound/aoa/codecs/Makefile b/sound/aoa/codecs/Makefile
new file mode 100644
index 000000000000..31cbe68fd42f
--- /dev/null
+++ b/sound/aoa/codecs/Makefile
@@ -0,0 +1,3 @@
1obj-$(CONFIG_SND_AOA_ONYX) += snd-aoa-codec-onyx.o
2obj-$(CONFIG_SND_AOA_TAS) += snd-aoa-codec-tas.o
3obj-$(CONFIG_SND_AOA_TOONIE) += snd-aoa-codec-toonie.o
diff --git a/sound/aoa/codecs/snd-aoa-codec-onyx.c b/sound/aoa/codecs/snd-aoa-codec-onyx.c
new file mode 100644
index 000000000000..0b7650788f1f
--- /dev/null
+++ b/sound/aoa/codecs/snd-aoa-codec-onyx.c
@@ -0,0 +1,1113 @@
1/*
2 * Apple Onboard Audio driver for Onyx codec
3 *
4 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
5 *
6 * GPL v2, can be found in COPYING.
7 *
8 *
9 * This is a driver for the pcm3052 codec chip (codenamed Onyx)
10 * that is present in newer Apple hardware (with digital output).
11 *
12 * The Onyx codec has the following connections (listed by the bit
13 * to be used in aoa_codec.connected):
14 * 0: analog output
15 * 1: digital output
16 * 2: line input
17 * 3: microphone input
18 * Note that even though I know of no machine that has for example
19 * the digital output connected but not the analog, I have handled
20 * all the different cases in the code so that this driver may serve
21 * as a good example of what to do.
22 *
23 * NOTE: This driver assumes that there's at most one chip to be
24 * used with one alsa card, in form of creating all kinds
25 * of mixer elements without regard for their existence.
26 * But snd-aoa assumes that there's at most one card, so
27 * this means you can only have one onyx on a system. This
28 * should probably be fixed by changing the assumption of
29 * having just a single card on a system, and making the
30 * 'card' pointer accessible to anyone who needs it instead
31 * of hiding it in the aoa_snd_* functions...
32 *
33 */
34#include <linux/delay.h>
35#include <linux/module.h>
36MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
37MODULE_LICENSE("GPL");
38MODULE_DESCRIPTION("pcm3052 (onyx) codec driver for snd-aoa");
39
40#include "snd-aoa-codec-onyx.h"
41#include "../aoa.h"
42#include "../soundbus/soundbus.h"
43
44
45#define PFX "snd-aoa-codec-onyx: "
46
47struct onyx {
48 /* cache registers 65 to 80, they are write-only! */
49 u8 cache[16];
50 struct i2c_client i2c;
51 struct aoa_codec codec;
52 u32 initialised:1,
53 spdif_locked:1,
54 analog_locked:1,
55 original_mute:2;
56 int open_count;
57 struct codec_info *codec_info;
58
59 /* mutex serializes concurrent access to the device
60 * and this structure.
61 */
62 struct mutex mutex;
63};
64#define codec_to_onyx(c) container_of(c, struct onyx, codec)
65
66/* both return 0 if all ok, else on error */
67static int onyx_read_register(struct onyx *onyx, u8 reg, u8 *value)
68{
69 s32 v;
70
71 if (reg != ONYX_REG_CONTROL) {
72 *value = onyx->cache[reg-FIRSTREGISTER];
73 return 0;
74 }
75 v = i2c_smbus_read_byte_data(&onyx->i2c, reg);
76 if (v < 0)
77 return -1;
78 *value = (u8)v;
79 onyx->cache[ONYX_REG_CONTROL-FIRSTREGISTER] = *value;
80 return 0;
81}
82
83static int onyx_write_register(struct onyx *onyx, u8 reg, u8 value)
84{
85 int result;
86
87 result = i2c_smbus_write_byte_data(&onyx->i2c, reg, value);
88 if (!result)
89 onyx->cache[reg-FIRSTREGISTER] = value;
90 return result;
91}
92
93/* alsa stuff */
94
95static int onyx_dev_register(struct snd_device *dev)
96{
97 return 0;
98}
99
100static struct snd_device_ops ops = {
101 .dev_register = onyx_dev_register,
102};
103
104/* this is necessary because most alsa mixer programs
105 * can't properly handle the negative range */
106#define VOLUME_RANGE_SHIFT 128
107
108static int onyx_snd_vol_info(struct snd_kcontrol *kcontrol,
109 struct snd_ctl_elem_info *uinfo)
110{
111 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
112 uinfo->count = 2;
113 uinfo->value.integer.min = -128 + VOLUME_RANGE_SHIFT;
114 uinfo->value.integer.max = -1 + VOLUME_RANGE_SHIFT;
115 return 0;
116}
117
118static int onyx_snd_vol_get(struct snd_kcontrol *kcontrol,
119 struct snd_ctl_elem_value *ucontrol)
120{
121 struct onyx *onyx = snd_kcontrol_chip(kcontrol);
122 s8 l, r;
123
124 mutex_lock(&onyx->mutex);
125 onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_LEFT, &l);
126 onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT, &r);
127 mutex_unlock(&onyx->mutex);
128
129 ucontrol->value.integer.value[0] = l + VOLUME_RANGE_SHIFT;
130 ucontrol->value.integer.value[1] = r + VOLUME_RANGE_SHIFT;
131
132 return 0;
133}
134
135static int onyx_snd_vol_put(struct snd_kcontrol *kcontrol,
136 struct snd_ctl_elem_value *ucontrol)
137{
138 struct onyx *onyx = snd_kcontrol_chip(kcontrol);
139 s8 l, r;
140
141 mutex_lock(&onyx->mutex);
142 onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_LEFT, &l);
143 onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT, &r);
144
145 if (l + VOLUME_RANGE_SHIFT == ucontrol->value.integer.value[0] &&
146 r + VOLUME_RANGE_SHIFT == ucontrol->value.integer.value[1]) {
147 mutex_unlock(&onyx->mutex);
148 return 0;
149 }
150
151 onyx_write_register(onyx, ONYX_REG_DAC_ATTEN_LEFT,
152 ucontrol->value.integer.value[0]
153 - VOLUME_RANGE_SHIFT);
154 onyx_write_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT,
155 ucontrol->value.integer.value[1]
156 - VOLUME_RANGE_SHIFT);
157 mutex_unlock(&onyx->mutex);
158
159 return 1;
160}
161
162static struct snd_kcontrol_new volume_control = {
163 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
164 .name = "Master Playback Volume",
165 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
166 .info = onyx_snd_vol_info,
167 .get = onyx_snd_vol_get,
168 .put = onyx_snd_vol_put,
169};
170
171/* like above, this is necessary because a lot
172 * of alsa mixer programs don't handle ranges
173 * that don't start at 0 properly.
174 * even alsamixer is one of them... */
175#define INPUTGAIN_RANGE_SHIFT (-3)
176
177static int onyx_snd_inputgain_info(struct snd_kcontrol *kcontrol,
178 struct snd_ctl_elem_info *uinfo)
179{
180 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
181 uinfo->count = 1;
182 uinfo->value.integer.min = 3 + INPUTGAIN_RANGE_SHIFT;
183 uinfo->value.integer.max = 28 + INPUTGAIN_RANGE_SHIFT;
184 return 0;
185}
186
187static int onyx_snd_inputgain_get(struct snd_kcontrol *kcontrol,
188 struct snd_ctl_elem_value *ucontrol)
189{
190 struct onyx *onyx = snd_kcontrol_chip(kcontrol);
191 u8 ig;
192
193 mutex_lock(&onyx->mutex);
194 onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &ig);
195 mutex_unlock(&onyx->mutex);
196
197 ucontrol->value.integer.value[0] =
198 (ig & ONYX_ADC_PGA_GAIN_MASK) + INPUTGAIN_RANGE_SHIFT;
199
200 return 0;
201}
202
203static int onyx_snd_inputgain_put(struct snd_kcontrol *kcontrol,
204 struct snd_ctl_elem_value *ucontrol)
205{
206 struct onyx *onyx = snd_kcontrol_chip(kcontrol);
207 u8 v, n;
208
209 mutex_lock(&onyx->mutex);
210 onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v);
211 n = v;
212 n &= ~ONYX_ADC_PGA_GAIN_MASK;
213 n |= (ucontrol->value.integer.value[0] - INPUTGAIN_RANGE_SHIFT)
214 & ONYX_ADC_PGA_GAIN_MASK;
215 onyx_write_register(onyx, ONYX_REG_ADC_CONTROL, n);
216 mutex_unlock(&onyx->mutex);
217
218 return n != v;
219}
220
221static struct snd_kcontrol_new inputgain_control = {
222 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
223 .name = "Master Capture Volume",
224 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
225 .info = onyx_snd_inputgain_info,
226 .get = onyx_snd_inputgain_get,
227 .put = onyx_snd_inputgain_put,
228};
229
230static int onyx_snd_capture_source_info(struct snd_kcontrol *kcontrol,
231 struct snd_ctl_elem_info *uinfo)
232{
233 static char *texts[] = { "Line-In", "Microphone" };
234
235 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
236 uinfo->count = 1;
237 uinfo->value.enumerated.items = 2;
238 if (uinfo->value.enumerated.item > 1)
239 uinfo->value.enumerated.item = 1;
240 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
241 return 0;
242}
243
244static int onyx_snd_capture_source_get(struct snd_kcontrol *kcontrol,
245 struct snd_ctl_elem_value *ucontrol)
246{
247 struct onyx *onyx = snd_kcontrol_chip(kcontrol);
248 s8 v;
249
250 mutex_lock(&onyx->mutex);
251 onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v);
252 mutex_unlock(&onyx->mutex);
253
254 ucontrol->value.enumerated.item[0] = !!(v&ONYX_ADC_INPUT_MIC);
255
256 return 0;
257}
258
259static void onyx_set_capture_source(struct onyx *onyx, int mic)
260{
261 s8 v;
262
263 mutex_lock(&onyx->mutex);
264 onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v);
265 v &= ~ONYX_ADC_INPUT_MIC;
266 if (mic)
267 v |= ONYX_ADC_INPUT_MIC;
268 onyx_write_register(onyx, ONYX_REG_ADC_CONTROL, v);
269 mutex_unlock(&onyx->mutex);
270}
271
272static int onyx_snd_capture_source_put(struct snd_kcontrol *kcontrol,
273 struct snd_ctl_elem_value *ucontrol)
274{
275 onyx_set_capture_source(snd_kcontrol_chip(kcontrol),
276 ucontrol->value.enumerated.item[0]);
277 return 1;
278}
279
280static struct snd_kcontrol_new capture_source_control = {
281 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
282 /* If we name this 'Input Source', it properly shows up in
283 * alsamixer as a selection, * but it's shown under the
284 * 'Playback' category.
285 * If I name it 'Capture Source', it shows up in strange
286 * ways (two bools of which one can be selected at a
287 * time) but at least it's shown in the 'Capture'
288 * category.
289 * I was told that this was due to backward compatibility,
290 * but I don't understand then why the mangling is *not*
291 * done when I name it "Input Source".....
292 */
293 .name = "Capture Source",
294 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
295 .info = onyx_snd_capture_source_info,
296 .get = onyx_snd_capture_source_get,
297 .put = onyx_snd_capture_source_put,
298};
299
300static int onyx_snd_mute_info(struct snd_kcontrol *kcontrol,
301 struct snd_ctl_elem_info *uinfo)
302{
303 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
304 uinfo->count = 2;
305 uinfo->value.integer.min = 0;
306 uinfo->value.integer.max = 1;
307 return 0;
308}
309
310static int onyx_snd_mute_get(struct snd_kcontrol *kcontrol,
311 struct snd_ctl_elem_value *ucontrol)
312{
313 struct onyx *onyx = snd_kcontrol_chip(kcontrol);
314 u8 c;
315
316 mutex_lock(&onyx->mutex);
317 onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &c);
318 mutex_unlock(&onyx->mutex);
319
320 ucontrol->value.integer.value[0] = !(c & ONYX_MUTE_LEFT);
321 ucontrol->value.integer.value[1] = !(c & ONYX_MUTE_RIGHT);
322
323 return 0;
324}
325
326static int onyx_snd_mute_put(struct snd_kcontrol *kcontrol,
327 struct snd_ctl_elem_value *ucontrol)
328{
329 struct onyx *onyx = snd_kcontrol_chip(kcontrol);
330 u8 v = 0, c = 0;
331 int err = -EBUSY;
332
333 mutex_lock(&onyx->mutex);
334 if (onyx->analog_locked)
335 goto out_unlock;
336
337 onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v);
338 c = v;
339 c &= ~(ONYX_MUTE_RIGHT | ONYX_MUTE_LEFT);
340 if (!ucontrol->value.integer.value[0])
341 c |= ONYX_MUTE_LEFT;
342 if (!ucontrol->value.integer.value[1])
343 c |= ONYX_MUTE_RIGHT;
344 err = onyx_write_register(onyx, ONYX_REG_DAC_CONTROL, c);
345
346 out_unlock:
347 mutex_unlock(&onyx->mutex);
348
349 return !err ? (v != c) : err;
350}
351
352static struct snd_kcontrol_new mute_control = {
353 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
354 .name = "Master Playback Switch",
355 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
356 .info = onyx_snd_mute_info,
357 .get = onyx_snd_mute_get,
358 .put = onyx_snd_mute_put,
359};
360
361
362static int onyx_snd_single_bit_info(struct snd_kcontrol *kcontrol,
363 struct snd_ctl_elem_info *uinfo)
364{
365 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
366 uinfo->count = 1;
367 uinfo->value.integer.min = 0;
368 uinfo->value.integer.max = 1;
369 return 0;
370}
371
372#define FLAG_POLARITY_INVERT 1
373#define FLAG_SPDIFLOCK 2
374
375static int onyx_snd_single_bit_get(struct snd_kcontrol *kcontrol,
376 struct snd_ctl_elem_value *ucontrol)
377{
378 struct onyx *onyx = snd_kcontrol_chip(kcontrol);
379 u8 c;
380 long int pv = kcontrol->private_value;
381 u8 polarity = (pv >> 16) & FLAG_POLARITY_INVERT;
382 u8 address = (pv >> 8) & 0xff;
383 u8 mask = pv & 0xff;
384
385 mutex_lock(&onyx->mutex);
386 onyx_read_register(onyx, address, &c);
387 mutex_unlock(&onyx->mutex);
388
389 ucontrol->value.integer.value[0] = !!(c & mask) ^ polarity;
390
391 return 0;
392}
393
394static int onyx_snd_single_bit_put(struct snd_kcontrol *kcontrol,
395 struct snd_ctl_elem_value *ucontrol)
396{
397 struct onyx *onyx = snd_kcontrol_chip(kcontrol);
398 u8 v = 0, c = 0;
399 int err;
400 long int pv = kcontrol->private_value;
401 u8 polarity = (pv >> 16) & FLAG_POLARITY_INVERT;
402 u8 spdiflock = (pv >> 16) & FLAG_SPDIFLOCK;
403 u8 address = (pv >> 8) & 0xff;
404 u8 mask = pv & 0xff;
405
406 mutex_lock(&onyx->mutex);
407 if (spdiflock && onyx->spdif_locked) {
408 /* even if alsamixer doesn't care.. */
409 err = -EBUSY;
410 goto out_unlock;
411 }
412 onyx_read_register(onyx, address, &v);
413 c = v;
414 c &= ~(mask);
415 if (!!ucontrol->value.integer.value[0] ^ polarity)
416 c |= mask;
417 err = onyx_write_register(onyx, address, c);
418
419 out_unlock:
420 mutex_unlock(&onyx->mutex);
421
422 return !err ? (v != c) : err;
423}
424
425#define SINGLE_BIT(n, type, description, address, mask, flags) \
426static struct snd_kcontrol_new n##_control = { \
427 .iface = SNDRV_CTL_ELEM_IFACE_##type, \
428 .name = description, \
429 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
430 .info = onyx_snd_single_bit_info, \
431 .get = onyx_snd_single_bit_get, \
432 .put = onyx_snd_single_bit_put, \
433 .private_value = (flags << 16) | (address << 8) | mask \
434}
435
436SINGLE_BIT(spdif,
437 MIXER,
438 SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH),
439 ONYX_REG_DIG_INFO4,
440 ONYX_SPDIF_ENABLE,
441 FLAG_SPDIFLOCK);
442SINGLE_BIT(ovr1,
443 MIXER,
444 "Oversampling Rate",
445 ONYX_REG_DAC_CONTROL,
446 ONYX_OVR1,
447 0);
448SINGLE_BIT(flt0,
449 MIXER,
450 "Fast Digital Filter Rolloff",
451 ONYX_REG_DAC_FILTER,
452 ONYX_ROLLOFF_FAST,
453 FLAG_POLARITY_INVERT);
454SINGLE_BIT(hpf,
455 MIXER,
456 "Highpass Filter",
457 ONYX_REG_ADC_HPF_BYPASS,
458 ONYX_HPF_DISABLE,
459 FLAG_POLARITY_INVERT);
460SINGLE_BIT(dm12,
461 MIXER,
462 "Digital De-Emphasis",
463 ONYX_REG_DAC_DEEMPH,
464 ONYX_DIGDEEMPH_CTRL,
465 0);
466
467static int onyx_spdif_info(struct snd_kcontrol *kcontrol,
468 struct snd_ctl_elem_info *uinfo)
469{
470 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
471 uinfo->count = 1;
472 return 0;
473}
474
475static int onyx_spdif_mask_get(struct snd_kcontrol *kcontrol,
476 struct snd_ctl_elem_value *ucontrol)
477{
478 /* datasheet page 30, all others are 0 */
479 ucontrol->value.iec958.status[0] = 0x3e;
480 ucontrol->value.iec958.status[1] = 0xff;
481
482 ucontrol->value.iec958.status[3] = 0x3f;
483 ucontrol->value.iec958.status[4] = 0x0f;
484
485 return 0;
486}
487
488static struct snd_kcontrol_new onyx_spdif_mask = {
489 .access = SNDRV_CTL_ELEM_ACCESS_READ,
490 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
491 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
492 .info = onyx_spdif_info,
493 .get = onyx_spdif_mask_get,
494};
495
496static int onyx_spdif_get(struct snd_kcontrol *kcontrol,
497 struct snd_ctl_elem_value *ucontrol)
498{
499 struct onyx *onyx = snd_kcontrol_chip(kcontrol);
500 u8 v;
501
502 mutex_lock(&onyx->mutex);
503 onyx_read_register(onyx, ONYX_REG_DIG_INFO1, &v);
504 ucontrol->value.iec958.status[0] = v & 0x3e;
505
506 onyx_read_register(onyx, ONYX_REG_DIG_INFO2, &v);
507 ucontrol->value.iec958.status[1] = v;
508
509 onyx_read_register(onyx, ONYX_REG_DIG_INFO3, &v);
510 ucontrol->value.iec958.status[3] = v & 0x3f;
511
512 onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v);
513 ucontrol->value.iec958.status[4] = v & 0x0f;
514 mutex_unlock(&onyx->mutex);
515
516 return 0;
517}
518
519static int onyx_spdif_put(struct snd_kcontrol *kcontrol,
520 struct snd_ctl_elem_value *ucontrol)
521{
522 struct onyx *onyx = snd_kcontrol_chip(kcontrol);
523 u8 v;
524
525 mutex_lock(&onyx->mutex);
526 onyx_read_register(onyx, ONYX_REG_DIG_INFO1, &v);
527 v = (v & ~0x3e) | (ucontrol->value.iec958.status[0] & 0x3e);
528 onyx_write_register(onyx, ONYX_REG_DIG_INFO1, v);
529
530 v = ucontrol->value.iec958.status[1];
531 onyx_write_register(onyx, ONYX_REG_DIG_INFO2, v);
532
533 onyx_read_register(onyx, ONYX_REG_DIG_INFO3, &v);
534 v = (v & ~0x3f) | (ucontrol->value.iec958.status[3] & 0x3f);
535 onyx_write_register(onyx, ONYX_REG_DIG_INFO3, v);
536
537 onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v);
538 v = (v & ~0x0f) | (ucontrol->value.iec958.status[4] & 0x0f);
539 onyx_write_register(onyx, ONYX_REG_DIG_INFO4, v);
540 mutex_unlock(&onyx->mutex);
541
542 return 1;
543}
544
545static struct snd_kcontrol_new onyx_spdif_ctrl = {
546 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
547 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
548 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
549 .info = onyx_spdif_info,
550 .get = onyx_spdif_get,
551 .put = onyx_spdif_put,
552};
553
554/* our registers */
555
556static u8 register_map[] = {
557 ONYX_REG_DAC_ATTEN_LEFT,
558 ONYX_REG_DAC_ATTEN_RIGHT,
559 ONYX_REG_CONTROL,
560 ONYX_REG_DAC_CONTROL,
561 ONYX_REG_DAC_DEEMPH,
562 ONYX_REG_DAC_FILTER,
563 ONYX_REG_DAC_OUTPHASE,
564 ONYX_REG_ADC_CONTROL,
565 ONYX_REG_ADC_HPF_BYPASS,
566 ONYX_REG_DIG_INFO1,
567 ONYX_REG_DIG_INFO2,
568 ONYX_REG_DIG_INFO3,
569 ONYX_REG_DIG_INFO4
570};
571
572static u8 initial_values[ARRAY_SIZE(register_map)] = {
573 0x80, 0x80, /* muted */
574 ONYX_MRST | ONYX_SRST, /* but handled specially! */
575 ONYX_MUTE_LEFT | ONYX_MUTE_RIGHT,
576 0, /* no deemphasis */
577 ONYX_DAC_FILTER_ALWAYS,
578 ONYX_OUTPHASE_INVERTED,
579 (-1 /*dB*/ + 8) & 0xF, /* line in selected, -1 dB gain*/
580 ONYX_ADC_HPF_ALWAYS,
581 (1<<2), /* pcm audio */
582 2, /* category: pcm coder */
583 0, /* sampling frequency 44.1 kHz, clock accuracy level II */
584 1 /* 24 bit depth */
585};
586
587/* reset registers of chip, either to initial or to previous values */
588static int onyx_register_init(struct onyx *onyx)
589{
590 int i;
591 u8 val;
592 u8 regs[sizeof(initial_values)];
593
594 if (!onyx->initialised) {
595 memcpy(regs, initial_values, sizeof(initial_values));
596 if (onyx_read_register(onyx, ONYX_REG_CONTROL, &val))
597 return -1;
598 val &= ~ONYX_SILICONVERSION;
599 val |= initial_values[3];
600 regs[3] = val;
601 } else {
602 for (i=0; i<sizeof(register_map); i++)
603 regs[i] = onyx->cache[register_map[i]-FIRSTREGISTER];
604 }
605
606 for (i=0; i<sizeof(register_map); i++) {
607 if (onyx_write_register(onyx, register_map[i], regs[i]))
608 return -1;
609 }
610 onyx->initialised = 1;
611 return 0;
612}
613
614static struct transfer_info onyx_transfers[] = {
615 /* this is first so we can skip it if no input is present...
616 * No hardware exists with that, but it's here as an example
617 * of what to do :) */
618 {
619 /* analog input */
620 .formats = SNDRV_PCM_FMTBIT_S8 |
621 SNDRV_PCM_FMTBIT_S16_BE |
622 SNDRV_PCM_FMTBIT_S24_BE,
623 .rates = SNDRV_PCM_RATE_8000_96000,
624 .transfer_in = 1,
625 .must_be_clock_source = 0,
626 .tag = 0,
627 },
628 {
629 /* if analog and digital are currently off, anything should go,
630 * so this entry describes everything we can do... */
631 .formats = SNDRV_PCM_FMTBIT_S8 |
632 SNDRV_PCM_FMTBIT_S16_BE |
633 SNDRV_PCM_FMTBIT_S24_BE
634#ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE
635 | SNDRV_PCM_FMTBIT_COMPRESSED_16BE
636#endif
637 ,
638 .rates = SNDRV_PCM_RATE_8000_96000,
639 .tag = 0,
640 },
641 {
642 /* analog output */
643 .formats = SNDRV_PCM_FMTBIT_S8 |
644 SNDRV_PCM_FMTBIT_S16_BE |
645 SNDRV_PCM_FMTBIT_S24_BE,
646 .rates = SNDRV_PCM_RATE_8000_96000,
647 .transfer_in = 0,
648 .must_be_clock_source = 0,
649 .tag = 1,
650 },
651 {
652 /* digital pcm output, also possible for analog out */
653 .formats = SNDRV_PCM_FMTBIT_S8 |
654 SNDRV_PCM_FMTBIT_S16_BE |
655 SNDRV_PCM_FMTBIT_S24_BE,
656 .rates = SNDRV_PCM_RATE_32000 |
657 SNDRV_PCM_RATE_44100 |
658 SNDRV_PCM_RATE_48000,
659 .transfer_in = 0,
660 .must_be_clock_source = 0,
661 .tag = 2,
662 },
663#ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE
664Once alsa gets supports for this kind of thing we can add it...
665 {
666 /* digital compressed output */
667 .formats = SNDRV_PCM_FMTBIT_COMPRESSED_16BE,
668 .rates = SNDRV_PCM_RATE_32000 |
669 SNDRV_PCM_RATE_44100 |
670 SNDRV_PCM_RATE_48000,
671 .tag = 2,
672 },
673#endif
674 {}
675};
676
677static int onyx_usable(struct codec_info_item *cii,
678 struct transfer_info *ti,
679 struct transfer_info *out)
680{
681 u8 v;
682 struct onyx *onyx = cii->codec_data;
683 int spdif_enabled, analog_enabled;
684
685 mutex_lock(&onyx->mutex);
686 onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v);
687 spdif_enabled = !!(v & ONYX_SPDIF_ENABLE);
688 onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v);
689 analog_enabled =
690 (v & (ONYX_MUTE_RIGHT|ONYX_MUTE_LEFT))
691 != (ONYX_MUTE_RIGHT|ONYX_MUTE_LEFT);
692 mutex_unlock(&onyx->mutex);
693
694 switch (ti->tag) {
695 case 0: return 1;
696 case 1: return analog_enabled;
697 case 2: return spdif_enabled;
698 }
699 return 1;
700}
701
702static int onyx_prepare(struct codec_info_item *cii,
703 struct bus_info *bi,
704 struct snd_pcm_substream *substream)
705{
706 u8 v;
707 struct onyx *onyx = cii->codec_data;
708 int err = -EBUSY;
709
710 mutex_lock(&onyx->mutex);
711
712#ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE
713 if (substream->runtime->format == SNDRV_PCM_FMTBIT_COMPRESSED_16BE) {
714 /* mute and lock analog output */
715 onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v);
716 if (onyx_write_register(onyx
717 ONYX_REG_DAC_CONTROL,
718 v | ONYX_MUTE_RIGHT | ONYX_MUTE_LEFT))
719 goto out_unlock;
720 onyx->analog_locked = 1;
721 err = 0;
722 goto out_unlock;
723 }
724#endif
725 switch (substream->runtime->rate) {
726 case 32000:
727 case 44100:
728 case 48000:
729 /* these rates are ok for all outputs */
730 /* FIXME: program spdif channel control bits here so that
731 * userspace doesn't have to if it only plays pcm! */
732 err = 0;
733 goto out_unlock;
734 default:
735 /* got some rate that the digital output can't do,
736 * so disable and lock it */
737 onyx_read_register(cii->codec_data, ONYX_REG_DIG_INFO4, &v);
738 if (onyx_write_register(onyx,
739 ONYX_REG_DIG_INFO4,
740 v & ~ONYX_SPDIF_ENABLE))
741 goto out_unlock;
742 onyx->spdif_locked = 1;
743 err = 0;
744 goto out_unlock;
745 }
746
747 out_unlock:
748 mutex_unlock(&onyx->mutex);
749
750 return err;
751}
752
753static int onyx_open(struct codec_info_item *cii,
754 struct snd_pcm_substream *substream)
755{
756 struct onyx *onyx = cii->codec_data;
757
758 mutex_lock(&onyx->mutex);
759 onyx->open_count++;
760 mutex_unlock(&onyx->mutex);
761
762 return 0;
763}
764
765static int onyx_close(struct codec_info_item *cii,
766 struct snd_pcm_substream *substream)
767{
768 struct onyx *onyx = cii->codec_data;
769
770 mutex_lock(&onyx->mutex);
771 onyx->open_count--;
772 if (!onyx->open_count)
773 onyx->spdif_locked = onyx->analog_locked = 0;
774 mutex_unlock(&onyx->mutex);
775
776 return 0;
777}
778
779static int onyx_switch_clock(struct codec_info_item *cii,
780 enum clock_switch what)
781{
782 struct onyx *onyx = cii->codec_data;
783
784 mutex_lock(&onyx->mutex);
785 /* this *MUST* be more elaborate later... */
786 switch (what) {
787 case CLOCK_SWITCH_PREPARE_SLAVE:
788 onyx->codec.gpio->methods->all_amps_off(onyx->codec.gpio);
789 break;
790 case CLOCK_SWITCH_SLAVE:
791 onyx->codec.gpio->methods->all_amps_restore(onyx->codec.gpio);
792 break;
793 default: /* silence warning */
794 break;
795 }
796 mutex_unlock(&onyx->mutex);
797
798 return 0;
799}
800
801#ifdef CONFIG_PM
802
803static int onyx_suspend(struct codec_info_item *cii, pm_message_t state)
804{
805 struct onyx *onyx = cii->codec_data;
806 u8 v;
807 int err = -ENXIO;
808
809 mutex_lock(&onyx->mutex);
810 if (onyx_read_register(onyx, ONYX_REG_CONTROL, &v))
811 goto out_unlock;
812 onyx_write_register(onyx, ONYX_REG_CONTROL, v | ONYX_ADPSV | ONYX_DAPSV);
813 /* Apple does a sleep here but the datasheet says to do it on resume */
814 err = 0;
815 out_unlock:
816 mutex_unlock(&onyx->mutex);
817
818 return err;
819}
820
821static int onyx_resume(struct codec_info_item *cii)
822{
823 struct onyx *onyx = cii->codec_data;
824 u8 v;
825 int err = -ENXIO;
826
827 mutex_lock(&onyx->mutex);
828 /* take codec out of suspend */
829 if (onyx_read_register(onyx, ONYX_REG_CONTROL, &v))
830 goto out_unlock;
831 onyx_write_register(onyx, ONYX_REG_CONTROL, v & ~(ONYX_ADPSV | ONYX_DAPSV));
832 /* FIXME: should divide by sample rate, but 8k is the lowest we go */
833 msleep(2205000/8000);
834 /* reset all values */
835 onyx_register_init(onyx);
836 err = 0;
837 out_unlock:
838 mutex_unlock(&onyx->mutex);
839
840 return err;
841}
842
843#endif /* CONFIG_PM */
844
845static struct codec_info onyx_codec_info = {
846 .transfers = onyx_transfers,
847 .sysclock_factor = 256,
848 .bus_factor = 64,
849 .owner = THIS_MODULE,
850 .usable = onyx_usable,
851 .prepare = onyx_prepare,
852 .open = onyx_open,
853 .close = onyx_close,
854 .switch_clock = onyx_switch_clock,
855#ifdef CONFIG_PM
856 .suspend = onyx_suspend,
857 .resume = onyx_resume,
858#endif
859};
860
861static int onyx_init_codec(struct aoa_codec *codec)
862{
863 struct onyx *onyx = codec_to_onyx(codec);
864 struct snd_kcontrol *ctl;
865 struct codec_info *ci = &onyx_codec_info;
866 u8 v;
867 int err;
868
869 if (!onyx->codec.gpio || !onyx->codec.gpio->methods) {
870 printk(KERN_ERR PFX "gpios not assigned!!\n");
871 return -EINVAL;
872 }
873
874 onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0);
875 msleep(1);
876 onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 1);
877 msleep(1);
878 onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0);
879 msleep(1);
880
881 if (onyx_register_init(onyx)) {
882 printk(KERN_ERR PFX "failed to initialise onyx registers\n");
883 return -ENODEV;
884 }
885
886 if (aoa_snd_device_new(SNDRV_DEV_LOWLEVEL, onyx, &ops)) {
887 printk(KERN_ERR PFX "failed to create onyx snd device!\n");
888 return -ENODEV;
889 }
890
891 /* nothing connected? what a joke! */
892 if ((onyx->codec.connected & 0xF) == 0)
893 return -ENOTCONN;
894
895 /* if no inputs are present... */
896 if ((onyx->codec.connected & 0xC) == 0) {
897 if (!onyx->codec_info)
898 onyx->codec_info = kmalloc(sizeof(struct codec_info), GFP_KERNEL);
899 if (!onyx->codec_info)
900 return -ENOMEM;
901 ci = onyx->codec_info;
902 *ci = onyx_codec_info;
903 ci->transfers++;
904 }
905
906 /* if no outputs are present... */
907 if ((onyx->codec.connected & 3) == 0) {
908 if (!onyx->codec_info)
909 onyx->codec_info = kmalloc(sizeof(struct codec_info), GFP_KERNEL);
910 if (!onyx->codec_info)
911 return -ENOMEM;
912 ci = onyx->codec_info;
913 /* this is fine as there have to be inputs
914 * if we end up in this part of the code */
915 *ci = onyx_codec_info;
916 ci->transfers[1].formats = 0;
917 }
918
919 if (onyx->codec.soundbus_dev->attach_codec(onyx->codec.soundbus_dev,
920 aoa_get_card(),
921 ci, onyx)) {
922 printk(KERN_ERR PFX "error creating onyx pcm\n");
923 return -ENODEV;
924 }
925#define ADDCTL(n) \
926 do { \
927 ctl = snd_ctl_new1(&n, onyx); \
928 if (ctl) { \
929 ctl->id.device = \
930 onyx->codec.soundbus_dev->pcm->device; \
931 err = aoa_snd_ctl_add(ctl); \
932 if (err) \
933 goto error; \
934 } \
935 } while (0)
936
937 if (onyx->codec.soundbus_dev->pcm) {
938 /* give the user appropriate controls
939 * depending on what inputs are connected */
940 if ((onyx->codec.connected & 0xC) == 0xC)
941 ADDCTL(capture_source_control);
942 else if (onyx->codec.connected & 4)
943 onyx_set_capture_source(onyx, 0);
944 else
945 onyx_set_capture_source(onyx, 1);
946 if (onyx->codec.connected & 0xC)
947 ADDCTL(inputgain_control);
948
949 /* depending on what output is connected,
950 * give the user appropriate controls */
951 if (onyx->codec.connected & 1) {
952 ADDCTL(volume_control);
953 ADDCTL(mute_control);
954 ADDCTL(ovr1_control);
955 ADDCTL(flt0_control);
956 ADDCTL(hpf_control);
957 ADDCTL(dm12_control);
958 /* spdif control defaults to off */
959 }
960 if (onyx->codec.connected & 2) {
961 ADDCTL(onyx_spdif_mask);
962 ADDCTL(onyx_spdif_ctrl);
963 }
964 if ((onyx->codec.connected & 3) == 3)
965 ADDCTL(spdif_control);
966 /* if only S/PDIF is connected, enable it unconditionally */
967 if ((onyx->codec.connected & 3) == 2) {
968 onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v);
969 v |= ONYX_SPDIF_ENABLE;
970 onyx_write_register(onyx, ONYX_REG_DIG_INFO4, v);
971 }
972 }
973#undef ADDCTL
974 printk(KERN_INFO PFX "attached to onyx codec via i2c\n");
975
976 return 0;
977 error:
978 onyx->codec.soundbus_dev->detach_codec(onyx->codec.soundbus_dev, onyx);
979 snd_device_free(aoa_get_card(), onyx);
980 return err;
981}
982
983static void onyx_exit_codec(struct aoa_codec *codec)
984{
985 struct onyx *onyx = codec_to_onyx(codec);
986
987 if (!onyx->codec.soundbus_dev) {
988 printk(KERN_ERR PFX "onyx_exit_codec called without soundbus_dev!\n");
989 return;
990 }
991 onyx->codec.soundbus_dev->detach_codec(onyx->codec.soundbus_dev, onyx);
992}
993
994static struct i2c_driver onyx_driver;
995
996static int onyx_create(struct i2c_adapter *adapter,
997 struct device_node *node,
998 int addr)
999{
1000 struct onyx *onyx;
1001 u8 dummy;
1002
1003 onyx = kzalloc(sizeof(struct onyx), GFP_KERNEL);
1004
1005 if (!onyx)
1006 return -ENOMEM;
1007
1008 mutex_init(&onyx->mutex);
1009 onyx->i2c.driver = &onyx_driver;
1010 onyx->i2c.adapter = adapter;
1011 onyx->i2c.addr = addr & 0x7f;
1012 strlcpy(onyx->i2c.name, "onyx audio codec", I2C_NAME_SIZE-1);
1013
1014 if (i2c_attach_client(&onyx->i2c)) {
1015 printk(KERN_ERR PFX "failed to attach to i2c\n");
1016 goto fail;
1017 }
1018
1019 /* we try to read from register ONYX_REG_CONTROL
1020 * to check if the codec is present */
1021 if (onyx_read_register(onyx, ONYX_REG_CONTROL, &dummy) != 0) {
1022 i2c_detach_client(&onyx->i2c);
1023 printk(KERN_ERR PFX "failed to read control register\n");
1024 goto fail;
1025 }
1026
1027 strlcpy(onyx->codec.name, "onyx", MAX_CODEC_NAME_LEN-1);
1028 onyx->codec.owner = THIS_MODULE;
1029 onyx->codec.init = onyx_init_codec;
1030 onyx->codec.exit = onyx_exit_codec;
1031 onyx->codec.node = of_node_get(node);
1032
1033 if (aoa_codec_register(&onyx->codec)) {
1034 i2c_detach_client(&onyx->i2c);
1035 goto fail;
1036 }
1037 printk(KERN_DEBUG PFX "created and attached onyx instance\n");
1038 return 0;
1039 fail:
1040 kfree(onyx);
1041 return -EINVAL;
1042}
1043
1044static int onyx_i2c_attach(struct i2c_adapter *adapter)
1045{
1046 struct device_node *busnode, *dev = NULL;
1047 struct pmac_i2c_bus *bus;
1048
1049 bus = pmac_i2c_adapter_to_bus(adapter);
1050 if (bus == NULL)
1051 return -ENODEV;
1052 busnode = pmac_i2c_get_bus_node(bus);
1053
1054 while ((dev = of_get_next_child(busnode, dev)) != NULL) {
1055 if (device_is_compatible(dev, "pcm3052")) {
1056 u32 *addr;
1057 printk(KERN_DEBUG PFX "found pcm3052\n");
1058 addr = (u32 *) get_property(dev, "reg", NULL);
1059 if (!addr)
1060 return -ENODEV;
1061 return onyx_create(adapter, dev, (*addr)>>1);
1062 }
1063 }
1064
1065 /* if that didn't work, try desperate mode for older
1066 * machines that have stuff missing from the device tree */
1067
1068 if (!device_is_compatible(busnode, "k2-i2c"))
1069 return -ENODEV;
1070
1071 printk(KERN_DEBUG PFX "found k2-i2c, checking if onyx chip is on it\n");
1072 /* probe both possible addresses for the onyx chip */
1073 if (onyx_create(adapter, NULL, 0x46) == 0)
1074 return 0;
1075 return onyx_create(adapter, NULL, 0x47);
1076}
1077
1078static int onyx_i2c_detach(struct i2c_client *client)
1079{
1080 struct onyx *onyx = container_of(client, struct onyx, i2c);
1081 int err;
1082
1083 if ((err = i2c_detach_client(client)))
1084 return err;
1085 aoa_codec_unregister(&onyx->codec);
1086 of_node_put(onyx->codec.node);
1087 if (onyx->codec_info)
1088 kfree(onyx->codec_info);
1089 kfree(onyx);
1090 return 0;
1091}
1092
1093static struct i2c_driver onyx_driver = {
1094 .driver = {
1095 .name = "aoa_codec_onyx",
1096 .owner = THIS_MODULE,
1097 },
1098 .attach_adapter = onyx_i2c_attach,
1099 .detach_client = onyx_i2c_detach,
1100};
1101
1102static int __init onyx_init(void)
1103{
1104 return i2c_add_driver(&onyx_driver);
1105}
1106
1107static void __exit onyx_exit(void)
1108{
1109 i2c_del_driver(&onyx_driver);
1110}
1111
1112module_init(onyx_init);
1113module_exit(onyx_exit);
diff --git a/sound/aoa/codecs/snd-aoa-codec-onyx.h b/sound/aoa/codecs/snd-aoa-codec-onyx.h
new file mode 100644
index 000000000000..aeedda773699
--- /dev/null
+++ b/sound/aoa/codecs/snd-aoa-codec-onyx.h
@@ -0,0 +1,76 @@
1/*
2 * Apple Onboard Audio driver for Onyx codec (header)
3 *
4 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
5 *
6 * GPL v2, can be found in COPYING.
7 */
8#ifndef __SND_AOA_CODEC_ONYX_H
9#define __SND_AOA_CODEC_ONYX_H
10#include <stddef.h>
11#include <linux/i2c.h>
12#include <linux/i2c-dev.h>
13#include <asm/pmac_low_i2c.h>
14#include <asm/prom.h>
15
16/* PCM3052 register definitions */
17
18/* the attenuation registers take values from
19 * -1 (0dB) to -127 (-63.0 dB) or others (muted) */
20#define ONYX_REG_DAC_ATTEN_LEFT 65
21#define FIRSTREGISTER ONYX_REG_DAC_ATTEN_LEFT
22#define ONYX_REG_DAC_ATTEN_RIGHT 66
23
24#define ONYX_REG_CONTROL 67
25# define ONYX_MRST (1<<7)
26# define ONYX_SRST (1<<6)
27# define ONYX_ADPSV (1<<5)
28# define ONYX_DAPSV (1<<4)
29# define ONYX_SILICONVERSION (1<<0)
30/* all others reserved */
31
32#define ONYX_REG_DAC_CONTROL 68
33# define ONYX_OVR1 (1<<6)
34# define ONYX_MUTE_RIGHT (1<<1)
35# define ONYX_MUTE_LEFT (1<<0)
36
37#define ONYX_REG_DAC_DEEMPH 69
38# define ONYX_DIGDEEMPH_SHIFT 5
39# define ONYX_DIGDEEMPH_MASK (3<<ONYX_DIGDEEMPH_SHIFT)
40# define ONYX_DIGDEEMPH_CTRL (1<<4)
41
42#define ONYX_REG_DAC_FILTER 70
43# define ONYX_ROLLOFF_FAST (1<<5)
44# define ONYX_DAC_FILTER_ALWAYS (1<<2)
45
46#define ONYX_REG_DAC_OUTPHASE 71
47# define ONYX_OUTPHASE_INVERTED (1<<0)
48
49#define ONYX_REG_ADC_CONTROL 72
50# define ONYX_ADC_INPUT_MIC (1<<5)
51/* 8 + input gain in dB, valid range for input gain is -4 .. 20 dB */
52# define ONYX_ADC_PGA_GAIN_MASK 0x1f
53
54#define ONYX_REG_ADC_HPF_BYPASS 75
55# define ONYX_HPF_DISABLE (1<<3)
56# define ONYX_ADC_HPF_ALWAYS (1<<2)
57
58#define ONYX_REG_DIG_INFO1 77
59# define ONYX_MASK_DIN_TO_BPZ (1<<7)
60/* bits 1-5 control channel bits 1-5 */
61# define ONYX_DIGOUT_DISABLE (1<<0)
62
63#define ONYX_REG_DIG_INFO2 78
64/* controls channel bits 8-15 */
65
66#define ONYX_REG_DIG_INFO3 79
67/* control channel bits 24-29, high 2 bits reserved */
68
69#define ONYX_REG_DIG_INFO4 80
70# define ONYX_VALIDL (1<<7)
71# define ONYX_VALIDR (1<<6)
72# define ONYX_SPDIF_ENABLE (1<<5)
73/* lower 4 bits control bits 32-35 of channel control and word length */
74# define ONYX_WORDLEN_MASK (0xF)
75
76#endif /* __SND_AOA_CODEC_ONYX_H */
diff --git a/sound/aoa/codecs/snd-aoa-codec-tas-gain-table.h b/sound/aoa/codecs/snd-aoa-codec-tas-gain-table.h
new file mode 100644
index 000000000000..4cfa6757715e
--- /dev/null
+++ b/sound/aoa/codecs/snd-aoa-codec-tas-gain-table.h
@@ -0,0 +1,209 @@
1/*
2 This is the program used to generate below table.
3
4#include <stdio.h>
5#include <math.h>
6int main() {
7 int dB2;
8 printf("/" "* This file is only included exactly once!\n");
9 printf(" *\n");
10 printf(" * If they'd only tell us that generating this table was\n");
11 printf(" * as easy as calculating\n");
12 printf(" * hwvalue = 1048576.0*exp(0.057564628*dB*2)\n");
13 printf(" * :) *" "/\n");
14 printf("static int tas_gaintable[] = {\n");
15 printf(" 0x000000, /" "* -infinity dB *" "/\n");
16 for (dB2=-140;dB2<=36;dB2++)
17 printf(" 0x%.6x, /" "* %-02.1f dB *" "/\n", (int)(1048576.0*exp(0.057564628*dB2)), dB2/2.0);
18 printf("};\n\n");
19}
20
21*/
22
23/* This file is only included exactly once!
24 *
25 * If they'd only tell us that generating this table was
26 * as easy as calculating
27 * hwvalue = 1048576.0*exp(0.057564628*dB*2)
28 * :) */
29static int tas_gaintable[] = {
30 0x000000, /* -infinity dB */
31 0x00014b, /* -70.0 dB */
32 0x00015f, /* -69.5 dB */
33 0x000174, /* -69.0 dB */
34 0x00018a, /* -68.5 dB */
35 0x0001a1, /* -68.0 dB */
36 0x0001ba, /* -67.5 dB */
37 0x0001d4, /* -67.0 dB */
38 0x0001f0, /* -66.5 dB */
39 0x00020d, /* -66.0 dB */
40 0x00022c, /* -65.5 dB */
41 0x00024d, /* -65.0 dB */
42 0x000270, /* -64.5 dB */
43 0x000295, /* -64.0 dB */
44 0x0002bc, /* -63.5 dB */
45 0x0002e6, /* -63.0 dB */
46 0x000312, /* -62.5 dB */
47 0x000340, /* -62.0 dB */
48 0x000372, /* -61.5 dB */
49 0x0003a6, /* -61.0 dB */
50 0x0003dd, /* -60.5 dB */
51 0x000418, /* -60.0 dB */
52 0x000456, /* -59.5 dB */
53 0x000498, /* -59.0 dB */
54 0x0004de, /* -58.5 dB */
55 0x000528, /* -58.0 dB */
56 0x000576, /* -57.5 dB */
57 0x0005c9, /* -57.0 dB */
58 0x000620, /* -56.5 dB */
59 0x00067d, /* -56.0 dB */
60 0x0006e0, /* -55.5 dB */
61 0x000748, /* -55.0 dB */
62 0x0007b7, /* -54.5 dB */
63 0x00082c, /* -54.0 dB */
64 0x0008a8, /* -53.5 dB */
65 0x00092b, /* -53.0 dB */
66 0x0009b6, /* -52.5 dB */
67 0x000a49, /* -52.0 dB */
68 0x000ae5, /* -51.5 dB */
69 0x000b8b, /* -51.0 dB */
70 0x000c3a, /* -50.5 dB */
71 0x000cf3, /* -50.0 dB */
72 0x000db8, /* -49.5 dB */
73 0x000e88, /* -49.0 dB */
74 0x000f64, /* -48.5 dB */
75 0x00104e, /* -48.0 dB */
76 0x001145, /* -47.5 dB */
77 0x00124b, /* -47.0 dB */
78 0x001361, /* -46.5 dB */
79 0x001487, /* -46.0 dB */
80 0x0015be, /* -45.5 dB */
81 0x001708, /* -45.0 dB */
82 0x001865, /* -44.5 dB */
83 0x0019d8, /* -44.0 dB */
84 0x001b60, /* -43.5 dB */
85 0x001cff, /* -43.0 dB */
86 0x001eb7, /* -42.5 dB */
87 0x002089, /* -42.0 dB */
88 0x002276, /* -41.5 dB */
89 0x002481, /* -41.0 dB */
90 0x0026ab, /* -40.5 dB */
91 0x0028f5, /* -40.0 dB */
92 0x002b63, /* -39.5 dB */
93 0x002df5, /* -39.0 dB */
94 0x0030ae, /* -38.5 dB */
95 0x003390, /* -38.0 dB */
96 0x00369e, /* -37.5 dB */
97 0x0039db, /* -37.0 dB */
98 0x003d49, /* -36.5 dB */
99 0x0040ea, /* -36.0 dB */
100 0x0044c3, /* -35.5 dB */
101 0x0048d6, /* -35.0 dB */
102 0x004d27, /* -34.5 dB */
103 0x0051b9, /* -34.0 dB */
104 0x005691, /* -33.5 dB */
105 0x005bb2, /* -33.0 dB */
106 0x006121, /* -32.5 dB */
107 0x0066e3, /* -32.0 dB */
108 0x006cfb, /* -31.5 dB */
109 0x007370, /* -31.0 dB */
110 0x007a48, /* -30.5 dB */
111 0x008186, /* -30.0 dB */
112 0x008933, /* -29.5 dB */
113 0x009154, /* -29.0 dB */
114 0x0099f1, /* -28.5 dB */
115 0x00a310, /* -28.0 dB */
116 0x00acba, /* -27.5 dB */
117 0x00b6f6, /* -27.0 dB */
118 0x00c1cd, /* -26.5 dB */
119 0x00cd49, /* -26.0 dB */
120 0x00d973, /* -25.5 dB */
121 0x00e655, /* -25.0 dB */
122 0x00f3fb, /* -24.5 dB */
123 0x010270, /* -24.0 dB */
124 0x0111c0, /* -23.5 dB */
125 0x0121f9, /* -23.0 dB */
126 0x013328, /* -22.5 dB */
127 0x01455b, /* -22.0 dB */
128 0x0158a2, /* -21.5 dB */
129 0x016d0e, /* -21.0 dB */
130 0x0182af, /* -20.5 dB */
131 0x019999, /* -20.0 dB */
132 0x01b1de, /* -19.5 dB */
133 0x01cb94, /* -19.0 dB */
134 0x01e6cf, /* -18.5 dB */
135 0x0203a7, /* -18.0 dB */
136 0x022235, /* -17.5 dB */
137 0x024293, /* -17.0 dB */
138 0x0264db, /* -16.5 dB */
139 0x02892c, /* -16.0 dB */
140 0x02afa3, /* -15.5 dB */
141 0x02d862, /* -15.0 dB */
142 0x03038a, /* -14.5 dB */
143 0x033142, /* -14.0 dB */
144 0x0361af, /* -13.5 dB */
145 0x0394fa, /* -13.0 dB */
146 0x03cb50, /* -12.5 dB */
147 0x0404de, /* -12.0 dB */
148 0x0441d5, /* -11.5 dB */
149 0x048268, /* -11.0 dB */
150 0x04c6d0, /* -10.5 dB */
151 0x050f44, /* -10.0 dB */
152 0x055c04, /* -9.5 dB */
153 0x05ad50, /* -9.0 dB */
154 0x06036e, /* -8.5 dB */
155 0x065ea5, /* -8.0 dB */
156 0x06bf44, /* -7.5 dB */
157 0x07259d, /* -7.0 dB */
158 0x079207, /* -6.5 dB */
159 0x0804dc, /* -6.0 dB */
160 0x087e80, /* -5.5 dB */
161 0x08ff59, /* -5.0 dB */
162 0x0987d5, /* -4.5 dB */
163 0x0a1866, /* -4.0 dB */
164 0x0ab189, /* -3.5 dB */
165 0x0b53be, /* -3.0 dB */
166 0x0bff91, /* -2.5 dB */
167 0x0cb591, /* -2.0 dB */
168 0x0d765a, /* -1.5 dB */
169 0x0e4290, /* -1.0 dB */
170 0x0f1adf, /* -0.5 dB */
171 0x100000, /* 0.0 dB */
172 0x10f2b4, /* 0.5 dB */
173 0x11f3c9, /* 1.0 dB */
174 0x13041a, /* 1.5 dB */
175 0x14248e, /* 2.0 dB */
176 0x15561a, /* 2.5 dB */
177 0x1699c0, /* 3.0 dB */
178 0x17f094, /* 3.5 dB */
179 0x195bb8, /* 4.0 dB */
180 0x1adc61, /* 4.5 dB */
181 0x1c73d5, /* 5.0 dB */
182 0x1e236d, /* 5.5 dB */
183 0x1fec98, /* 6.0 dB */
184 0x21d0d9, /* 6.5 dB */
185 0x23d1cd, /* 7.0 dB */
186 0x25f125, /* 7.5 dB */
187 0x2830af, /* 8.0 dB */
188 0x2a9254, /* 8.5 dB */
189 0x2d1818, /* 9.0 dB */
190 0x2fc420, /* 9.5 dB */
191 0x3298b0, /* 10.0 dB */
192 0x35982f, /* 10.5 dB */
193 0x38c528, /* 11.0 dB */
194 0x3c224c, /* 11.5 dB */
195 0x3fb278, /* 12.0 dB */
196 0x4378b0, /* 12.5 dB */
197 0x477829, /* 13.0 dB */
198 0x4bb446, /* 13.5 dB */
199 0x5030a1, /* 14.0 dB */
200 0x54f106, /* 14.5 dB */
201 0x59f980, /* 15.0 dB */
202 0x5f4e52, /* 15.5 dB */
203 0x64f403, /* 16.0 dB */
204 0x6aef5e, /* 16.5 dB */
205 0x714575, /* 17.0 dB */
206 0x77fbaa, /* 17.5 dB */
207 0x7f17af, /* 18.0 dB */
208};
209
diff --git a/sound/aoa/codecs/snd-aoa-codec-tas.c b/sound/aoa/codecs/snd-aoa-codec-tas.c
new file mode 100644
index 000000000000..2e39ff6ee349
--- /dev/null
+++ b/sound/aoa/codecs/snd-aoa-codec-tas.c
@@ -0,0 +1,654 @@
1/*
2 * Apple Onboard Audio driver for tas codec
3 *
4 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
5 *
6 * GPL v2, can be found in COPYING.
7 *
8 * Open questions:
9 * - How to distinguish between 3004 and versions?
10 *
11 * FIXMEs:
12 * - This codec driver doesn't honour the 'connected'
13 * property of the aoa_codec struct, hence if
14 * it is used in machines where not everything is
15 * connected it will display wrong mixer elements.
16 * - Driver assumes that the microphone is always
17 * monaureal and connected to the right channel of
18 * the input. This should also be a codec-dependent
19 * flag, maybe the codec should have 3 different
20 * bits for the three different possibilities how
21 * it can be hooked up...
22 * But as long as I don't see any hardware hooked
23 * up that way...
24 * - As Apple notes in their code, the tas3004 seems
25 * to delay the right channel by one sample. You can
26 * see this when for example recording stereo in
27 * audacity, or recording the tas output via cable
28 * on another machine (use a sinus generator or so).
29 * I tried programming the BiQuads but couldn't
30 * make the delay work, maybe someone can read the
31 * datasheet and fix it. The relevant Apple comment
32 * is in AppleTAS3004Audio.cpp lines 1637 ff. Note
33 * that their comment describing how they program
34 * the filters sucks...
35 *
36 * Other things:
37 * - this should actually register *two* aoa_codec
38 * structs since it has two inputs. Then it must
39 * use the prepare callback to forbid running the
40 * secondary output on a different clock.
41 * Also, whatever bus knows how to do this must
42 * provide two soundbus_dev devices and the fabric
43 * must be able to link them correctly.
44 *
45 * I don't even know if Apple ever uses the second
46 * port on the tas3004 though, I don't think their
47 * i2s controllers can even do it. OTOH, they all
48 * derive the clocks from common clocks, so it
49 * might just be possible. The framework allows the
50 * codec to refine the transfer_info items in the
51 * usable callback, so we can simply remove the
52 * rates the second instance is not using when it
53 * actually is in use.
54 * Maybe we'll need to make the sound busses have
55 * a 'clock group id' value so the codec can
56 * determine if the two outputs can be driven at
57 * the same time. But that is likely overkill, up
58 * to the fabric to not link them up incorrectly,
59 * and up to the hardware designer to not wire
60 * them up in some weird unusable way.
61 */
62#include <stddef.h>
63#include <linux/i2c.h>
64#include <linux/i2c-dev.h>
65#include <asm/pmac_low_i2c.h>
66#include <asm/prom.h>
67#include <linux/delay.h>
68#include <linux/module.h>
69MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
70MODULE_LICENSE("GPL");
71MODULE_DESCRIPTION("tas codec driver for snd-aoa");
72
73#include "snd-aoa-codec-tas.h"
74#include "snd-aoa-codec-tas-gain-table.h"
75#include "../aoa.h"
76#include "../soundbus/soundbus.h"
77
78
79#define PFX "snd-aoa-codec-tas: "
80
81struct tas {
82 struct aoa_codec codec;
83 struct i2c_client i2c;
84 u32 muted_l:1, muted_r:1,
85 controls_created:1;
86 u8 cached_volume_l, cached_volume_r;
87 u8 mixer_l[3], mixer_r[3];
88 u8 acr;
89};
90
91static struct tas *codec_to_tas(struct aoa_codec *codec)
92{
93 return container_of(codec, struct tas, codec);
94}
95
96static inline int tas_write_reg(struct tas *tas, u8 reg, u8 len, u8 *data)
97{
98 if (len == 1)
99 return i2c_smbus_write_byte_data(&tas->i2c, reg, *data);
100 else
101 return i2c_smbus_write_i2c_block_data(&tas->i2c, reg, len, data);
102}
103
104static void tas_set_volume(struct tas *tas)
105{
106 u8 block[6];
107 int tmp;
108 u8 left, right;
109
110 left = tas->cached_volume_l;
111 right = tas->cached_volume_r;
112
113 if (left > 177) left = 177;
114 if (right > 177) right = 177;
115
116 if (tas->muted_l) left = 0;
117 if (tas->muted_r) right = 0;
118
119 /* analysing the volume and mixer tables shows
120 * that they are similar enough when we shift
121 * the mixer table down by 4 bits. The error
122 * is miniscule, in just one item the error
123 * is 1, at a value of 0x07f17b (mixer table
124 * value is 0x07f17a) */
125 tmp = tas_gaintable[left];
126 block[0] = tmp>>20;
127 block[1] = tmp>>12;
128 block[2] = tmp>>4;
129 tmp = tas_gaintable[right];
130 block[3] = tmp>>20;
131 block[4] = tmp>>12;
132 block[5] = tmp>>4;
133 tas_write_reg(tas, TAS_REG_VOL, 6, block);
134}
135
136static void tas_set_mixer(struct tas *tas)
137{
138 u8 block[9];
139 int tmp, i;
140 u8 val;
141
142 for (i=0;i<3;i++) {
143 val = tas->mixer_l[i];
144 if (val > 177) val = 177;
145 tmp = tas_gaintable[val];
146 block[3*i+0] = tmp>>16;
147 block[3*i+1] = tmp>>8;
148 block[3*i+2] = tmp;
149 }
150 tas_write_reg(tas, TAS_REG_LMIX, 9, block);
151
152 for (i=0;i<3;i++) {
153 val = tas->mixer_r[i];
154 if (val > 177) val = 177;
155 tmp = tas_gaintable[val];
156 block[3*i+0] = tmp>>16;
157 block[3*i+1] = tmp>>8;
158 block[3*i+2] = tmp;
159 }
160 tas_write_reg(tas, TAS_REG_RMIX, 9, block);
161}
162
163/* alsa stuff */
164
165static int tas_dev_register(struct snd_device *dev)
166{
167 return 0;
168}
169
170static struct snd_device_ops ops = {
171 .dev_register = tas_dev_register,
172};
173
174static int tas_snd_vol_info(struct snd_kcontrol *kcontrol,
175 struct snd_ctl_elem_info *uinfo)
176{
177 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
178 uinfo->count = 2;
179 uinfo->value.integer.min = 0;
180 uinfo->value.integer.max = 177;
181 return 0;
182}
183
184static int tas_snd_vol_get(struct snd_kcontrol *kcontrol,
185 struct snd_ctl_elem_value *ucontrol)
186{
187 struct tas *tas = snd_kcontrol_chip(kcontrol);
188
189 ucontrol->value.integer.value[0] = tas->cached_volume_l;
190 ucontrol->value.integer.value[1] = tas->cached_volume_r;
191 return 0;
192}
193
194static int tas_snd_vol_put(struct snd_kcontrol *kcontrol,
195 struct snd_ctl_elem_value *ucontrol)
196{
197 struct tas *tas = snd_kcontrol_chip(kcontrol);
198
199 if (tas->cached_volume_l == ucontrol->value.integer.value[0]
200 && tas->cached_volume_r == ucontrol->value.integer.value[1])
201 return 0;
202
203 tas->cached_volume_l = ucontrol->value.integer.value[0];
204 tas->cached_volume_r = ucontrol->value.integer.value[1];
205 tas_set_volume(tas);
206 return 1;
207}
208
209static struct snd_kcontrol_new volume_control = {
210 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
211 .name = "Master Playback Volume",
212 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
213 .info = tas_snd_vol_info,
214 .get = tas_snd_vol_get,
215 .put = tas_snd_vol_put,
216};
217
218static int tas_snd_mute_info(struct snd_kcontrol *kcontrol,
219 struct snd_ctl_elem_info *uinfo)
220{
221 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
222 uinfo->count = 2;
223 uinfo->value.integer.min = 0;
224 uinfo->value.integer.max = 1;
225 return 0;
226}
227
228static int tas_snd_mute_get(struct snd_kcontrol *kcontrol,
229 struct snd_ctl_elem_value *ucontrol)
230{
231 struct tas *tas = snd_kcontrol_chip(kcontrol);
232
233 ucontrol->value.integer.value[0] = !tas->muted_l;
234 ucontrol->value.integer.value[1] = !tas->muted_r;
235 return 0;
236}
237
238static int tas_snd_mute_put(struct snd_kcontrol *kcontrol,
239 struct snd_ctl_elem_value *ucontrol)
240{
241 struct tas *tas = snd_kcontrol_chip(kcontrol);
242
243 if (tas->muted_l == !ucontrol->value.integer.value[0]
244 && tas->muted_r == !ucontrol->value.integer.value[1])
245 return 0;
246
247 tas->muted_l = !ucontrol->value.integer.value[0];
248 tas->muted_r = !ucontrol->value.integer.value[1];
249 tas_set_volume(tas);
250 return 1;
251}
252
253static struct snd_kcontrol_new mute_control = {
254 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
255 .name = "Master Playback Switch",
256 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
257 .info = tas_snd_mute_info,
258 .get = tas_snd_mute_get,
259 .put = tas_snd_mute_put,
260};
261
262static int tas_snd_mixer_info(struct snd_kcontrol *kcontrol,
263 struct snd_ctl_elem_info *uinfo)
264{
265 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
266 uinfo->count = 2;
267 uinfo->value.integer.min = 0;
268 uinfo->value.integer.max = 177;
269 return 0;
270}
271
272static int tas_snd_mixer_get(struct snd_kcontrol *kcontrol,
273 struct snd_ctl_elem_value *ucontrol)
274{
275 struct tas *tas = snd_kcontrol_chip(kcontrol);
276 int idx = kcontrol->private_value;
277
278 ucontrol->value.integer.value[0] = tas->mixer_l[idx];
279 ucontrol->value.integer.value[1] = tas->mixer_r[idx];
280
281 return 0;
282}
283
284static int tas_snd_mixer_put(struct snd_kcontrol *kcontrol,
285 struct snd_ctl_elem_value *ucontrol)
286{
287 struct tas *tas = snd_kcontrol_chip(kcontrol);
288 int idx = kcontrol->private_value;
289
290 if (tas->mixer_l[idx] == ucontrol->value.integer.value[0]
291 && tas->mixer_r[idx] == ucontrol->value.integer.value[1])
292 return 0;
293
294 tas->mixer_l[idx] = ucontrol->value.integer.value[0];
295 tas->mixer_r[idx] = ucontrol->value.integer.value[1];
296
297 tas_set_mixer(tas);
298 return 1;
299}
300
301#define MIXER_CONTROL(n,descr,idx) \
302static struct snd_kcontrol_new n##_control = { \
303 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
304 .name = descr " Playback Volume", \
305 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
306 .info = tas_snd_mixer_info, \
307 .get = tas_snd_mixer_get, \
308 .put = tas_snd_mixer_put, \
309 .private_value = idx, \
310}
311
312MIXER_CONTROL(pcm1, "PCM1", 0);
313MIXER_CONTROL(monitor, "Monitor", 2);
314
315static int tas_snd_capture_source_info(struct snd_kcontrol *kcontrol,
316 struct snd_ctl_elem_info *uinfo)
317{
318 static char *texts[] = { "Line-In", "Microphone" };
319
320 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
321 uinfo->count = 1;
322 uinfo->value.enumerated.items = 2;
323 if (uinfo->value.enumerated.item > 1)
324 uinfo->value.enumerated.item = 1;
325 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
326 return 0;
327}
328
329static int tas_snd_capture_source_get(struct snd_kcontrol *kcontrol,
330 struct snd_ctl_elem_value *ucontrol)
331{
332 struct tas *tas = snd_kcontrol_chip(kcontrol);
333
334 ucontrol->value.enumerated.item[0] = !!(tas->acr & TAS_ACR_INPUT_B);
335 return 0;
336}
337
338static int tas_snd_capture_source_put(struct snd_kcontrol *kcontrol,
339 struct snd_ctl_elem_value *ucontrol)
340{
341 struct tas *tas = snd_kcontrol_chip(kcontrol);
342 int oldacr = tas->acr;
343
344 tas->acr &= ~TAS_ACR_INPUT_B;
345 if (ucontrol->value.enumerated.item[0])
346 tas->acr |= TAS_ACR_INPUT_B;
347 if (oldacr == tas->acr)
348 return 0;
349 tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr);
350 return 1;
351}
352
353static struct snd_kcontrol_new capture_source_control = {
354 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
355 /* If we name this 'Input Source', it properly shows up in
356 * alsamixer as a selection, * but it's shown under the
357 * 'Playback' category.
358 * If I name it 'Capture Source', it shows up in strange
359 * ways (two bools of which one can be selected at a
360 * time) but at least it's shown in the 'Capture'
361 * category.
362 * I was told that this was due to backward compatibility,
363 * but I don't understand then why the mangling is *not*
364 * done when I name it "Input Source".....
365 */
366 .name = "Capture Source",
367 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
368 .info = tas_snd_capture_source_info,
369 .get = tas_snd_capture_source_get,
370 .put = tas_snd_capture_source_put,
371};
372
373
374static struct transfer_info tas_transfers[] = {
375 {
376 /* input */
377 .formats = SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S16_BE |
378 SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S24_BE,
379 .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
380 .transfer_in = 1,
381 },
382 {
383 /* output */
384 .formats = SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S16_BE |
385 SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S24_BE,
386 .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
387 .transfer_in = 0,
388 },
389 {}
390};
391
392static int tas_usable(struct codec_info_item *cii,
393 struct transfer_info *ti,
394 struct transfer_info *out)
395{
396 return 1;
397}
398
399static int tas_reset_init(struct tas *tas)
400{
401 u8 tmp;
402 tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 0);
403 msleep(1);
404 tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 1);
405 msleep(1);
406 tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 0);
407 msleep(1);
408
409 tas->acr &= ~TAS_ACR_ANALOG_PDOWN;
410 tas->acr |= TAS_ACR_B_MONAUREAL | TAS_ACR_B_MON_SEL_RIGHT;
411 if (tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr))
412 return -ENODEV;
413
414 tmp = TAS_MCS_SCLK64 | TAS_MCS_SPORT_MODE_I2S | TAS_MCS_SPORT_WL_24BIT;
415 if (tas_write_reg(tas, TAS_REG_MCS, 1, &tmp))
416 return -ENODEV;
417
418 tmp = 0;
419 if (tas_write_reg(tas, TAS_REG_MCS2, 1, &tmp))
420 return -ENODEV;
421
422 return 0;
423}
424
425/* we are controlled via i2c and assume that is always up
426 * If that wasn't the case, we'd have to suspend once
427 * our i2c device is suspended, and then take note of that! */
428static int tas_suspend(struct tas *tas)
429{
430 tas->acr |= TAS_ACR_ANALOG_PDOWN;
431 tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr);
432 return 0;
433}
434
435static int tas_resume(struct tas *tas)
436{
437 /* reset codec */
438 tas_reset_init(tas);
439 tas_set_volume(tas);
440 tas_set_mixer(tas);
441 return 0;
442}
443
444#ifdef CONFIG_PM
445static int _tas_suspend(struct codec_info_item *cii, pm_message_t state)
446{
447 return tas_suspend(cii->codec_data);
448}
449
450static int _tas_resume(struct codec_info_item *cii)
451{
452 return tas_resume(cii->codec_data);
453}
454#endif
455
456static struct codec_info tas_codec_info = {
457 .transfers = tas_transfers,
458 /* in theory, we can drive it at 512 too...
459 * but so far the framework doesn't allow
460 * for that and I don't see much point in it. */
461 .sysclock_factor = 256,
462 /* same here, could be 32 for just one 16 bit format */
463 .bus_factor = 64,
464 .owner = THIS_MODULE,
465 .usable = tas_usable,
466#ifdef CONFIG_PM
467 .suspend = _tas_suspend,
468 .resume = _tas_resume,
469#endif
470};
471
472static int tas_init_codec(struct aoa_codec *codec)
473{
474 struct tas *tas = codec_to_tas(codec);
475 int err;
476
477 if (!tas->codec.gpio || !tas->codec.gpio->methods) {
478 printk(KERN_ERR PFX "gpios not assigned!!\n");
479 return -EINVAL;
480 }
481
482 if (tas_reset_init(tas)) {
483 printk(KERN_ERR PFX "tas failed to initialise\n");
484 return -ENXIO;
485 }
486
487 if (tas->codec.soundbus_dev->attach_codec(tas->codec.soundbus_dev,
488 aoa_get_card(),
489 &tas_codec_info, tas)) {
490 printk(KERN_ERR PFX "error attaching tas to soundbus\n");
491 return -ENODEV;
492 }
493
494 if (aoa_snd_device_new(SNDRV_DEV_LOWLEVEL, tas, &ops)) {
495 printk(KERN_ERR PFX "failed to create tas snd device!\n");
496 return -ENODEV;
497 }
498 err = aoa_snd_ctl_add(snd_ctl_new1(&volume_control, tas));
499 if (err)
500 goto error;
501
502 err = aoa_snd_ctl_add(snd_ctl_new1(&mute_control, tas));
503 if (err)
504 goto error;
505
506 err = aoa_snd_ctl_add(snd_ctl_new1(&pcm1_control, tas));
507 if (err)
508 goto error;
509
510 err = aoa_snd_ctl_add(snd_ctl_new1(&monitor_control, tas));
511 if (err)
512 goto error;
513
514 err = aoa_snd_ctl_add(snd_ctl_new1(&capture_source_control, tas));
515 if (err)
516 goto error;
517
518 return 0;
519 error:
520 tas->codec.soundbus_dev->detach_codec(tas->codec.soundbus_dev, tas);
521 snd_device_free(aoa_get_card(), tas);
522 return err;
523}
524
525static void tas_exit_codec(struct aoa_codec *codec)
526{
527 struct tas *tas = codec_to_tas(codec);
528
529 if (!tas->codec.soundbus_dev)
530 return;
531 tas->codec.soundbus_dev->detach_codec(tas->codec.soundbus_dev, tas);
532}
533
534
535static struct i2c_driver tas_driver;
536
537static int tas_create(struct i2c_adapter *adapter,
538 struct device_node *node,
539 int addr)
540{
541 struct tas *tas;
542
543 tas = kzalloc(sizeof(struct tas), GFP_KERNEL);
544
545 if (!tas)
546 return -ENOMEM;
547
548 tas->i2c.driver = &tas_driver;
549 tas->i2c.adapter = adapter;
550 tas->i2c.addr = addr;
551 strlcpy(tas->i2c.name, "tas audio codec", I2C_NAME_SIZE-1);
552
553 if (i2c_attach_client(&tas->i2c)) {
554 printk(KERN_ERR PFX "failed to attach to i2c\n");
555 goto fail;
556 }
557
558 strlcpy(tas->codec.name, "tas", MAX_CODEC_NAME_LEN-1);
559 tas->codec.owner = THIS_MODULE;
560 tas->codec.init = tas_init_codec;
561 tas->codec.exit = tas_exit_codec;
562 tas->codec.node = of_node_get(node);
563
564 if (aoa_codec_register(&tas->codec)) {
565 goto detach;
566 }
567 printk(KERN_DEBUG "snd-aoa-codec-tas: created and attached tas instance\n");
568 return 0;
569 detach:
570 i2c_detach_client(&tas->i2c);
571 fail:
572 kfree(tas);
573 return -EINVAL;
574}
575
576static int tas_i2c_attach(struct i2c_adapter *adapter)
577{
578 struct device_node *busnode, *dev = NULL;
579 struct pmac_i2c_bus *bus;
580
581 bus = pmac_i2c_adapter_to_bus(adapter);
582 if (bus == NULL)
583 return -ENODEV;
584 busnode = pmac_i2c_get_bus_node(bus);
585
586 while ((dev = of_get_next_child(busnode, dev)) != NULL) {
587 if (device_is_compatible(dev, "tas3004")) {
588 u32 *addr;
589 printk(KERN_DEBUG PFX "found tas3004\n");
590 addr = (u32 *) get_property(dev, "reg", NULL);
591 if (!addr)
592 continue;
593 return tas_create(adapter, dev, ((*addr) >> 1) & 0x7f);
594 }
595 /* older machines have no 'codec' node with a 'compatible'
596 * property that says 'tas3004', they just have a 'deq'
597 * node without any such property... */
598 if (strcmp(dev->name, "deq") == 0) {
599 u32 *_addr, addr;
600 printk(KERN_DEBUG PFX "found 'deq' node\n");
601 _addr = (u32 *) get_property(dev, "i2c-address", NULL);
602 if (!_addr)
603 continue;
604 addr = ((*_addr) >> 1) & 0x7f;
605 /* now, if the address doesn't match any of the two
606 * that a tas3004 can have, we cannot handle this.
607 * I doubt it ever happens but hey. */
608 if (addr != 0x34 && addr != 0x35)
609 continue;
610 return tas_create(adapter, dev, addr);
611 }
612 }
613 return -ENODEV;
614}
615
616static int tas_i2c_detach(struct i2c_client *client)
617{
618 struct tas *tas = container_of(client, struct tas, i2c);
619 int err;
620 u8 tmp = TAS_ACR_ANALOG_PDOWN;
621
622 if ((err = i2c_detach_client(client)))
623 return err;
624 aoa_codec_unregister(&tas->codec);
625 of_node_put(tas->codec.node);
626
627 /* power down codec chip */
628 tas_write_reg(tas, TAS_REG_ACR, 1, &tmp);
629
630 kfree(tas);
631 return 0;
632}
633
634static struct i2c_driver tas_driver = {
635 .driver = {
636 .name = "aoa_codec_tas",
637 .owner = THIS_MODULE,
638 },
639 .attach_adapter = tas_i2c_attach,
640 .detach_client = tas_i2c_detach,
641};
642
643static int __init tas_init(void)
644{
645 return i2c_add_driver(&tas_driver);
646}
647
648static void __exit tas_exit(void)
649{
650 i2c_del_driver(&tas_driver);
651}
652
653module_init(tas_init);
654module_exit(tas_exit);
diff --git a/sound/aoa/codecs/snd-aoa-codec-tas.h b/sound/aoa/codecs/snd-aoa-codec-tas.h
new file mode 100644
index 000000000000..daf81f45d83a
--- /dev/null
+++ b/sound/aoa/codecs/snd-aoa-codec-tas.h
@@ -0,0 +1,47 @@
1/*
2 * Apple Onboard Audio driver for tas codec (header)
3 *
4 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
5 *
6 * GPL v2, can be found in COPYING.
7 */
8#ifndef __SND_AOA_CODECTASH
9#define __SND_AOA_CODECTASH
10
11#define TAS_REG_MCS 0x01 /* main control */
12# define TAS_MCS_FASTLOAD (1<<7)
13# define TAS_MCS_SCLK64 (1<<6)
14# define TAS_MCS_SPORT_MODE_MASK (3<<4)
15# define TAS_MCS_SPORT_MODE_I2S (2<<4)
16# define TAS_MCS_SPORT_MODE_RJ (1<<4)
17# define TAS_MCS_SPORT_MODE_LJ (0<<4)
18# define TAS_MCS_SPORT_WL_MASK (3<<0)
19# define TAS_MCS_SPORT_WL_16BIT (0<<0)
20# define TAS_MCS_SPORT_WL_18BIT (1<<0)
21# define TAS_MCS_SPORT_WL_20BIT (2<<0)
22# define TAS_MCS_SPORT_WL_24BIT (3<<0)
23
24#define TAS_REG_DRC 0x02
25#define TAS_REG_VOL 0x04
26#define TAS_REG_TREBLE 0x05
27#define TAS_REG_BASS 0x06
28#define TAS_REG_LMIX 0x07
29#define TAS_REG_RMIX 0x08
30
31#define TAS_REG_ACR 0x40 /* analog control */
32# define TAS_ACR_B_MONAUREAL (1<<7)
33# define TAS_ACR_B_MON_SEL_RIGHT (1<<6)
34# define TAS_ACR_DEEMPH_MASK (3<<2)
35# define TAS_ACR_DEEMPH_OFF (0<<2)
36# define TAS_ACR_DEEMPH_48KHz (1<<2)
37# define TAS_ACR_DEEMPH_44KHz (2<<2)
38# define TAS_ACR_INPUT_B (1<<1)
39# define TAS_ACR_ANALOG_PDOWN (1<<0)
40
41#define TAS_REG_MCS2 0x43 /* main control 2 */
42# define TAS_MCS2_ALLPASS (1<<1)
43
44#define TAS_REG_LEFT_BIQUAD6 0x10
45#define TAS_REG_RIGHT_BIQUAD6 0x19
46
47#endif /* __SND_AOA_CODECTASH */
diff --git a/sound/aoa/codecs/snd-aoa-codec-toonie.c b/sound/aoa/codecs/snd-aoa-codec-toonie.c
new file mode 100644
index 000000000000..bcc555647e79
--- /dev/null
+++ b/sound/aoa/codecs/snd-aoa-codec-toonie.c
@@ -0,0 +1,141 @@
1/*
2 * Apple Onboard Audio driver for Toonie codec
3 *
4 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
5 *
6 * GPL v2, can be found in COPYING.
7 *
8 *
9 * This is a driver for the toonie codec chip. This chip is present
10 * on the Mac Mini and is nothing but a DAC.
11 */
12#include <linux/delay.h>
13#include <linux/module.h>
14MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
15MODULE_LICENSE("GPL");
16MODULE_DESCRIPTION("toonie codec driver for snd-aoa");
17
18#include "../aoa.h"
19#include "../soundbus/soundbus.h"
20
21
22#define PFX "snd-aoa-codec-toonie: "
23
24struct toonie {
25 struct aoa_codec codec;
26};
27#define codec_to_toonie(c) container_of(c, struct toonie, codec)
28
29static int toonie_dev_register(struct snd_device *dev)
30{
31 return 0;
32}
33
34static struct snd_device_ops ops = {
35 .dev_register = toonie_dev_register,
36};
37
38static struct transfer_info toonie_transfers[] = {
39 /* This thing *only* has analog output,
40 * the rates are taken from Info.plist
41 * from Darwin. */
42 {
43 .formats = SNDRV_PCM_FMTBIT_S16_BE |
44 SNDRV_PCM_FMTBIT_S24_BE,
45 .rates = SNDRV_PCM_RATE_32000 |
46 SNDRV_PCM_RATE_44100 |
47 SNDRV_PCM_RATE_48000 |
48 SNDRV_PCM_RATE_88200 |
49 SNDRV_PCM_RATE_96000,
50 },
51 {}
52};
53
54#ifdef CONFIG_PM
55static int toonie_suspend(struct codec_info_item *cii, pm_message_t state)
56{
57 /* can we turn it off somehow? */
58 return 0;
59}
60
61static int toonie_resume(struct codec_info_item *cii)
62{
63 return 0;
64}
65#endif /* CONFIG_PM */
66
67static struct codec_info toonie_codec_info = {
68 .transfers = toonie_transfers,
69 .sysclock_factor = 256,
70 .bus_factor = 64,
71 .owner = THIS_MODULE,
72#ifdef CONFIG_PM
73 .suspend = toonie_suspend,
74 .resume = toonie_resume,
75#endif
76};
77
78static int toonie_init_codec(struct aoa_codec *codec)
79{
80 struct toonie *toonie = codec_to_toonie(codec);
81
82 if (aoa_snd_device_new(SNDRV_DEV_LOWLEVEL, toonie, &ops)) {
83 printk(KERN_ERR PFX "failed to create toonie snd device!\n");
84 return -ENODEV;
85 }
86
87 /* nothing connected? what a joke! */
88 if (toonie->codec.connected != 1)
89 return -ENOTCONN;
90
91 if (toonie->codec.soundbus_dev->attach_codec(toonie->codec.soundbus_dev,
92 aoa_get_card(),
93 &toonie_codec_info, toonie)) {
94 printk(KERN_ERR PFX "error creating toonie pcm\n");
95 return -ENODEV;
96 }
97
98 return 0;
99}
100
101static void toonie_exit_codec(struct aoa_codec *codec)
102{
103 struct toonie *toonie = codec_to_toonie(codec);
104
105 if (!toonie->codec.soundbus_dev) {
106 printk(KERN_ERR PFX "toonie_exit_codec called without soundbus_dev!\n");
107 return;
108 }
109 toonie->codec.soundbus_dev->detach_codec(toonie->codec.soundbus_dev, toonie);
110}
111
112static struct toonie *toonie;
113
114static int __init toonie_init(void)
115{
116 toonie = kzalloc(sizeof(struct toonie), GFP_KERNEL);
117
118 if (!toonie)
119 return -ENOMEM;
120
121 strlcpy(toonie->codec.name, "toonie", sizeof(toonie->codec.name));
122 toonie->codec.owner = THIS_MODULE;
123 toonie->codec.init = toonie_init_codec;
124 toonie->codec.exit = toonie_exit_codec;
125
126 if (aoa_codec_register(&toonie->codec)) {
127 kfree(toonie);
128 return -EINVAL;
129 }
130
131 return 0;
132}
133
134static void __exit toonie_exit(void)
135{
136 aoa_codec_unregister(&toonie->codec);
137 kfree(toonie);
138}
139
140module_init(toonie_init);
141module_exit(toonie_exit);
diff --git a/sound/aoa/core/Makefile b/sound/aoa/core/Makefile
new file mode 100644
index 000000000000..62dc7287f663
--- /dev/null
+++ b/sound/aoa/core/Makefile
@@ -0,0 +1,5 @@
1obj-$(CONFIG_SND_AOA) += snd-aoa.o
2snd-aoa-objs := snd-aoa-core.o \
3 snd-aoa-alsa.o \
4 snd-aoa-gpio-pmf.o \
5 snd-aoa-gpio-feature.o
diff --git a/sound/aoa/core/snd-aoa-alsa.c b/sound/aoa/core/snd-aoa-alsa.c
new file mode 100644
index 000000000000..b42fdea77ed0
--- /dev/null
+++ b/sound/aoa/core/snd-aoa-alsa.c
@@ -0,0 +1,98 @@
1/*
2 * Apple Onboard Audio Alsa helpers
3 *
4 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
5 *
6 * GPL v2, can be found in COPYING.
7 */
8#include <linux/module.h>
9#include "snd-aoa-alsa.h"
10
11static int index = -1;
12module_param(index, int, 0444);
13MODULE_PARM_DESC(index, "index for AOA sound card.");
14
15static struct aoa_card *aoa_card;
16
17int aoa_alsa_init(char *name, struct module *mod)
18{
19 struct snd_card *alsa_card;
20 int err;
21
22 if (aoa_card)
23 /* cannot be EEXIST due to usage in aoa_fabric_register */
24 return -EBUSY;
25
26 alsa_card = snd_card_new(index, name, mod, sizeof(struct aoa_card));
27 if (!alsa_card)
28 return -ENOMEM;
29 aoa_card = alsa_card->private_data;
30 aoa_card->alsa_card = alsa_card;
31 strlcpy(alsa_card->driver, "AppleOnbdAudio", sizeof(alsa_card->driver));
32 strlcpy(alsa_card->shortname, name, sizeof(alsa_card->shortname));
33 strlcpy(alsa_card->longname, name, sizeof(alsa_card->longname));
34 strlcpy(alsa_card->mixername, name, sizeof(alsa_card->mixername));
35 err = snd_card_register(aoa_card->alsa_card);
36 if (err < 0) {
37 printk(KERN_ERR "snd-aoa: couldn't register alsa card\n");
38 snd_card_free(aoa_card->alsa_card);
39 aoa_card = NULL;
40 return err;
41 }
42 return 0;
43}
44
45struct snd_card *aoa_get_card(void)
46{
47 if (aoa_card)
48 return aoa_card->alsa_card;
49 return NULL;
50}
51EXPORT_SYMBOL_GPL(aoa_get_card);
52
53void aoa_alsa_cleanup(void)
54{
55 if (aoa_card) {
56 snd_card_free(aoa_card->alsa_card);
57 aoa_card = NULL;
58 }
59}
60
61int aoa_snd_device_new(snd_device_type_t type,
62 void * device_data, struct snd_device_ops * ops)
63{
64 struct snd_card *card = aoa_get_card();
65 int err;
66
67 if (!card) return -ENOMEM;
68
69 err = snd_device_new(card, type, device_data, ops);
70 if (err) {
71 printk(KERN_ERR "snd-aoa: failed to create snd device (%d)\n", err);
72 return err;
73 }
74 err = snd_device_register(card, device_data);
75 if (err) {
76 printk(KERN_ERR "snd-aoa: failed to register "
77 "snd device (%d)\n", err);
78 printk(KERN_ERR "snd-aoa: have you forgotten the "
79 "dev_register callback?\n");
80 snd_device_free(card, device_data);
81 }
82 return err;
83}
84EXPORT_SYMBOL_GPL(aoa_snd_device_new);
85
86int aoa_snd_ctl_add(struct snd_kcontrol* control)
87{
88 int err;
89
90 if (!aoa_card) return -ENODEV;
91
92 err = snd_ctl_add(aoa_card->alsa_card, control);
93 if (err)
94 printk(KERN_ERR "snd-aoa: failed to add alsa control (%d)\n",
95 err);
96 return err;
97}
98EXPORT_SYMBOL_GPL(aoa_snd_ctl_add);
diff --git a/sound/aoa/core/snd-aoa-alsa.h b/sound/aoa/core/snd-aoa-alsa.h
new file mode 100644
index 000000000000..660d2f1793bb
--- /dev/null
+++ b/sound/aoa/core/snd-aoa-alsa.h
@@ -0,0 +1,16 @@
1/*
2 * Apple Onboard Audio Alsa private helpers
3 *
4 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
5 *
6 * GPL v2, can be found in COPYING.
7 */
8
9#ifndef __SND_AOA_ALSA_H
10#define __SND_AOA_ALSA_H
11#include "../aoa.h"
12
13extern int aoa_alsa_init(char *name, struct module *mod);
14extern void aoa_alsa_cleanup(void);
15
16#endif /* __SND_AOA_ALSA_H */
diff --git a/sound/aoa/core/snd-aoa-core.c b/sound/aoa/core/snd-aoa-core.c
new file mode 100644
index 000000000000..ecd2d8263f2d
--- /dev/null
+++ b/sound/aoa/core/snd-aoa-core.c
@@ -0,0 +1,162 @@
1/*
2 * Apple Onboard Audio driver core
3 *
4 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
5 *
6 * GPL v2, can be found in COPYING.
7 */
8
9#include <linux/init.h>
10#include <linux/module.h>
11#include <linux/list.h>
12#include "../aoa.h"
13#include "snd-aoa-alsa.h"
14
15MODULE_DESCRIPTION("Apple Onboard Audio Sound Driver");
16MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
17MODULE_LICENSE("GPL");
18
19/* We allow only one fabric. This simplifies things,
20 * and more don't really make that much sense */
21static struct aoa_fabric *fabric;
22static LIST_HEAD(codec_list);
23
24static int attach_codec_to_fabric(struct aoa_codec *c)
25{
26 int err;
27
28 if (!try_module_get(c->owner))
29 return -EBUSY;
30 /* found_codec has to be assigned */
31 err = -ENOENT;
32 if (fabric->found_codec)
33 err = fabric->found_codec(c);
34 if (err) {
35 module_put(c->owner);
36 printk(KERN_ERR "snd-aoa: fabric didn't like codec %s\n",
37 c->name);
38 return err;
39 }
40 c->fabric = fabric;
41
42 err = 0;
43 if (c->init)
44 err = c->init(c);
45 if (err) {
46 printk(KERN_ERR "snd-aoa: codec %s didn't init\n", c->name);
47 c->fabric = NULL;
48 if (fabric->remove_codec)
49 fabric->remove_codec(c);
50 module_put(c->owner);
51 return err;
52 }
53 if (fabric->attached_codec)
54 fabric->attached_codec(c);
55 return 0;
56}
57
58int aoa_codec_register(struct aoa_codec *codec)
59{
60 int err = 0;
61
62 /* if there's a fabric already, we can tell if we
63 * will want to have this codec, so propagate error
64 * through. Otherwise, this will happen later... */
65 if (fabric)
66 err = attach_codec_to_fabric(codec);
67 if (!err)
68 list_add(&codec->list, &codec_list);
69 return err;
70}
71EXPORT_SYMBOL_GPL(aoa_codec_register);
72
73void aoa_codec_unregister(struct aoa_codec *codec)
74{
75 list_del(&codec->list);
76 if (codec->fabric && codec->exit)
77 codec->exit(codec);
78 if (fabric && fabric->remove_codec)
79 fabric->remove_codec(codec);
80 codec->fabric = NULL;
81 module_put(codec->owner);
82}
83EXPORT_SYMBOL_GPL(aoa_codec_unregister);
84
85int aoa_fabric_register(struct aoa_fabric *new_fabric)
86{
87 struct aoa_codec *c;
88 int err;
89
90 /* allow querying for presence of fabric
91 * (i.e. do this test first!) */
92 if (new_fabric == fabric) {
93 err = -EALREADY;
94 goto attach;
95 }
96 if (fabric)
97 return -EEXIST;
98 if (!new_fabric)
99 return -EINVAL;
100
101 err = aoa_alsa_init(new_fabric->name, new_fabric->owner);
102 if (err)
103 return err;
104
105 fabric = new_fabric;
106
107 attach:
108 list_for_each_entry(c, &codec_list, list) {
109 if (c->fabric != fabric)
110 attach_codec_to_fabric(c);
111 }
112 return err;
113}
114EXPORT_SYMBOL_GPL(aoa_fabric_register);
115
116void aoa_fabric_unregister(struct aoa_fabric *old_fabric)
117{
118 struct aoa_codec *c;
119
120 if (fabric != old_fabric)
121 return;
122
123 list_for_each_entry(c, &codec_list, list) {
124 if (c->fabric)
125 aoa_fabric_unlink_codec(c);
126 }
127
128 aoa_alsa_cleanup();
129
130 fabric = NULL;
131}
132EXPORT_SYMBOL_GPL(aoa_fabric_unregister);
133
134void aoa_fabric_unlink_codec(struct aoa_codec *codec)
135{
136 if (!codec->fabric) {
137 printk(KERN_ERR "snd-aoa: fabric unassigned "
138 "in aoa_fabric_unlink_codec\n");
139 dump_stack();
140 return;
141 }
142 if (codec->exit)
143 codec->exit(codec);
144 if (codec->fabric->remove_codec)
145 codec->fabric->remove_codec(codec);
146 codec->fabric = NULL;
147 module_put(codec->owner);
148}
149EXPORT_SYMBOL_GPL(aoa_fabric_unlink_codec);
150
151static int __init aoa_init(void)
152{
153 return 0;
154}
155
156static void __exit aoa_exit(void)
157{
158 aoa_alsa_cleanup();
159}
160
161module_init(aoa_init);
162module_exit(aoa_exit);
diff --git a/sound/aoa/core/snd-aoa-gpio-feature.c b/sound/aoa/core/snd-aoa-gpio-feature.c
new file mode 100644
index 000000000000..2c6eb7784cc9
--- /dev/null
+++ b/sound/aoa/core/snd-aoa-gpio-feature.c
@@ -0,0 +1,399 @@
1/*
2 * Apple Onboard Audio feature call GPIO control
3 *
4 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
5 *
6 * GPL v2, can be found in COPYING.
7 *
8 * This file contains the GPIO control routines for
9 * direct (through feature calls) access to the GPIO
10 * registers.
11 */
12
13#include <asm/pmac_feature.h>
14#include <linux/interrupt.h>
15#include "../aoa.h"
16
17/* TODO: these are 20 global variables
18 * that aren't used on most machines...
19 * Move them into a dynamically allocated
20 * structure and use that.
21 */
22
23/* these are the GPIO numbers (register addresses as offsets into
24 * the GPIO space) */
25static int headphone_mute_gpio;
26static int amp_mute_gpio;
27static int lineout_mute_gpio;
28static int hw_reset_gpio;
29static int lineout_detect_gpio;
30static int headphone_detect_gpio;
31static int linein_detect_gpio;
32
33/* see the SWITCH_GPIO macro */
34static int headphone_mute_gpio_activestate;
35static int amp_mute_gpio_activestate;
36static int lineout_mute_gpio_activestate;
37static int hw_reset_gpio_activestate;
38static int lineout_detect_gpio_activestate;
39static int headphone_detect_gpio_activestate;
40static int linein_detect_gpio_activestate;
41
42/* node pointers that we save when getting the GPIO number
43 * to get the interrupt later */
44static struct device_node *lineout_detect_node;
45static struct device_node *linein_detect_node;
46static struct device_node *headphone_detect_node;
47
48static int lineout_detect_irq;
49static int linein_detect_irq;
50static int headphone_detect_irq;
51
52static struct device_node *get_gpio(char *name,
53 char *altname,
54 int *gpioptr,
55 int *gpioactiveptr)
56{
57 struct device_node *np, *gpio;
58 u32 *reg;
59 char *audio_gpio;
60
61 *gpioptr = -1;
62
63 /* check if we can get it the easy way ... */
64 np = of_find_node_by_name(NULL, name);
65 if (!np) {
66 /* some machines have only gpioX/extint-gpioX nodes,
67 * and an audio-gpio property saying what it is ...
68 * So what we have to do is enumerate all children
69 * of the gpio node and check them all. */
70 gpio = of_find_node_by_name(NULL, "gpio");
71 if (!gpio)
72 return NULL;
73 while ((np = of_get_next_child(gpio, np))) {
74 audio_gpio = get_property(np, "audio-gpio", NULL);
75 if (!audio_gpio)
76 continue;
77 if (strcmp(audio_gpio, name) == 0)
78 break;
79 if (altname && (strcmp(audio_gpio, altname) == 0))
80 break;
81 }
82 /* still not found, assume not there */
83 if (!np)
84 return NULL;
85 }
86
87 reg = (u32 *)get_property(np, "reg", NULL);
88 if (!reg)
89 return NULL;
90
91 *gpioptr = *reg;
92
93 /* this is a hack, usually the GPIOs 'reg' property
94 * should have the offset based from the GPIO space
95 * which is at 0x50, but apparently not always... */
96 if (*gpioptr < 0x50)
97 *gpioptr += 0x50;
98
99 reg = (u32 *)get_property(np, "audio-gpio-active-state", NULL);
100 if (!reg)
101 /* Apple seems to default to 1, but
102 * that doesn't seem right at least on most
103 * machines. So until proven that the opposite
104 * is necessary, we default to 0
105 * (which, incidentally, snd-powermac also does...) */
106 *gpioactiveptr = 0;
107 else
108 *gpioactiveptr = *reg;
109
110 return np;
111}
112
113static void get_irq(struct device_node * np, int *irqptr)
114{
115 *irqptr = -1;
116 if (!np)
117 return;
118 if (np->n_intrs != 1)
119 return;
120 *irqptr = np->intrs[0].line;
121}
122
123/* 0x4 is outenable, 0x1 is out, thus 4 or 5 */
124#define SWITCH_GPIO(name, v, on) \
125 (((v)&~1) | ((on)? \
126 (name##_gpio_activestate==0?4:5): \
127 (name##_gpio_activestate==0?5:4)))
128
129#define FTR_GPIO(name, bit) \
130static void ftr_gpio_set_##name(struct gpio_runtime *rt, int on)\
131{ \
132 int v; \
133 \
134 if (unlikely(!rt)) return; \
135 \
136 if (name##_mute_gpio < 0) \
137 return; \
138 \
139 v = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, \
140 name##_mute_gpio, \
141 0); \
142 \
143 /* muted = !on... */ \
144 v = SWITCH_GPIO(name##_mute, v, !on); \
145 \
146 pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, \
147 name##_mute_gpio, v); \
148 \
149 rt->implementation_private &= ~(1<<bit); \
150 rt->implementation_private |= (!!on << bit); \
151} \
152static int ftr_gpio_get_##name(struct gpio_runtime *rt) \
153{ \
154 if (unlikely(!rt)) return 0; \
155 return (rt->implementation_private>>bit)&1; \
156}
157
158FTR_GPIO(headphone, 0);
159FTR_GPIO(amp, 1);
160FTR_GPIO(lineout, 2);
161
162static void ftr_gpio_set_hw_reset(struct gpio_runtime *rt, int on)
163{
164 int v;
165
166 if (unlikely(!rt)) return;
167 if (hw_reset_gpio < 0)
168 return;
169
170 v = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL,
171 hw_reset_gpio, 0);
172 v = SWITCH_GPIO(hw_reset, v, on);
173 pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL,
174 hw_reset_gpio, v);
175}
176
177static void ftr_gpio_all_amps_off(struct gpio_runtime *rt)
178{
179 int saved;
180
181 if (unlikely(!rt)) return;
182 saved = rt->implementation_private;
183 ftr_gpio_set_headphone(rt, 0);
184 ftr_gpio_set_amp(rt, 0);
185 ftr_gpio_set_lineout(rt, 0);
186 rt->implementation_private = saved;
187}
188
189static void ftr_gpio_all_amps_restore(struct gpio_runtime *rt)
190{
191 int s;
192
193 if (unlikely(!rt)) return;
194 s = rt->implementation_private;
195 ftr_gpio_set_headphone(rt, (s>>0)&1);
196 ftr_gpio_set_amp(rt, (s>>1)&1);
197 ftr_gpio_set_lineout(rt, (s>>2)&1);
198}
199
200static void ftr_handle_notify(void *data)
201{
202 struct gpio_notification *notif = data;
203
204 mutex_lock(&notif->mutex);
205 if (notif->notify)
206 notif->notify(notif->data);
207 mutex_unlock(&notif->mutex);
208}
209
210static void ftr_gpio_init(struct gpio_runtime *rt)
211{
212 get_gpio("headphone-mute", NULL,
213 &headphone_mute_gpio,
214 &headphone_mute_gpio_activestate);
215 get_gpio("amp-mute", NULL,
216 &amp_mute_gpio,
217 &amp_mute_gpio_activestate);
218 get_gpio("lineout-mute", NULL,
219 &lineout_mute_gpio,
220 &lineout_mute_gpio_activestate);
221 get_gpio("hw-reset", "audio-hw-reset",
222 &hw_reset_gpio,
223 &hw_reset_gpio_activestate);
224
225 headphone_detect_node = get_gpio("headphone-detect", NULL,
226 &headphone_detect_gpio,
227 &headphone_detect_gpio_activestate);
228 /* go Apple, and thanks for giving these different names
229 * across the board... */
230 lineout_detect_node = get_gpio("lineout-detect", "line-output-detect",
231 &lineout_detect_gpio,
232 &lineout_detect_gpio_activestate);
233 linein_detect_node = get_gpio("linein-detect", "line-input-detect",
234 &linein_detect_gpio,
235 &linein_detect_gpio_activestate);
236
237 get_irq(headphone_detect_node, &headphone_detect_irq);
238 get_irq(lineout_detect_node, &lineout_detect_irq);
239 get_irq(linein_detect_node, &linein_detect_irq);
240
241 ftr_gpio_all_amps_off(rt);
242 rt->implementation_private = 0;
243 INIT_WORK(&rt->headphone_notify.work, ftr_handle_notify,
244 &rt->headphone_notify);
245 INIT_WORK(&rt->line_in_notify.work, ftr_handle_notify,
246 &rt->line_in_notify);
247 INIT_WORK(&rt->line_out_notify.work, ftr_handle_notify,
248 &rt->line_out_notify);
249 mutex_init(&rt->headphone_notify.mutex);
250 mutex_init(&rt->line_in_notify.mutex);
251 mutex_init(&rt->line_out_notify.mutex);
252}
253
254static void ftr_gpio_exit(struct gpio_runtime *rt)
255{
256 ftr_gpio_all_amps_off(rt);
257 rt->implementation_private = 0;
258 if (rt->headphone_notify.notify)
259 free_irq(headphone_detect_irq, &rt->headphone_notify);
260 if (rt->line_in_notify.gpio_private)
261 free_irq(linein_detect_irq, &rt->line_in_notify);
262 if (rt->line_out_notify.gpio_private)
263 free_irq(lineout_detect_irq, &rt->line_out_notify);
264 cancel_delayed_work(&rt->headphone_notify.work);
265 cancel_delayed_work(&rt->line_in_notify.work);
266 cancel_delayed_work(&rt->line_out_notify.work);
267 flush_scheduled_work();
268 mutex_destroy(&rt->headphone_notify.mutex);
269 mutex_destroy(&rt->line_in_notify.mutex);
270 mutex_destroy(&rt->line_out_notify.mutex);
271}
272
273static irqreturn_t ftr_handle_notify_irq(int xx,
274 void *data,
275 struct pt_regs *regs)
276{
277 struct gpio_notification *notif = data;
278
279 schedule_work(&notif->work);
280
281 return IRQ_HANDLED;
282}
283
284static int ftr_set_notify(struct gpio_runtime *rt,
285 enum notify_type type,
286 notify_func_t notify,
287 void *data)
288{
289 struct gpio_notification *notif;
290 notify_func_t old;
291 int irq;
292 char *name;
293 int err = -EBUSY;
294
295 switch (type) {
296 case AOA_NOTIFY_HEADPHONE:
297 notif = &rt->headphone_notify;
298 name = "headphone-detect";
299 irq = headphone_detect_irq;
300 break;
301 case AOA_NOTIFY_LINE_IN:
302 notif = &rt->line_in_notify;
303 name = "linein-detect";
304 irq = linein_detect_irq;
305 break;
306 case AOA_NOTIFY_LINE_OUT:
307 notif = &rt->line_out_notify;
308 name = "lineout-detect";
309 irq = lineout_detect_irq;
310 break;
311 default:
312 return -EINVAL;
313 }
314
315 if (irq == -1)
316 return -ENODEV;
317
318 mutex_lock(&notif->mutex);
319
320 old = notif->notify;
321
322 if (!old && !notify) {
323 err = 0;
324 goto out_unlock;
325 }
326
327 if (old && notify) {
328 if (old == notify && notif->data == data)
329 err = 0;
330 goto out_unlock;
331 }
332
333 if (old && !notify)
334 free_irq(irq, notif);
335
336 if (!old && notify) {
337 err = request_irq(irq, ftr_handle_notify_irq, 0, name, notif);
338 if (err)
339 goto out_unlock;
340 }
341
342 notif->notify = notify;
343 notif->data = data;
344
345 err = 0;
346 out_unlock:
347 mutex_unlock(&notif->mutex);
348 return err;
349}
350
351static int ftr_get_detect(struct gpio_runtime *rt,
352 enum notify_type type)
353{
354 int gpio, ret, active;
355
356 switch (type) {
357 case AOA_NOTIFY_HEADPHONE:
358 gpio = headphone_detect_gpio;
359 active = headphone_detect_gpio_activestate;
360 break;
361 case AOA_NOTIFY_LINE_IN:
362 gpio = linein_detect_gpio;
363 active = linein_detect_gpio_activestate;
364 break;
365 case AOA_NOTIFY_LINE_OUT:
366 gpio = lineout_detect_gpio;
367 active = lineout_detect_gpio_activestate;
368 break;
369 default:
370 return -EINVAL;
371 }
372
373 if (gpio == -1)
374 return -ENODEV;
375
376 ret = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, gpio, 0);
377 if (ret < 0)
378 return ret;
379 return ((ret >> 1) & 1) == active;
380}
381
382static struct gpio_methods methods = {
383 .init = ftr_gpio_init,
384 .exit = ftr_gpio_exit,
385 .all_amps_off = ftr_gpio_all_amps_off,
386 .all_amps_restore = ftr_gpio_all_amps_restore,
387 .set_headphone = ftr_gpio_set_headphone,
388 .set_speakers = ftr_gpio_set_amp,
389 .set_lineout = ftr_gpio_set_lineout,
390 .set_hw_reset = ftr_gpio_set_hw_reset,
391 .get_headphone = ftr_gpio_get_headphone,
392 .get_speakers = ftr_gpio_get_amp,
393 .get_lineout = ftr_gpio_get_lineout,
394 .set_notify = ftr_set_notify,
395 .get_detect = ftr_get_detect,
396};
397
398struct gpio_methods *ftr_gpio_methods = &methods;
399EXPORT_SYMBOL_GPL(ftr_gpio_methods);
diff --git a/sound/aoa/core/snd-aoa-gpio-pmf.c b/sound/aoa/core/snd-aoa-gpio-pmf.c
new file mode 100644
index 000000000000..0e9b9bb2a6de
--- /dev/null
+++ b/sound/aoa/core/snd-aoa-gpio-pmf.c
@@ -0,0 +1,246 @@
1/*
2 * Apple Onboard Audio pmf GPIOs
3 *
4 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
5 *
6 * GPL v2, can be found in COPYING.
7 */
8
9#include <asm/pmac_feature.h>
10#include <asm/pmac_pfunc.h>
11#include "../aoa.h"
12
13#define PMF_GPIO(name, bit) \
14static void pmf_gpio_set_##name(struct gpio_runtime *rt, int on)\
15{ \
16 struct pmf_args args = { .count = 1, .u[0].v = !on }; \
17 \
18 if (unlikely(!rt)) return; \
19 pmf_call_function(rt->node, #name "-mute", &args); \
20 rt->implementation_private &= ~(1<<bit); \
21 rt->implementation_private |= (!!on << bit); \
22} \
23static int pmf_gpio_get_##name(struct gpio_runtime *rt) \
24{ \
25 if (unlikely(!rt)) return 0; \
26 return (rt->implementation_private>>bit)&1; \
27}
28
29PMF_GPIO(headphone, 0);
30PMF_GPIO(amp, 1);
31PMF_GPIO(lineout, 2);
32
33static void pmf_gpio_set_hw_reset(struct gpio_runtime *rt, int on)
34{
35 struct pmf_args args = { .count = 1, .u[0].v = !!on };
36
37 if (unlikely(!rt)) return;
38 pmf_call_function(rt->node, "hw-reset", &args);
39}
40
41static void pmf_gpio_all_amps_off(struct gpio_runtime *rt)
42{
43 int saved;
44
45 if (unlikely(!rt)) return;
46 saved = rt->implementation_private;
47 pmf_gpio_set_headphone(rt, 0);
48 pmf_gpio_set_amp(rt, 0);
49 pmf_gpio_set_lineout(rt, 0);
50 rt->implementation_private = saved;
51}
52
53static void pmf_gpio_all_amps_restore(struct gpio_runtime *rt)
54{
55 int s;
56
57 if (unlikely(!rt)) return;
58 s = rt->implementation_private;
59 pmf_gpio_set_headphone(rt, (s>>0)&1);
60 pmf_gpio_set_amp(rt, (s>>1)&1);
61 pmf_gpio_set_lineout(rt, (s>>2)&1);
62}
63
64static void pmf_handle_notify(void *data)
65{
66 struct gpio_notification *notif = data;
67
68 mutex_lock(&notif->mutex);
69 if (notif->notify)
70 notif->notify(notif->data);
71 mutex_unlock(&notif->mutex);
72}
73
74static void pmf_gpio_init(struct gpio_runtime *rt)
75{
76 pmf_gpio_all_amps_off(rt);
77 rt->implementation_private = 0;
78 INIT_WORK(&rt->headphone_notify.work, pmf_handle_notify,
79 &rt->headphone_notify);
80 INIT_WORK(&rt->line_in_notify.work, pmf_handle_notify,
81 &rt->line_in_notify);
82 INIT_WORK(&rt->line_out_notify.work, pmf_handle_notify,
83 &rt->line_out_notify);
84 mutex_init(&rt->headphone_notify.mutex);
85 mutex_init(&rt->line_in_notify.mutex);
86 mutex_init(&rt->line_out_notify.mutex);
87}
88
89static void pmf_gpio_exit(struct gpio_runtime *rt)
90{
91 pmf_gpio_all_amps_off(rt);
92 rt->implementation_private = 0;
93
94 if (rt->headphone_notify.gpio_private)
95 pmf_unregister_irq_client(rt->headphone_notify.gpio_private);
96 if (rt->line_in_notify.gpio_private)
97 pmf_unregister_irq_client(rt->line_in_notify.gpio_private);
98 if (rt->line_out_notify.gpio_private)
99 pmf_unregister_irq_client(rt->line_out_notify.gpio_private);
100
101 /* make sure no work is pending before freeing
102 * all things */
103 cancel_delayed_work(&rt->headphone_notify.work);
104 cancel_delayed_work(&rt->line_in_notify.work);
105 cancel_delayed_work(&rt->line_out_notify.work);
106 flush_scheduled_work();
107
108 mutex_destroy(&rt->headphone_notify.mutex);
109 mutex_destroy(&rt->line_in_notify.mutex);
110 mutex_destroy(&rt->line_out_notify.mutex);
111
112 if (rt->headphone_notify.gpio_private)
113 kfree(rt->headphone_notify.gpio_private);
114 if (rt->line_in_notify.gpio_private)
115 kfree(rt->line_in_notify.gpio_private);
116 if (rt->line_out_notify.gpio_private)
117 kfree(rt->line_out_notify.gpio_private);
118}
119
120static void pmf_handle_notify_irq(void *data)
121{
122 struct gpio_notification *notif = data;
123
124 schedule_work(&notif->work);
125}
126
127static int pmf_set_notify(struct gpio_runtime *rt,
128 enum notify_type type,
129 notify_func_t notify,
130 void *data)
131{
132 struct gpio_notification *notif;
133 notify_func_t old;
134 struct pmf_irq_client *irq_client;
135 char *name;
136 int err = -EBUSY;
137
138 switch (type) {
139 case AOA_NOTIFY_HEADPHONE:
140 notif = &rt->headphone_notify;
141 name = "headphone-detect";
142 break;
143 case AOA_NOTIFY_LINE_IN:
144 notif = &rt->line_in_notify;
145 name = "linein-detect";
146 break;
147 case AOA_NOTIFY_LINE_OUT:
148 notif = &rt->line_out_notify;
149 name = "lineout-detect";
150 break;
151 default:
152 return -EINVAL;
153 }
154
155 mutex_lock(&notif->mutex);
156
157 old = notif->notify;
158
159 if (!old && !notify) {
160 err = 0;
161 goto out_unlock;
162 }
163
164 if (old && notify) {
165 if (old == notify && notif->data == data)
166 err = 0;
167 goto out_unlock;
168 }
169
170 if (old && !notify) {
171 irq_client = notif->gpio_private;
172 pmf_unregister_irq_client(irq_client);
173 kfree(irq_client);
174 notif->gpio_private = NULL;
175 }
176 if (!old && notify) {
177 irq_client = kzalloc(sizeof(struct pmf_irq_client),
178 GFP_KERNEL);
179 irq_client->data = notif;
180 irq_client->handler = pmf_handle_notify_irq;
181 irq_client->owner = THIS_MODULE;
182 err = pmf_register_irq_client(rt->node,
183 name,
184 irq_client);
185 if (err) {
186 printk(KERN_ERR "snd-aoa: gpio layer failed to"
187 " register %s irq (%d)\n", name, err);
188 kfree(irq_client);
189 goto out_unlock;
190 }
191 notif->gpio_private = irq_client;
192 }
193 notif->notify = notify;
194 notif->data = data;
195
196 err = 0;
197 out_unlock:
198 mutex_unlock(&notif->mutex);
199 return err;
200}
201
202static int pmf_get_detect(struct gpio_runtime *rt,
203 enum notify_type type)
204{
205 char *name;
206 int err = -EBUSY, ret;
207 struct pmf_args args = { .count = 1, .u[0].p = &ret };
208
209 switch (type) {
210 case AOA_NOTIFY_HEADPHONE:
211 name = "headphone-detect";
212 break;
213 case AOA_NOTIFY_LINE_IN:
214 name = "linein-detect";
215 break;
216 case AOA_NOTIFY_LINE_OUT:
217 name = "lineout-detect";
218 break;
219 default:
220 return -EINVAL;
221 }
222
223 err = pmf_call_function(rt->node, name, &args);
224 if (err)
225 return err;
226 return ret;
227}
228
229static struct gpio_methods methods = {
230 .init = pmf_gpio_init,
231 .exit = pmf_gpio_exit,
232 .all_amps_off = pmf_gpio_all_amps_off,
233 .all_amps_restore = pmf_gpio_all_amps_restore,
234 .set_headphone = pmf_gpio_set_headphone,
235 .set_speakers = pmf_gpio_set_amp,
236 .set_lineout = pmf_gpio_set_lineout,
237 .set_hw_reset = pmf_gpio_set_hw_reset,
238 .get_headphone = pmf_gpio_get_headphone,
239 .get_speakers = pmf_gpio_get_amp,
240 .get_lineout = pmf_gpio_get_lineout,
241 .set_notify = pmf_set_notify,
242 .get_detect = pmf_get_detect,
243};
244
245struct gpio_methods *pmf_gpio_methods = &methods;
246EXPORT_SYMBOL_GPL(pmf_gpio_methods);
diff --git a/sound/aoa/fabrics/Kconfig b/sound/aoa/fabrics/Kconfig
new file mode 100644
index 000000000000..c3bc7705c86a
--- /dev/null
+++ b/sound/aoa/fabrics/Kconfig
@@ -0,0 +1,12 @@
1config SND_AOA_FABRIC_LAYOUT
2 tristate "layout-id fabric"
3 depends SND_AOA
4 select SND_AOA_SOUNDBUS
5 select SND_AOA_SOUNDBUS_I2S
6 ---help---
7 This enables the layout-id fabric for the Apple Onboard
8 Audio driver, the module holding it all together
9 based on the device-tree's layout-id property.
10
11 If you are unsure and have a later Apple machine,
12 compile it as a module.
diff --git a/sound/aoa/fabrics/Makefile b/sound/aoa/fabrics/Makefile
new file mode 100644
index 000000000000..55fc5e7e52cf
--- /dev/null
+++ b/sound/aoa/fabrics/Makefile
@@ -0,0 +1 @@
obj-$(CONFIG_SND_AOA_FABRIC_LAYOUT) += snd-aoa-fabric-layout.o
diff --git a/sound/aoa/fabrics/snd-aoa-fabric-layout.c b/sound/aoa/fabrics/snd-aoa-fabric-layout.c
new file mode 100644
index 000000000000..04a7238e9494
--- /dev/null
+++ b/sound/aoa/fabrics/snd-aoa-fabric-layout.c
@@ -0,0 +1,1109 @@
1/*
2 * Apple Onboard Audio driver -- layout fabric
3 *
4 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
5 *
6 * GPL v2, can be found in COPYING.
7 *
8 *
9 * This fabric module looks for sound codecs
10 * based on the layout-id property in the device tree.
11 *
12 */
13
14#include <asm/prom.h>
15#include <linux/list.h>
16#include <linux/module.h>
17#include "../aoa.h"
18#include "../soundbus/soundbus.h"
19
20MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
21MODULE_LICENSE("GPL");
22MODULE_DESCRIPTION("Layout-ID fabric for snd-aoa");
23
24#define MAX_CODECS_PER_BUS 2
25
26/* These are the connections the layout fabric
27 * knows about. It doesn't really care about the
28 * input ones, but I thought I'd separate them
29 * to give them proper names. The thing is that
30 * Apple usually will distinguish the active output
31 * by GPIOs, while the active input is set directly
32 * on the codec. Hence we here tell the codec what
33 * we think is connected. This information is hard-
34 * coded below ... */
35#define CC_SPEAKERS (1<<0)
36#define CC_HEADPHONE (1<<1)
37#define CC_LINEOUT (1<<2)
38#define CC_DIGITALOUT (1<<3)
39#define CC_LINEIN (1<<4)
40#define CC_MICROPHONE (1<<5)
41#define CC_DIGITALIN (1<<6)
42/* pretty bogus but users complain...
43 * This is a flag saying that the LINEOUT
44 * should be renamed to HEADPHONE.
45 * be careful with input detection! */
46#define CC_LINEOUT_LABELLED_HEADPHONE (1<<7)
47
48struct codec_connection {
49 /* CC_ flags from above */
50 int connected;
51 /* codec dependent bit to be set in the aoa_codec.connected field.
52 * This intentionally doesn't have any generic flags because the
53 * fabric has to know the codec anyway and all codecs might have
54 * different connectors */
55 int codec_bit;
56};
57
58struct codec_connect_info {
59 char *name;
60 struct codec_connection *connections;
61};
62
63#define LAYOUT_FLAG_COMBO_LINEOUT_SPDIF (1<<0)
64
65struct layout {
66 unsigned int layout_id;
67 struct codec_connect_info codecs[MAX_CODECS_PER_BUS];
68 int flags;
69
70 /* if busname is not assigned, we use 'Master' below,
71 * so that our layout table doesn't need to be filled
72 * too much.
73 * We only assign these two if we expect to find more
74 * than one soundbus, i.e. on those machines with
75 * multiple layout-ids */
76 char *busname;
77 int pcmid;
78};
79
80MODULE_ALIAS("sound-layout-41");
81MODULE_ALIAS("sound-layout-45");
82MODULE_ALIAS("sound-layout-51");
83MODULE_ALIAS("sound-layout-58");
84MODULE_ALIAS("sound-layout-60");
85MODULE_ALIAS("sound-layout-61");
86MODULE_ALIAS("sound-layout-64");
87MODULE_ALIAS("sound-layout-65");
88MODULE_ALIAS("sound-layout-68");
89MODULE_ALIAS("sound-layout-69");
90MODULE_ALIAS("sound-layout-70");
91MODULE_ALIAS("sound-layout-72");
92MODULE_ALIAS("sound-layout-80");
93MODULE_ALIAS("sound-layout-82");
94MODULE_ALIAS("sound-layout-84");
95MODULE_ALIAS("sound-layout-86");
96MODULE_ALIAS("sound-layout-92");
97
98/* onyx with all but microphone connected */
99static struct codec_connection onyx_connections_nomic[] = {
100 {
101 .connected = CC_SPEAKERS | CC_HEADPHONE | CC_LINEOUT,
102 .codec_bit = 0,
103 },
104 {
105 .connected = CC_DIGITALOUT,
106 .codec_bit = 1,
107 },
108 {
109 .connected = CC_LINEIN,
110 .codec_bit = 2,
111 },
112 {} /* terminate array by .connected == 0 */
113};
114
115/* onyx on machines without headphone */
116static struct codec_connection onyx_connections_noheadphones[] = {
117 {
118 .connected = CC_SPEAKERS | CC_LINEOUT |
119 CC_LINEOUT_LABELLED_HEADPHONE,
120 .codec_bit = 0,
121 },
122 {
123 .connected = CC_DIGITALOUT,
124 .codec_bit = 1,
125 },
126 /* FIXME: are these correct? probably not for all the machines
127 * below ... If not this will need separating. */
128 {
129 .connected = CC_LINEIN,
130 .codec_bit = 2,
131 },
132 {
133 .connected = CC_MICROPHONE,
134 .codec_bit = 3,
135 },
136 {} /* terminate array by .connected == 0 */
137};
138
139/* onyx on machines with real line-out */
140static struct codec_connection onyx_connections_reallineout[] = {
141 {
142 .connected = CC_SPEAKERS | CC_LINEOUT | CC_HEADPHONE,
143 .codec_bit = 0,
144 },
145 {
146 .connected = CC_DIGITALOUT,
147 .codec_bit = 1,
148 },
149 {
150 .connected = CC_LINEIN,
151 .codec_bit = 2,
152 },
153 {} /* terminate array by .connected == 0 */
154};
155
156/* tas on machines without line out */
157static struct codec_connection tas_connections_nolineout[] = {
158 {
159 .connected = CC_SPEAKERS | CC_HEADPHONE,
160 .codec_bit = 0,
161 },
162 {
163 .connected = CC_LINEIN,
164 .codec_bit = 2,
165 },
166 {
167 .connected = CC_MICROPHONE,
168 .codec_bit = 3,
169 },
170 {} /* terminate array by .connected == 0 */
171};
172
173/* tas on machines with neither line out nor line in */
174static struct codec_connection tas_connections_noline[] = {
175 {
176 .connected = CC_SPEAKERS | CC_HEADPHONE,
177 .codec_bit = 0,
178 },
179 {
180 .connected = CC_MICROPHONE,
181 .codec_bit = 3,
182 },
183 {} /* terminate array by .connected == 0 */
184};
185
186/* tas on machines without microphone */
187static struct codec_connection tas_connections_nomic[] = {
188 {
189 .connected = CC_SPEAKERS | CC_HEADPHONE | CC_LINEOUT,
190 .codec_bit = 0,
191 },
192 {
193 .connected = CC_LINEIN,
194 .codec_bit = 2,
195 },
196 {} /* terminate array by .connected == 0 */
197};
198
199/* tas on machines with everything connected */
200static struct codec_connection tas_connections_all[] = {
201 {
202 .connected = CC_SPEAKERS | CC_HEADPHONE | CC_LINEOUT,
203 .codec_bit = 0,
204 },
205 {
206 .connected = CC_LINEIN,
207 .codec_bit = 2,
208 },
209 {
210 .connected = CC_MICROPHONE,
211 .codec_bit = 3,
212 },
213 {} /* terminate array by .connected == 0 */
214};
215
216static struct codec_connection toonie_connections[] = {
217 {
218 .connected = CC_SPEAKERS | CC_HEADPHONE,
219 .codec_bit = 0,
220 },
221 {} /* terminate array by .connected == 0 */
222};
223
224static struct codec_connection topaz_input[] = {
225 {
226 .connected = CC_DIGITALIN,
227 .codec_bit = 0,
228 },
229 {} /* terminate array by .connected == 0 */
230};
231
232static struct codec_connection topaz_output[] = {
233 {
234 .connected = CC_DIGITALOUT,
235 .codec_bit = 1,
236 },
237 {} /* terminate array by .connected == 0 */
238};
239
240static struct codec_connection topaz_inout[] = {
241 {
242 .connected = CC_DIGITALIN,
243 .codec_bit = 0,
244 },
245 {
246 .connected = CC_DIGITALOUT,
247 .codec_bit = 1,
248 },
249 {} /* terminate array by .connected == 0 */
250};
251
252static struct layout layouts[] = {
253 /* last PowerBooks (15" Oct 2005) */
254 { .layout_id = 82,
255 .flags = LAYOUT_FLAG_COMBO_LINEOUT_SPDIF,
256 .codecs[0] = {
257 .name = "onyx",
258 .connections = onyx_connections_noheadphones,
259 },
260 .codecs[1] = {
261 .name = "topaz",
262 .connections = topaz_input,
263 },
264 },
265 /* PowerMac9,1 */
266 { .layout_id = 60,
267 .codecs[0] = {
268 .name = "onyx",
269 .connections = onyx_connections_reallineout,
270 },
271 },
272 /* PowerMac9,1 */
273 { .layout_id = 61,
274 .codecs[0] = {
275 .name = "topaz",
276 .connections = topaz_input,
277 },
278 },
279 /* PowerBook5,7 */
280 { .layout_id = 64,
281 .flags = LAYOUT_FLAG_COMBO_LINEOUT_SPDIF,
282 .codecs[0] = {
283 .name = "onyx",
284 .connections = onyx_connections_noheadphones,
285 },
286 },
287 /* PowerBook5,7 */
288 { .layout_id = 65,
289 .codecs[0] = {
290 .name = "topaz",
291 .connections = topaz_input,
292 },
293 },
294 /* PowerBook5,9 [17" Oct 2005] */
295 { .layout_id = 84,
296 .flags = LAYOUT_FLAG_COMBO_LINEOUT_SPDIF,
297 .codecs[0] = {
298 .name = "onyx",
299 .connections = onyx_connections_noheadphones,
300 },
301 .codecs[1] = {
302 .name = "topaz",
303 .connections = topaz_input,
304 },
305 },
306 /* PowerMac8,1 */
307 { .layout_id = 45,
308 .codecs[0] = {
309 .name = "onyx",
310 .connections = onyx_connections_noheadphones,
311 },
312 .codecs[1] = {
313 .name = "topaz",
314 .connections = topaz_input,
315 },
316 },
317 /* Quad PowerMac (analog in, analog/digital out) */
318 { .layout_id = 68,
319 .codecs[0] = {
320 .name = "onyx",
321 .connections = onyx_connections_nomic,
322 },
323 },
324 /* Quad PowerMac (digital in) */
325 { .layout_id = 69,
326 .codecs[0] = {
327 .name = "topaz",
328 .connections = topaz_input,
329 },
330 .busname = "digital in", .pcmid = 1 },
331 /* Early 2005 PowerBook (PowerBook 5,6) */
332 { .layout_id = 70,
333 .codecs[0] = {
334 .name = "tas",
335 .connections = tas_connections_nolineout,
336 },
337 },
338 /* PowerBook 5,4 */
339 { .layout_id = 51,
340 .codecs[0] = {
341 .name = "tas",
342 .connections = tas_connections_nolineout,
343 },
344 },
345 /* PowerBook6,7 */
346 { .layout_id = 80,
347 .codecs[0] = {
348 .name = "tas",
349 .connections = tas_connections_noline,
350 },
351 },
352 /* PowerBook6,8 */
353 { .layout_id = 72,
354 .codecs[0] = {
355 .name = "tas",
356 .connections = tas_connections_nolineout,
357 },
358 },
359 /* PowerMac8,2 */
360 { .layout_id = 86,
361 .codecs[0] = {
362 .name = "onyx",
363 .connections = onyx_connections_nomic,
364 },
365 .codecs[1] = {
366 .name = "topaz",
367 .connections = topaz_input,
368 },
369 },
370 /* PowerBook6,7 */
371 { .layout_id = 92,
372 .codecs[0] = {
373 .name = "tas",
374 .connections = tas_connections_nolineout,
375 },
376 },
377 /* PowerMac10,1 (Mac Mini) */
378 { .layout_id = 58,
379 .codecs[0] = {
380 .name = "toonie",
381 .connections = toonie_connections,
382 },
383 },
384 /* unknown, untested, but this comes from Apple */
385 { .layout_id = 41,
386 .codecs[0] = {
387 .name = "tas",
388 .connections = tas_connections_all,
389 },
390 },
391 { .layout_id = 36,
392 .codecs[0] = {
393 .name = "tas",
394 .connections = tas_connections_nomic,
395 },
396 .codecs[1] = {
397 .name = "topaz",
398 .connections = topaz_inout,
399 },
400 },
401 { .layout_id = 47,
402 .codecs[0] = {
403 .name = "onyx",
404 .connections = onyx_connections_noheadphones,
405 },
406 },
407 { .layout_id = 48,
408 .codecs[0] = {
409 .name = "topaz",
410 .connections = topaz_input,
411 },
412 },
413 { .layout_id = 49,
414 .codecs[0] = {
415 .name = "onyx",
416 .connections = onyx_connections_nomic,
417 },
418 },
419 { .layout_id = 50,
420 .codecs[0] = {
421 .name = "topaz",
422 .connections = topaz_input,
423 },
424 },
425 { .layout_id = 56,
426 .codecs[0] = {
427 .name = "onyx",
428 .connections = onyx_connections_noheadphones,
429 },
430 },
431 { .layout_id = 57,
432 .codecs[0] = {
433 .name = "topaz",
434 .connections = topaz_input,
435 },
436 },
437 { .layout_id = 62,
438 .codecs[0] = {
439 .name = "onyx",
440 .connections = onyx_connections_noheadphones,
441 },
442 .codecs[1] = {
443 .name = "topaz",
444 .connections = topaz_output,
445 },
446 },
447 { .layout_id = 66,
448 .codecs[0] = {
449 .name = "onyx",
450 .connections = onyx_connections_noheadphones,
451 },
452 },
453 { .layout_id = 67,
454 .codecs[0] = {
455 .name = "topaz",
456 .connections = topaz_input,
457 },
458 },
459 { .layout_id = 76,
460 .codecs[0] = {
461 .name = "tas",
462 .connections = tas_connections_nomic,
463 },
464 .codecs[1] = {
465 .name = "topaz",
466 .connections = topaz_inout,
467 },
468 },
469 { .layout_id = 90,
470 .codecs[0] = {
471 .name = "tas",
472 .connections = tas_connections_noline,
473 },
474 },
475 { .layout_id = 94,
476 .codecs[0] = {
477 .name = "onyx",
478 /* but it has an external mic?? how to select? */
479 .connections = onyx_connections_noheadphones,
480 },
481 },
482 { .layout_id = 96,
483 .codecs[0] = {
484 .name = "onyx",
485 .connections = onyx_connections_noheadphones,
486 },
487 },
488 { .layout_id = 98,
489 .codecs[0] = {
490 .name = "toonie",
491 .connections = toonie_connections,
492 },
493 },
494 { .layout_id = 100,
495 .codecs[0] = {
496 .name = "topaz",
497 .connections = topaz_input,
498 },
499 .codecs[1] = {
500 .name = "onyx",
501 .connections = onyx_connections_noheadphones,
502 },
503 },
504 {}
505};
506
507static struct layout *find_layout_by_id(unsigned int id)
508{
509 struct layout *l;
510
511 l = layouts;
512 while (l->layout_id) {
513 if (l->layout_id == id)
514 return l;
515 l++;
516 }
517 return NULL;
518}
519
520static void use_layout(struct layout *l)
521{
522 int i;
523
524 for (i=0; i<MAX_CODECS_PER_BUS; i++) {
525 if (l->codecs[i].name) {
526 request_module("snd-aoa-codec-%s", l->codecs[i].name);
527 }
528 }
529 /* now we wait for the codecs to call us back */
530}
531
532struct layout_dev;
533
534struct layout_dev_ptr {
535 struct layout_dev *ptr;
536};
537
538struct layout_dev {
539 struct list_head list;
540 struct soundbus_dev *sdev;
541 struct device_node *sound;
542 struct aoa_codec *codecs[MAX_CODECS_PER_BUS];
543 struct layout *layout;
544 struct gpio_runtime gpio;
545
546 /* we need these for headphone/lineout detection */
547 struct snd_kcontrol *headphone_ctrl;
548 struct snd_kcontrol *lineout_ctrl;
549 struct snd_kcontrol *speaker_ctrl;
550 struct snd_kcontrol *headphone_detected_ctrl;
551 struct snd_kcontrol *lineout_detected_ctrl;
552
553 struct layout_dev_ptr selfptr_headphone;
554 struct layout_dev_ptr selfptr_lineout;
555
556 u32 have_lineout_detect:1,
557 have_headphone_detect:1,
558 switch_on_headphone:1,
559 switch_on_lineout:1;
560};
561
562static LIST_HEAD(layouts_list);
563static int layouts_list_items;
564/* this can go away but only if we allow multiple cards,
565 * make the fabric handle all the card stuff, etc... */
566static struct layout_dev *layout_device;
567
568static int control_info(struct snd_kcontrol *kcontrol,
569 struct snd_ctl_elem_info *uinfo)
570{
571 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
572 uinfo->count = 1;
573 uinfo->value.integer.min = 0;
574 uinfo->value.integer.max = 1;
575 return 0;
576}
577
578#define AMP_CONTROL(n, description) \
579static int n##_control_get(struct snd_kcontrol *kcontrol, \
580 struct snd_ctl_elem_value *ucontrol) \
581{ \
582 struct gpio_runtime *gpio = snd_kcontrol_chip(kcontrol); \
583 if (gpio->methods && gpio->methods->get_##n) \
584 ucontrol->value.integer.value[0] = \
585 gpio->methods->get_##n(gpio); \
586 return 0; \
587} \
588static int n##_control_put(struct snd_kcontrol *kcontrol, \
589 struct snd_ctl_elem_value *ucontrol) \
590{ \
591 struct gpio_runtime *gpio = snd_kcontrol_chip(kcontrol); \
592 if (gpio->methods && gpio->methods->get_##n) \
593 gpio->methods->set_##n(gpio, \
594 ucontrol->value.integer.value[0]); \
595 return 1; \
596} \
597static struct snd_kcontrol_new n##_ctl = { \
598 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
599 .name = description, \
600 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
601 .info = control_info, \
602 .get = n##_control_get, \
603 .put = n##_control_put, \
604}
605
606AMP_CONTROL(headphone, "Headphone Switch");
607AMP_CONTROL(speakers, "Speakers Switch");
608AMP_CONTROL(lineout, "Line-Out Switch");
609
610static int detect_choice_get(struct snd_kcontrol *kcontrol,
611 struct snd_ctl_elem_value *ucontrol)
612{
613 struct layout_dev *ldev = snd_kcontrol_chip(kcontrol);
614
615 switch (kcontrol->private_value) {
616 case 0:
617 ucontrol->value.integer.value[0] = ldev->switch_on_headphone;
618 break;
619 case 1:
620 ucontrol->value.integer.value[0] = ldev->switch_on_lineout;
621 break;
622 default:
623 return -ENODEV;
624 }
625 return 0;
626}
627
628static int detect_choice_put(struct snd_kcontrol *kcontrol,
629 struct snd_ctl_elem_value *ucontrol)
630{
631 struct layout_dev *ldev = snd_kcontrol_chip(kcontrol);
632
633 switch (kcontrol->private_value) {
634 case 0:
635 ldev->switch_on_headphone = !!ucontrol->value.integer.value[0];
636 break;
637 case 1:
638 ldev->switch_on_lineout = !!ucontrol->value.integer.value[0];
639 break;
640 default:
641 return -ENODEV;
642 }
643 return 1;
644}
645
646static struct snd_kcontrol_new headphone_detect_choice = {
647 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
648 .name = "Headphone Detect Autoswitch",
649 .info = control_info,
650 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
651 .get = detect_choice_get,
652 .put = detect_choice_put,
653 .private_value = 0,
654};
655
656static struct snd_kcontrol_new lineout_detect_choice = {
657 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
658 .name = "Line-Out Detect Autoswitch",
659 .info = control_info,
660 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
661 .get = detect_choice_get,
662 .put = detect_choice_put,
663 .private_value = 1,
664};
665
666static int detected_get(struct snd_kcontrol *kcontrol,
667 struct snd_ctl_elem_value *ucontrol)
668{
669 struct layout_dev *ldev = snd_kcontrol_chip(kcontrol);
670 int v;
671
672 switch (kcontrol->private_value) {
673 case 0:
674 v = ldev->gpio.methods->get_detect(&ldev->gpio,
675 AOA_NOTIFY_HEADPHONE);
676 break;
677 case 1:
678 v = ldev->gpio.methods->get_detect(&ldev->gpio,
679 AOA_NOTIFY_LINE_OUT);
680 break;
681 default:
682 return -ENODEV;
683 }
684 ucontrol->value.integer.value[0] = v;
685 return 0;
686}
687
688static struct snd_kcontrol_new headphone_detected = {
689 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
690 .name = "Headphone Detected",
691 .info = control_info,
692 .access = SNDRV_CTL_ELEM_ACCESS_READ,
693 .get = detected_get,
694 .private_value = 0,
695};
696
697static struct snd_kcontrol_new lineout_detected = {
698 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
699 .name = "Line-Out Detected",
700 .info = control_info,
701 .access = SNDRV_CTL_ELEM_ACCESS_READ,
702 .get = detected_get,
703 .private_value = 1,
704};
705
706static int check_codec(struct aoa_codec *codec,
707 struct layout_dev *ldev,
708 struct codec_connect_info *cci)
709{
710 u32 *ref;
711 char propname[32];
712 struct codec_connection *cc;
713
714 /* if the codec has a 'codec' node, we require a reference */
715 if (codec->node && (strcmp(codec->node->name, "codec") == 0)) {
716 snprintf(propname, sizeof(propname),
717 "platform-%s-codec-ref", codec->name);
718 ref = (u32*)get_property(ldev->sound, propname, NULL);
719 if (!ref) {
720 printk(KERN_INFO "snd-aoa-fabric-layout: "
721 "required property %s not present\n", propname);
722 return -ENODEV;
723 }
724 if (*ref != codec->node->linux_phandle) {
725 printk(KERN_INFO "snd-aoa-fabric-layout: "
726 "%s doesn't match!\n", propname);
727 return -ENODEV;
728 }
729 } else {
730 if (layouts_list_items != 1) {
731 printk(KERN_INFO "snd-aoa-fabric-layout: "
732 "more than one soundbus, but no references.\n");
733 return -ENODEV;
734 }
735 }
736 codec->soundbus_dev = ldev->sdev;
737 codec->gpio = &ldev->gpio;
738
739 cc = cci->connections;
740 if (!cc)
741 return -EINVAL;
742
743 printk(KERN_INFO "snd-aoa-fabric-layout: can use this codec\n");
744
745 codec->connected = 0;
746 codec->fabric_data = cc;
747
748 while (cc->connected) {
749 codec->connected |= 1<<cc->codec_bit;
750 cc++;
751 }
752
753 return 0;
754}
755
756static int layout_found_codec(struct aoa_codec *codec)
757{
758 struct layout_dev *ldev;
759 int i;
760
761 list_for_each_entry(ldev, &layouts_list, list) {
762 for (i=0; i<MAX_CODECS_PER_BUS; i++) {
763 if (!ldev->layout->codecs[i].name)
764 continue;
765 if (strcmp(ldev->layout->codecs[i].name, codec->name) == 0) {
766 if (check_codec(codec,
767 ldev,
768 &ldev->layout->codecs[i]) == 0)
769 return 0;
770 }
771 }
772 }
773 return -ENODEV;
774}
775
776static void layout_remove_codec(struct aoa_codec *codec)
777{
778 int i;
779 /* here remove the codec from the layout dev's
780 * codec reference */
781
782 codec->soundbus_dev = NULL;
783 codec->gpio = NULL;
784 for (i=0; i<MAX_CODECS_PER_BUS; i++) {
785 }
786}
787
788static void layout_notify(void *data)
789{
790 struct layout_dev_ptr *dptr = data;
791 struct layout_dev *ldev;
792 int v, update;
793 struct snd_kcontrol *detected, *c;
794 struct snd_card *card = aoa_get_card();
795
796 ldev = dptr->ptr;
797 if (data == &ldev->selfptr_headphone) {
798 v = ldev->gpio.methods->get_detect(&ldev->gpio, AOA_NOTIFY_HEADPHONE);
799 detected = ldev->headphone_detected_ctrl;
800 update = ldev->switch_on_headphone;
801 if (update) {
802 ldev->gpio.methods->set_speakers(&ldev->gpio, !v);
803 ldev->gpio.methods->set_headphone(&ldev->gpio, v);
804 ldev->gpio.methods->set_lineout(&ldev->gpio, 0);
805 }
806 } else if (data == &ldev->selfptr_lineout) {
807 v = ldev->gpio.methods->get_detect(&ldev->gpio, AOA_NOTIFY_LINE_OUT);
808 detected = ldev->lineout_detected_ctrl;
809 update = ldev->switch_on_lineout;
810 if (update) {
811 ldev->gpio.methods->set_speakers(&ldev->gpio, !v);
812 ldev->gpio.methods->set_headphone(&ldev->gpio, 0);
813 ldev->gpio.methods->set_lineout(&ldev->gpio, v);
814 }
815 } else
816 return;
817
818 if (detected)
819 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &detected->id);
820 if (update) {
821 c = ldev->headphone_ctrl;
822 if (c)
823 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &c->id);
824 c = ldev->speaker_ctrl;
825 if (c)
826 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &c->id);
827 c = ldev->lineout_ctrl;
828 if (c)
829 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &c->id);
830 }
831}
832
833static void layout_attached_codec(struct aoa_codec *codec)
834{
835 struct codec_connection *cc;
836 struct snd_kcontrol *ctl;
837 int headphones, lineout;
838 struct layout_dev *ldev = layout_device;
839
840 /* need to add this codec to our codec array! */
841
842 cc = codec->fabric_data;
843
844 headphones = codec->gpio->methods->get_detect(codec->gpio,
845 AOA_NOTIFY_HEADPHONE);
846 lineout = codec->gpio->methods->get_detect(codec->gpio,
847 AOA_NOTIFY_LINE_OUT);
848
849 while (cc->connected) {
850 if (cc->connected & CC_SPEAKERS) {
851 if (headphones <= 0 && lineout <= 0)
852 ldev->gpio.methods->set_speakers(codec->gpio, 1);
853 ctl = snd_ctl_new1(&speakers_ctl, codec->gpio);
854 ldev->speaker_ctrl = ctl;
855 aoa_snd_ctl_add(ctl);
856 }
857 if (cc->connected & CC_HEADPHONE) {
858 if (headphones == 1)
859 ldev->gpio.methods->set_headphone(codec->gpio, 1);
860 ctl = snd_ctl_new1(&headphone_ctl, codec->gpio);
861 ldev->headphone_ctrl = ctl;
862 aoa_snd_ctl_add(ctl);
863 ldev->have_headphone_detect =
864 !ldev->gpio.methods
865 ->set_notify(&ldev->gpio,
866 AOA_NOTIFY_HEADPHONE,
867 layout_notify,
868 &ldev->selfptr_headphone);
869 if (ldev->have_headphone_detect) {
870 ctl = snd_ctl_new1(&headphone_detect_choice,
871 ldev);
872 aoa_snd_ctl_add(ctl);
873 ctl = snd_ctl_new1(&headphone_detected,
874 ldev);
875 ldev->headphone_detected_ctrl = ctl;
876 aoa_snd_ctl_add(ctl);
877 }
878 }
879 if (cc->connected & CC_LINEOUT) {
880 if (lineout == 1)
881 ldev->gpio.methods->set_lineout(codec->gpio, 1);
882 ctl = snd_ctl_new1(&lineout_ctl, codec->gpio);
883 if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE)
884 strlcpy(ctl->id.name,
885 "Headphone Switch", sizeof(ctl->id.name));
886 ldev->lineout_ctrl = ctl;
887 aoa_snd_ctl_add(ctl);
888 ldev->have_lineout_detect =
889 !ldev->gpio.methods
890 ->set_notify(&ldev->gpio,
891 AOA_NOTIFY_LINE_OUT,
892 layout_notify,
893 &ldev->selfptr_lineout);
894 if (ldev->have_lineout_detect) {
895 ctl = snd_ctl_new1(&lineout_detect_choice,
896 ldev);
897 if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE)
898 strlcpy(ctl->id.name,
899 "Headphone Detect Autoswitch",
900 sizeof(ctl->id.name));
901 aoa_snd_ctl_add(ctl);
902 ctl = snd_ctl_new1(&lineout_detected,
903 ldev);
904 if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE)
905 strlcpy(ctl->id.name,
906 "Headphone Detected",
907 sizeof(ctl->id.name));
908 ldev->lineout_detected_ctrl = ctl;
909 aoa_snd_ctl_add(ctl);
910 }
911 }
912 cc++;
913 }
914 /* now update initial state */
915 if (ldev->have_headphone_detect)
916 layout_notify(&ldev->selfptr_headphone);
917 if (ldev->have_lineout_detect)
918 layout_notify(&ldev->selfptr_lineout);
919}
920
921static struct aoa_fabric layout_fabric = {
922 .name = "SoundByLayout",
923 .owner = THIS_MODULE,
924 .found_codec = layout_found_codec,
925 .remove_codec = layout_remove_codec,
926 .attached_codec = layout_attached_codec,
927};
928
929static int aoa_fabric_layout_probe(struct soundbus_dev *sdev)
930{
931 struct device_node *sound = NULL;
932 unsigned int *layout_id;
933 struct layout *layout;
934 struct layout_dev *ldev = NULL;
935 int err;
936
937 /* hm, currently we can only have one ... */
938 if (layout_device)
939 return -ENODEV;
940
941 /* by breaking out we keep a reference */
942 while ((sound = of_get_next_child(sdev->ofdev.node, sound))) {
943 if (sound->type && strcasecmp(sound->type, "soundchip") == 0)
944 break;
945 }
946 if (!sound) return -ENODEV;
947
948 layout_id = (unsigned int *) get_property(sound, "layout-id", NULL);
949 if (!layout_id)
950 goto outnodev;
951 printk(KERN_INFO "snd-aoa-fabric-layout: found bus with layout %d ", *layout_id);
952
953 layout = find_layout_by_id(*layout_id);
954 if (!layout) {
955 printk("(no idea how to handle)\n");
956 goto outnodev;
957 }
958
959 ldev = kzalloc(sizeof(struct layout_dev), GFP_KERNEL);
960 if (!ldev)
961 goto outnodev;
962
963 layout_device = ldev;
964 ldev->sdev = sdev;
965 ldev->sound = sound;
966 ldev->layout = layout;
967 ldev->gpio.node = sound->parent;
968 switch (layout->layout_id) {
969 case 41: /* that unknown machine no one seems to have */
970 case 51: /* PowerBook5,4 */
971 case 58: /* Mac Mini */
972 ldev->gpio.methods = ftr_gpio_methods;
973 break;
974 default:
975 ldev->gpio.methods = pmf_gpio_methods;
976 }
977 ldev->selfptr_headphone.ptr = ldev;
978 ldev->selfptr_lineout.ptr = ldev;
979 sdev->ofdev.dev.driver_data = ldev;
980
981 printk("(using)\n");
982 list_add(&ldev->list, &layouts_list);
983 layouts_list_items++;
984
985 /* assign these before registering ourselves, so
986 * callbacks that are done during registration
987 * already have the values */
988 sdev->pcmid = ldev->layout->pcmid;
989 if (ldev->layout->busname) {
990 sdev->pcmname = ldev->layout->busname;
991 } else {
992 sdev->pcmname = "Master";
993 }
994
995 ldev->gpio.methods->init(&ldev->gpio);
996
997 err = aoa_fabric_register(&layout_fabric);
998 if (err && err != -EALREADY) {
999 printk(KERN_INFO "snd-aoa-fabric-layout: can't use,"
1000 " another fabric is active!\n");
1001 goto outlistdel;
1002 }
1003
1004 use_layout(layout);
1005 ldev->switch_on_headphone = 1;
1006 ldev->switch_on_lineout = 1;
1007 return 0;
1008 outlistdel:
1009 /* we won't be using these then... */
1010 ldev->gpio.methods->exit(&ldev->gpio);
1011 /* reset if we didn't use it */
1012 sdev->pcmname = NULL;
1013 sdev->pcmid = -1;
1014 list_del(&ldev->list);
1015 layouts_list_items--;
1016 outnodev:
1017 if (sound) of_node_put(sound);
1018 layout_device = NULL;
1019 if (ldev) kfree(ldev);
1020 return -ENODEV;
1021}
1022
1023static int aoa_fabric_layout_remove(struct soundbus_dev *sdev)
1024{
1025 struct layout_dev *ldev = sdev->ofdev.dev.driver_data;
1026 int i;
1027
1028 for (i=0; i<MAX_CODECS_PER_BUS; i++) {
1029 if (ldev->codecs[i]) {
1030 aoa_fabric_unlink_codec(ldev->codecs[i]);
1031 }
1032 ldev->codecs[i] = NULL;
1033 }
1034 list_del(&ldev->list);
1035 layouts_list_items--;
1036 of_node_put(ldev->sound);
1037
1038 ldev->gpio.methods->set_notify(&ldev->gpio,
1039 AOA_NOTIFY_HEADPHONE,
1040 NULL,
1041 NULL);
1042 ldev->gpio.methods->set_notify(&ldev->gpio,
1043 AOA_NOTIFY_LINE_OUT,
1044 NULL,
1045 NULL);
1046
1047 ldev->gpio.methods->exit(&ldev->gpio);
1048 layout_device = NULL;
1049 kfree(ldev);
1050 sdev->pcmid = -1;
1051 sdev->pcmname = NULL;
1052 return 0;
1053}
1054
1055#ifdef CONFIG_PM
1056static int aoa_fabric_layout_suspend(struct soundbus_dev *sdev, pm_message_t state)
1057{
1058 struct layout_dev *ldev = sdev->ofdev.dev.driver_data;
1059
1060 printk("aoa_fabric_layout_suspend()\n");
1061
1062 if (ldev->gpio.methods && ldev->gpio.methods->all_amps_off)
1063 ldev->gpio.methods->all_amps_off(&ldev->gpio);
1064
1065 return 0;
1066}
1067
1068static int aoa_fabric_layout_resume(struct soundbus_dev *sdev)
1069{
1070 struct layout_dev *ldev = sdev->ofdev.dev.driver_data;
1071
1072 printk("aoa_fabric_layout_resume()\n");
1073
1074 if (ldev->gpio.methods && ldev->gpio.methods->all_amps_off)
1075 ldev->gpio.methods->all_amps_restore(&ldev->gpio);
1076
1077 return 0;
1078}
1079#endif
1080
1081static struct soundbus_driver aoa_soundbus_driver = {
1082 .name = "snd_aoa_soundbus_drv",
1083 .owner = THIS_MODULE,
1084 .probe = aoa_fabric_layout_probe,
1085 .remove = aoa_fabric_layout_remove,
1086#ifdef CONFIG_PM
1087 .suspend = aoa_fabric_layout_suspend,
1088 .resume = aoa_fabric_layout_resume,
1089#endif
1090};
1091
1092static int __init aoa_fabric_layout_init(void)
1093{
1094 int err;
1095
1096 err = soundbus_register_driver(&aoa_soundbus_driver);
1097 if (err)
1098 return err;
1099 return 0;
1100}
1101
1102static void __exit aoa_fabric_layout_exit(void)
1103{
1104 soundbus_unregister_driver(&aoa_soundbus_driver);
1105 aoa_fabric_unregister(&layout_fabric);
1106}
1107
1108module_init(aoa_fabric_layout_init);
1109module_exit(aoa_fabric_layout_exit);
diff --git a/sound/aoa/soundbus/Kconfig b/sound/aoa/soundbus/Kconfig
new file mode 100644
index 000000000000..d532d27a9f54
--- /dev/null
+++ b/sound/aoa/soundbus/Kconfig
@@ -0,0 +1,14 @@
1config SND_AOA_SOUNDBUS
2 tristate "Apple Soundbus support"
3 depends on SOUND && SND_PCM && EXPERIMENTAL
4 ---help---
5 This option enables the generic driver for the soundbus
6 support on Apple machines.
7
8 It is required for the sound bus implementations.
9
10config SND_AOA_SOUNDBUS_I2S
11 tristate "I2S bus support"
12 depends on SND_AOA_SOUNDBUS && PCI
13 ---help---
14 This option enables support for Apple I2S busses.
diff --git a/sound/aoa/soundbus/Makefile b/sound/aoa/soundbus/Makefile
new file mode 100644
index 000000000000..0e61f5aa06b5
--- /dev/null
+++ b/sound/aoa/soundbus/Makefile
@@ -0,0 +1,3 @@
1obj-$(CONFIG_SND_AOA_SOUNDBUS) += snd-aoa-soundbus.o
2snd-aoa-soundbus-objs := core.o sysfs.o
3obj-$(CONFIG_SND_AOA_SOUNDBUS_I2S) += i2sbus/
diff --git a/sound/aoa/soundbus/core.c b/sound/aoa/soundbus/core.c
new file mode 100644
index 000000000000..abe84a76c835
--- /dev/null
+++ b/sound/aoa/soundbus/core.c
@@ -0,0 +1,250 @@
1/*
2 * soundbus
3 *
4 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
5 *
6 * GPL v2, can be found in COPYING.
7 */
8
9#include <linux/module.h>
10#include "soundbus.h"
11
12MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
13MODULE_LICENSE("GPL");
14MODULE_DESCRIPTION("Apple Soundbus");
15
16struct soundbus_dev *soundbus_dev_get(struct soundbus_dev *dev)
17{
18 struct device *tmp;
19
20 if (!dev)
21 return NULL;
22 tmp = get_device(&dev->ofdev.dev);
23 if (tmp)
24 return to_soundbus_device(tmp);
25 else
26 return NULL;
27}
28EXPORT_SYMBOL_GPL(soundbus_dev_get);
29
30void soundbus_dev_put(struct soundbus_dev *dev)
31{
32 if (dev)
33 put_device(&dev->ofdev.dev);
34}
35EXPORT_SYMBOL_GPL(soundbus_dev_put);
36
37static int soundbus_probe(struct device *dev)
38{
39 int error = -ENODEV;
40 struct soundbus_driver *drv;
41 struct soundbus_dev *soundbus_dev;
42
43 drv = to_soundbus_driver(dev->driver);
44 soundbus_dev = to_soundbus_device(dev);
45
46 if (!drv->probe)
47 return error;
48
49 soundbus_dev_get(soundbus_dev);
50
51 error = drv->probe(soundbus_dev);
52 if (error)
53 soundbus_dev_put(soundbus_dev);
54
55 return error;
56}
57
58
59static int soundbus_uevent(struct device *dev, char **envp, int num_envp,
60 char *buffer, int buffer_size)
61{
62 struct soundbus_dev * soundbus_dev;
63 struct of_device * of;
64 char *scratch, *compat, *compat2;
65 int i = 0;
66 int length, cplen, cplen2, seen = 0;
67
68 if (!dev)
69 return -ENODEV;
70
71 soundbus_dev = to_soundbus_device(dev);
72 if (!soundbus_dev)
73 return -ENODEV;
74
75 of = &soundbus_dev->ofdev;
76
77 /* stuff we want to pass to /sbin/hotplug */
78 envp[i++] = scratch = buffer;
79 length = scnprintf (scratch, buffer_size, "OF_NAME=%s", of->node->name);
80 ++length;
81 buffer_size -= length;
82 if ((buffer_size <= 0) || (i >= num_envp))
83 return -ENOMEM;
84 scratch += length;
85
86 envp[i++] = scratch;
87 length = scnprintf (scratch, buffer_size, "OF_TYPE=%s", of->node->type);
88 ++length;
89 buffer_size -= length;
90 if ((buffer_size <= 0) || (i >= num_envp))
91 return -ENOMEM;
92 scratch += length;
93
94 /* Since the compatible field can contain pretty much anything
95 * it's not really legal to split it out with commas. We split it
96 * up using a number of environment variables instead. */
97
98 compat = (char *) get_property(of->node, "compatible", &cplen);
99 compat2 = compat;
100 cplen2= cplen;
101 while (compat && cplen > 0) {
102 envp[i++] = scratch;
103 length = scnprintf (scratch, buffer_size,
104 "OF_COMPATIBLE_%d=%s", seen, compat);
105 ++length;
106 buffer_size -= length;
107 if ((buffer_size <= 0) || (i >= num_envp))
108 return -ENOMEM;
109 scratch += length;
110 length = strlen (compat) + 1;
111 compat += length;
112 cplen -= length;
113 seen++;
114 }
115
116 envp[i++] = scratch;
117 length = scnprintf (scratch, buffer_size, "OF_COMPATIBLE_N=%d", seen);
118 ++length;
119 buffer_size -= length;
120 if ((buffer_size <= 0) || (i >= num_envp))
121 return -ENOMEM;
122 scratch += length;
123
124 envp[i++] = scratch;
125 length = scnprintf (scratch, buffer_size, "MODALIAS=%s",
126 soundbus_dev->modalias);
127
128 buffer_size -= length;
129 if ((buffer_size <= 0) || (i >= num_envp))
130 return -ENOMEM;
131
132 envp[i] = NULL;
133
134 return 0;
135}
136
137static int soundbus_device_remove(struct device *dev)
138{
139 struct soundbus_dev * soundbus_dev = to_soundbus_device(dev);
140 struct soundbus_driver * drv = to_soundbus_driver(dev->driver);
141
142 if (dev->driver && drv->remove)
143 drv->remove(soundbus_dev);
144 soundbus_dev_put(soundbus_dev);
145
146 return 0;
147}
148
149static void soundbus_device_shutdown(struct device *dev)
150{
151 struct soundbus_dev * soundbus_dev = to_soundbus_device(dev);
152 struct soundbus_driver * drv = to_soundbus_driver(dev->driver);
153
154 if (dev->driver && drv->shutdown)
155 drv->shutdown(soundbus_dev);
156}
157
158#ifdef CONFIG_PM
159
160static int soundbus_device_suspend(struct device *dev, pm_message_t state)
161{
162 struct soundbus_dev * soundbus_dev = to_soundbus_device(dev);
163 struct soundbus_driver * drv = to_soundbus_driver(dev->driver);
164
165 if (dev->driver && drv->suspend)
166 return drv->suspend(soundbus_dev, state);
167 return 0;
168}
169
170static int soundbus_device_resume(struct device * dev)
171{
172 struct soundbus_dev * soundbus_dev = to_soundbus_device(dev);
173 struct soundbus_driver * drv = to_soundbus_driver(dev->driver);
174
175 if (dev->driver && drv->resume)
176 return drv->resume(soundbus_dev);
177 return 0;
178}
179
180#endif /* CONFIG_PM */
181
182extern struct device_attribute soundbus_dev_attrs[];
183
184static struct bus_type soundbus_bus_type = {
185 .name = "aoa-soundbus",
186 .probe = soundbus_probe,
187 .uevent = soundbus_uevent,
188 .remove = soundbus_device_remove,
189 .shutdown = soundbus_device_shutdown,
190#ifdef CONFIG_PM
191 .suspend = soundbus_device_suspend,
192 .resume = soundbus_device_resume,
193#endif
194 .dev_attrs = soundbus_dev_attrs,
195};
196
197static int __init soundbus_init(void)
198{
199 return bus_register(&soundbus_bus_type);
200}
201
202static void __exit soundbus_exit(void)
203{
204 bus_unregister(&soundbus_bus_type);
205}
206
207int soundbus_add_one(struct soundbus_dev *dev)
208{
209 static int devcount;
210
211 /* sanity checks */
212 if (!dev->attach_codec ||
213 !dev->ofdev.node ||
214 dev->pcmname ||
215 dev->pcmid != -1) {
216 printk(KERN_ERR "soundbus: adding device failed sanity check!\n");
217 return -EINVAL;
218 }
219
220 snprintf(dev->ofdev.dev.bus_id, BUS_ID_SIZE, "soundbus:%x", ++devcount);
221 dev->ofdev.dev.bus = &soundbus_bus_type;
222 return of_device_register(&dev->ofdev);
223}
224EXPORT_SYMBOL_GPL(soundbus_add_one);
225
226void soundbus_remove_one(struct soundbus_dev *dev)
227{
228 of_device_unregister(&dev->ofdev);
229}
230EXPORT_SYMBOL_GPL(soundbus_remove_one);
231
232int soundbus_register_driver(struct soundbus_driver *drv)
233{
234 /* initialize common driver fields */
235 drv->driver.name = drv->name;
236 drv->driver.bus = &soundbus_bus_type;
237
238 /* register with core */
239 return driver_register(&drv->driver);
240}
241EXPORT_SYMBOL_GPL(soundbus_register_driver);
242
243void soundbus_unregister_driver(struct soundbus_driver *drv)
244{
245 driver_unregister(&drv->driver);
246}
247EXPORT_SYMBOL_GPL(soundbus_unregister_driver);
248
249module_init(soundbus_init);
250module_exit(soundbus_exit);
diff --git a/sound/aoa/soundbus/i2sbus/Makefile b/sound/aoa/soundbus/i2sbus/Makefile
new file mode 100644
index 000000000000..e57a5cf65655
--- /dev/null
+++ b/sound/aoa/soundbus/i2sbus/Makefile
@@ -0,0 +1,2 @@
1obj-$(CONFIG_SND_AOA_SOUNDBUS_I2S) += snd-aoa-i2sbus.o
2snd-aoa-i2sbus-objs := i2sbus-core.o i2sbus-pcm.o i2sbus-control.o
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-control.c b/sound/aoa/soundbus/i2sbus/i2sbus-control.c
new file mode 100644
index 000000000000..f50407952d3c
--- /dev/null
+++ b/sound/aoa/soundbus/i2sbus/i2sbus-control.c
@@ -0,0 +1,192 @@
1/*
2 * i2sbus driver -- bus control routines
3 *
4 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
5 *
6 * GPL v2, can be found in COPYING.
7 */
8
9#include <asm/io.h>
10#include <linux/delay.h>
11#include <asm/prom.h>
12#include <asm/macio.h>
13#include <asm/pmac_feature.h>
14#include <asm/pmac_pfunc.h>
15#include "i2sbus.h"
16
17int i2sbus_control_init(struct macio_dev* dev, struct i2sbus_control **c)
18{
19 *c = kzalloc(sizeof(struct i2sbus_control), GFP_KERNEL);
20 if (!*c)
21 return -ENOMEM;
22
23 INIT_LIST_HEAD(&(*c)->list);
24
25 if (of_address_to_resource(dev->ofdev.node, 0, &(*c)->rsrc))
26 goto err;
27 /* we really should be using feature calls instead of mapping
28 * these registers. It's safe for now since no one else is
29 * touching them... */
30 (*c)->controlregs = ioremap((*c)->rsrc.start,
31 sizeof(struct i2s_control_regs));
32 if (!(*c)->controlregs)
33 goto err;
34
35 return 0;
36 err:
37 kfree(*c);
38 *c = NULL;
39 return -ENODEV;
40}
41
42void i2sbus_control_destroy(struct i2sbus_control *c)
43{
44 iounmap(c->controlregs);
45 kfree(c);
46}
47
48/* this is serialised externally */
49int i2sbus_control_add_dev(struct i2sbus_control *c,
50 struct i2sbus_dev *i2sdev)
51{
52 struct device_node *np;
53
54 np = i2sdev->sound.ofdev.node;
55 i2sdev->enable = pmf_find_function(np, "enable");
56 i2sdev->cell_enable = pmf_find_function(np, "cell-enable");
57 i2sdev->clock_enable = pmf_find_function(np, "clock-enable");
58 i2sdev->cell_disable = pmf_find_function(np, "cell-disable");
59 i2sdev->clock_disable = pmf_find_function(np, "clock-disable");
60
61 /* if the bus number is not 0 or 1 we absolutely need to use
62 * the platform functions -- there's nothing in Darwin that
63 * would allow seeing a system behind what the FCRs are then,
64 * and I don't want to go parsing a bunch of platform functions
65 * by hand to try finding a system... */
66 if (i2sdev->bus_number != 0 && i2sdev->bus_number != 1 &&
67 (!i2sdev->enable ||
68 !i2sdev->cell_enable || !i2sdev->clock_enable ||
69 !i2sdev->cell_disable || !i2sdev->clock_disable)) {
70 pmf_put_function(i2sdev->enable);
71 pmf_put_function(i2sdev->cell_enable);
72 pmf_put_function(i2sdev->clock_enable);
73 pmf_put_function(i2sdev->cell_disable);
74 pmf_put_function(i2sdev->clock_disable);
75 return -ENODEV;
76 }
77
78 list_add(&i2sdev->item, &c->list);
79
80 return 0;
81}
82
83void i2sbus_control_remove_dev(struct i2sbus_control *c,
84 struct i2sbus_dev *i2sdev)
85{
86 /* this is serialised externally */
87 list_del(&i2sdev->item);
88 if (list_empty(&c->list))
89 i2sbus_control_destroy(c);
90}
91
92int i2sbus_control_enable(struct i2sbus_control *c,
93 struct i2sbus_dev *i2sdev)
94{
95 struct pmf_args args = { .count = 0 };
96 int cc;
97
98 if (i2sdev->enable)
99 return pmf_call_one(i2sdev->enable, &args);
100
101 switch (i2sdev->bus_number) {
102 case 0:
103 cc = in_le32(&c->controlregs->cell_control);
104 out_le32(&c->controlregs->cell_control, cc | CTRL_CLOCK_INTF_0_ENABLE);
105 break;
106 case 1:
107 cc = in_le32(&c->controlregs->cell_control);
108 out_le32(&c->controlregs->cell_control, cc | CTRL_CLOCK_INTF_1_ENABLE);
109 break;
110 default:
111 return -ENODEV;
112 }
113 return 0;
114}
115
116int i2sbus_control_cell(struct i2sbus_control *c,
117 struct i2sbus_dev *i2sdev,
118 int enable)
119{
120 struct pmf_args args = { .count = 0 };
121 int cc;
122
123 switch (enable) {
124 case 0:
125 if (i2sdev->cell_disable)
126 return pmf_call_one(i2sdev->cell_disable, &args);
127 break;
128 case 1:
129 if (i2sdev->cell_enable)
130 return pmf_call_one(i2sdev->cell_enable, &args);
131 break;
132 default:
133 printk(KERN_ERR "i2sbus: INVALID CELL ENABLE VALUE\n");
134 return -ENODEV;
135 }
136 switch (i2sdev->bus_number) {
137 case 0:
138 cc = in_le32(&c->controlregs->cell_control);
139 cc &= ~CTRL_CLOCK_CELL_0_ENABLE;
140 cc |= enable * CTRL_CLOCK_CELL_0_ENABLE;
141 out_le32(&c->controlregs->cell_control, cc);
142 break;
143 case 1:
144 cc = in_le32(&c->controlregs->cell_control);
145 cc &= ~CTRL_CLOCK_CELL_1_ENABLE;
146 cc |= enable * CTRL_CLOCK_CELL_1_ENABLE;
147 out_le32(&c->controlregs->cell_control, cc);
148 break;
149 default:
150 return -ENODEV;
151 }
152 return 0;
153}
154
155int i2sbus_control_clock(struct i2sbus_control *c,
156 struct i2sbus_dev *i2sdev,
157 int enable)
158{
159 struct pmf_args args = { .count = 0 };
160 int cc;
161
162 switch (enable) {
163 case 0:
164 if (i2sdev->clock_disable)
165 return pmf_call_one(i2sdev->clock_disable, &args);
166 break;
167 case 1:
168 if (i2sdev->clock_enable)
169 return pmf_call_one(i2sdev->clock_enable, &args);
170 break;
171 default:
172 printk(KERN_ERR "i2sbus: INVALID CLOCK ENABLE VALUE\n");
173 return -ENODEV;
174 }
175 switch (i2sdev->bus_number) {
176 case 0:
177 cc = in_le32(&c->controlregs->cell_control);
178 cc &= ~CTRL_CLOCK_CLOCK_0_ENABLE;
179 cc |= enable * CTRL_CLOCK_CLOCK_0_ENABLE;
180 out_le32(&c->controlregs->cell_control, cc);
181 break;
182 case 1:
183 cc = in_le32(&c->controlregs->cell_control);
184 cc &= ~CTRL_CLOCK_CLOCK_1_ENABLE;
185 cc |= enable * CTRL_CLOCK_CLOCK_1_ENABLE;
186 out_le32(&c->controlregs->cell_control, cc);
187 break;
188 default:
189 return -ENODEV;
190 }
191 return 0;
192}
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-control.h b/sound/aoa/soundbus/i2sbus/i2sbus-control.h
new file mode 100644
index 000000000000..bb05550f730b
--- /dev/null
+++ b/sound/aoa/soundbus/i2sbus/i2sbus-control.h
@@ -0,0 +1,37 @@
1/*
2 * i2sbus driver -- bus register definitions
3 *
4 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
5 *
6 * GPL v2, can be found in COPYING.
7 */
8#ifndef __I2SBUS_CONTROLREGS_H
9#define __I2SBUS_CONTROLREGS_H
10
11/* i2s control registers, at least what we know about them */
12
13#define __PAD(m,n) u8 __pad##m[n]
14#define _PAD(line, n) __PAD(line, n)
15#define PAD(n) _PAD(__LINE__, (n))
16struct i2s_control_regs {
17 PAD(0x38);
18 __le32 fcr0; /* 0x38 (unknown) */
19 __le32 cell_control; /* 0x3c (fcr1) */
20 __le32 fcr2; /* 0x40 (unknown) */
21 __le32 fcr3; /* 0x44 (fcr3) */
22 __le32 clock_control; /* 0x48 (unknown) */
23 PAD(4);
24 /* total size: 0x50 bytes */
25} __attribute__((__packed__));
26
27#define CTRL_CLOCK_CELL_0_ENABLE (1<<10)
28#define CTRL_CLOCK_CLOCK_0_ENABLE (1<<12)
29#define CTRL_CLOCK_SWRESET_0 (1<<11)
30#define CTRL_CLOCK_INTF_0_ENABLE (1<<13)
31
32#define CTRL_CLOCK_CELL_1_ENABLE (1<<17)
33#define CTRL_CLOCK_CLOCK_1_ENABLE (1<<18)
34#define CTRL_CLOCK_SWRESET_1 (1<<19)
35#define CTRL_CLOCK_INTF_1_ENABLE (1<<20)
36
37#endif /* __I2SBUS_CONTROLREGS_H */
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-core.c b/sound/aoa/soundbus/i2sbus/i2sbus-core.c
new file mode 100644
index 000000000000..f268dacdaa00
--- /dev/null
+++ b/sound/aoa/soundbus/i2sbus/i2sbus-core.c
@@ -0,0 +1,387 @@
1/*
2 * i2sbus driver
3 *
4 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
5 *
6 * GPL v2, can be found in COPYING.
7 */
8
9#include <linux/module.h>
10#include <asm/macio.h>
11#include <asm/dbdma.h>
12#include <linux/pci.h>
13#include <linux/interrupt.h>
14#include <sound/driver.h>
15#include <sound/core.h>
16#include <linux/dma-mapping.h>
17#include "../soundbus.h"
18#include "i2sbus.h"
19
20MODULE_LICENSE("GPL");
21MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
22MODULE_DESCRIPTION("Apple Soundbus: I2S support");
23/* for auto-loading, declare that we handle this weird
24 * string that macio puts into the relevant device */
25MODULE_ALIAS("of:Ni2sTi2sC");
26
27static struct of_device_id i2sbus_match[] = {
28 { .name = "i2s" },
29 { }
30};
31
32static int alloc_dbdma_descriptor_ring(struct i2sbus_dev *i2sdev,
33 struct dbdma_command_mem *r,
34 int numcmds)
35{
36 /* one more for rounding */
37 r->size = (numcmds+1) * sizeof(struct dbdma_cmd);
38 /* We use the PCI APIs for now until the generic one gets fixed
39 * enough or until we get some macio-specific versions
40 */
41 r->space = dma_alloc_coherent(
42 &macio_get_pci_dev(i2sdev->macio)->dev,
43 r->size,
44 &r->bus_addr,
45 GFP_KERNEL);
46
47 if (!r->space) return -ENOMEM;
48
49 memset(r->space, 0, r->size);
50 r->cmds = (void*)DBDMA_ALIGN(r->space);
51 r->bus_cmd_start = r->bus_addr +
52 (dma_addr_t)((char*)r->cmds - (char*)r->space);
53
54 return 0;
55}
56
57static void free_dbdma_descriptor_ring(struct i2sbus_dev *i2sdev,
58 struct dbdma_command_mem *r)
59{
60 if (!r->space) return;
61
62 dma_free_coherent(&macio_get_pci_dev(i2sdev->macio)->dev,
63 r->size, r->space, r->bus_addr);
64}
65
66static void i2sbus_release_dev(struct device *dev)
67{
68 struct i2sbus_dev *i2sdev;
69 int i;
70
71 i2sdev = container_of(dev, struct i2sbus_dev, sound.ofdev.dev);
72
73 if (i2sdev->intfregs) iounmap(i2sdev->intfregs);
74 if (i2sdev->out.dbdma) iounmap(i2sdev->out.dbdma);
75 if (i2sdev->in.dbdma) iounmap(i2sdev->in.dbdma);
76 for (i=0;i<3;i++)
77 if (i2sdev->allocated_resource[i])
78 release_and_free_resource(i2sdev->allocated_resource[i]);
79 free_dbdma_descriptor_ring(i2sdev, &i2sdev->out.dbdma_ring);
80 free_dbdma_descriptor_ring(i2sdev, &i2sdev->in.dbdma_ring);
81 for (i=0;i<3;i++)
82 free_irq(i2sdev->interrupts[i], i2sdev);
83 i2sbus_control_remove_dev(i2sdev->control, i2sdev);
84 mutex_destroy(&i2sdev->lock);
85 kfree(i2sdev);
86}
87
88static irqreturn_t i2sbus_bus_intr(int irq, void *devid, struct pt_regs *regs)
89{
90 struct i2sbus_dev *dev = devid;
91 u32 intreg;
92
93 spin_lock(&dev->low_lock);
94 intreg = in_le32(&dev->intfregs->intr_ctl);
95
96 /* acknowledge interrupt reasons */
97 out_le32(&dev->intfregs->intr_ctl, intreg);
98
99 spin_unlock(&dev->low_lock);
100
101 return IRQ_HANDLED;
102}
103
104static int force;
105module_param(force, int, 0444);
106MODULE_PARM_DESC(force, "Force loading i2sbus even when"
107 " no layout-id property is present");
108
109/* FIXME: look at device node refcounting */
110static int i2sbus_add_dev(struct macio_dev *macio,
111 struct i2sbus_control *control,
112 struct device_node *np)
113{
114 struct i2sbus_dev *dev;
115 struct device_node *child = NULL, *sound = NULL;
116 int i;
117 static const char *rnames[] = { "i2sbus: %s (control)",
118 "i2sbus: %s (tx)",
119 "i2sbus: %s (rx)" };
120 static irqreturn_t (*ints[])(int irq, void *devid,
121 struct pt_regs *regs) = {
122 i2sbus_bus_intr,
123 i2sbus_tx_intr,
124 i2sbus_rx_intr
125 };
126
127 if (strlen(np->name) != 5)
128 return 0;
129 if (strncmp(np->name, "i2s-", 4))
130 return 0;
131
132 if (np->n_intrs != 3)
133 return 0;
134
135 dev = kzalloc(sizeof(struct i2sbus_dev), GFP_KERNEL);
136 if (!dev)
137 return 0;
138
139 i = 0;
140 while ((child = of_get_next_child(np, child))) {
141 if (strcmp(child->name, "sound") == 0) {
142 i++;
143 sound = child;
144 }
145 }
146 if (i == 1) {
147 u32 *layout_id;
148 layout_id = (u32*) get_property(sound, "layout-id", NULL);
149 if (layout_id) {
150 snprintf(dev->sound.modalias, 32,
151 "sound-layout-%d", *layout_id);
152 force = 1;
153 }
154 }
155 /* for the time being, until we can handle non-layout-id
156 * things in some fabric, refuse to attach if there is no
157 * layout-id property or we haven't been forced to attach.
158 * When there are two i2s busses and only one has a layout-id,
159 * then this depends on the order, but that isn't important
160 * either as the second one in that case is just a modem. */
161 if (!force) {
162 kfree(dev);
163 return -ENODEV;
164 }
165
166 mutex_init(&dev->lock);
167 spin_lock_init(&dev->low_lock);
168 dev->sound.ofdev.node = np;
169 dev->sound.ofdev.dma_mask = macio->ofdev.dma_mask;
170 dev->sound.ofdev.dev.dma_mask = &dev->sound.ofdev.dma_mask;
171 dev->sound.ofdev.dev.parent = &macio->ofdev.dev;
172 dev->sound.ofdev.dev.release = i2sbus_release_dev;
173 dev->sound.attach_codec = i2sbus_attach_codec;
174 dev->sound.detach_codec = i2sbus_detach_codec;
175 dev->sound.pcmid = -1;
176 dev->macio = macio;
177 dev->control = control;
178 dev->bus_number = np->name[4] - 'a';
179 INIT_LIST_HEAD(&dev->sound.codec_list);
180
181 for (i=0;i<3;i++) {
182 dev->interrupts[i] = -1;
183 snprintf(dev->rnames[i], sizeof(dev->rnames[i]), rnames[i], np->name);
184 }
185 for (i=0;i<3;i++) {
186 if (request_irq(np->intrs[i].line, ints[i], 0, dev->rnames[i], dev))
187 goto err;
188 dev->interrupts[i] = np->intrs[i].line;
189 }
190
191 for (i=0;i<3;i++) {
192 if (of_address_to_resource(np, i, &dev->resources[i]))
193 goto err;
194 /* if only we could use our resource dev->resources[i]...
195 * but request_resource doesn't know about parents and
196 * contained resources... */
197 dev->allocated_resource[i] =
198 request_mem_region(dev->resources[i].start,
199 dev->resources[i].end -
200 dev->resources[i].start + 1,
201 dev->rnames[i]);
202 if (!dev->allocated_resource[i]) {
203 printk(KERN_ERR "i2sbus: failed to claim resource %d!\n", i);
204 goto err;
205 }
206 }
207 /* should do sanity checking here about length of them */
208 dev->intfregs = ioremap(dev->resources[0].start,
209 dev->resources[0].end-dev->resources[0].start+1);
210 dev->out.dbdma = ioremap(dev->resources[1].start,
211 dev->resources[1].end-dev->resources[1].start+1);
212 dev->in.dbdma = ioremap(dev->resources[2].start,
213 dev->resources[2].end-dev->resources[2].start+1);
214 if (!dev->intfregs || !dev->out.dbdma || !dev->in.dbdma)
215 goto err;
216
217 if (alloc_dbdma_descriptor_ring(dev, &dev->out.dbdma_ring,
218 MAX_DBDMA_COMMANDS))
219 goto err;
220 if (alloc_dbdma_descriptor_ring(dev, &dev->in.dbdma_ring,
221 MAX_DBDMA_COMMANDS))
222 goto err;
223
224 if (i2sbus_control_add_dev(dev->control, dev)) {
225 printk(KERN_ERR "i2sbus: control layer didn't like bus\n");
226 goto err;
227 }
228
229 if (soundbus_add_one(&dev->sound)) {
230 printk(KERN_DEBUG "i2sbus: device registration error!\n");
231 goto err;
232 }
233
234 /* enable this cell */
235 i2sbus_control_cell(dev->control, dev, 1);
236 i2sbus_control_enable(dev->control, dev);
237 i2sbus_control_clock(dev->control, dev, 1);
238
239 return 1;
240 err:
241 for (i=0;i<3;i++)
242 if (dev->interrupts[i] != -1)
243 free_irq(dev->interrupts[i], dev);
244 free_dbdma_descriptor_ring(dev, &dev->out.dbdma_ring);
245 free_dbdma_descriptor_ring(dev, &dev->in.dbdma_ring);
246 if (dev->intfregs) iounmap(dev->intfregs);
247 if (dev->out.dbdma) iounmap(dev->out.dbdma);
248 if (dev->in.dbdma) iounmap(dev->in.dbdma);
249 for (i=0;i<3;i++)
250 if (dev->allocated_resource[i])
251 release_and_free_resource(dev->allocated_resource[i]);
252 mutex_destroy(&dev->lock);
253 kfree(dev);
254 return 0;
255}
256
257static int i2sbus_probe(struct macio_dev* dev, const struct of_device_id *match)
258{
259 struct device_node *np = NULL;
260 int got = 0, err;
261 struct i2sbus_control *control = NULL;
262
263 err = i2sbus_control_init(dev, &control);
264 if (err)
265 return err;
266 if (!control) {
267 printk(KERN_ERR "i2sbus_control_init API breakage\n");
268 return -ENODEV;
269 }
270
271 while ((np = of_get_next_child(dev->ofdev.node, np))) {
272 if (device_is_compatible(np, "i2sbus") ||
273 device_is_compatible(np, "i2s-modem")) {
274 got += i2sbus_add_dev(dev, control, np);
275 }
276 }
277
278 if (!got) {
279 /* found none, clean up */
280 i2sbus_control_destroy(control);
281 return -ENODEV;
282 }
283
284 dev->ofdev.dev.driver_data = control;
285
286 return 0;
287}
288
289static int i2sbus_remove(struct macio_dev* dev)
290{
291 struct i2sbus_control *control = dev->ofdev.dev.driver_data;
292 struct i2sbus_dev *i2sdev, *tmp;
293
294 list_for_each_entry_safe(i2sdev, tmp, &control->list, item)
295 soundbus_remove_one(&i2sdev->sound);
296
297 return 0;
298}
299
300#ifdef CONFIG_PM
301static int i2sbus_suspend(struct macio_dev* dev, pm_message_t state)
302{
303 struct i2sbus_control *control = dev->ofdev.dev.driver_data;
304 struct codec_info_item *cii;
305 struct i2sbus_dev* i2sdev;
306 int err, ret = 0;
307
308 list_for_each_entry(i2sdev, &control->list, item) {
309 /* Notify Alsa */
310 if (i2sdev->sound.pcm) {
311 /* Suspend PCM streams */
312 snd_pcm_suspend_all(i2sdev->sound.pcm);
313 /* Probably useless as we handle
314 * power transitions ourselves */
315 snd_power_change_state(i2sdev->sound.pcm->card,
316 SNDRV_CTL_POWER_D3hot);
317 }
318 /* Notify codecs */
319 list_for_each_entry(cii, &i2sdev->sound.codec_list, list) {
320 err = 0;
321 if (cii->codec->suspend)
322 err = cii->codec->suspend(cii, state);
323 if (err)
324 ret = err;
325 }
326 }
327 return ret;
328}
329
330static int i2sbus_resume(struct macio_dev* dev)
331{
332 struct i2sbus_control *control = dev->ofdev.dev.driver_data;
333 struct codec_info_item *cii;
334 struct i2sbus_dev* i2sdev;
335 int err, ret = 0;
336
337 list_for_each_entry(i2sdev, &control->list, item) {
338 /* Notify codecs so they can re-initialize */
339 list_for_each_entry(cii, &i2sdev->sound.codec_list, list) {
340 err = 0;
341 if (cii->codec->resume)
342 err = cii->codec->resume(cii);
343 if (err)
344 ret = err;
345 }
346 /* Notify Alsa */
347 if (i2sdev->sound.pcm) {
348 /* Same comment as above, probably useless */
349 snd_power_change_state(i2sdev->sound.pcm->card,
350 SNDRV_CTL_POWER_D0);
351 }
352 }
353
354 return ret;
355}
356#endif /* CONFIG_PM */
357
358static int i2sbus_shutdown(struct macio_dev* dev)
359{
360 return 0;
361}
362
363static struct macio_driver i2sbus_drv = {
364 .name = "soundbus-i2s",
365 .owner = THIS_MODULE,
366 .match_table = i2sbus_match,
367 .probe = i2sbus_probe,
368 .remove = i2sbus_remove,
369#ifdef CONFIG_PM
370 .suspend = i2sbus_suspend,
371 .resume = i2sbus_resume,
372#endif
373 .shutdown = i2sbus_shutdown,
374};
375
376static int __init soundbus_i2sbus_init(void)
377{
378 return macio_register_driver(&i2sbus_drv);
379}
380
381static void __exit soundbus_i2sbus_exit(void)
382{
383 macio_unregister_driver(&i2sbus_drv);
384}
385
386module_init(soundbus_i2sbus_init);
387module_exit(soundbus_i2sbus_exit);
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-interface.h b/sound/aoa/soundbus/i2sbus/i2sbus-interface.h
new file mode 100644
index 000000000000..c6b5f5452d20
--- /dev/null
+++ b/sound/aoa/soundbus/i2sbus/i2sbus-interface.h
@@ -0,0 +1,187 @@
1/*
2 * i2sbus driver -- interface register definitions
3 *
4 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
5 *
6 * GPL v2, can be found in COPYING.
7 */
8#ifndef __I2SBUS_INTERFACE_H
9#define __I2SBUS_INTERFACE_H
10
11/* i2s bus control registers, at least what we know about them */
12
13#define __PAD(m,n) u8 __pad##m[n]
14#define _PAD(line, n) __PAD(line, n)
15#define PAD(n) _PAD(__LINE__, (n))
16struct i2s_interface_regs {
17 __le32 intr_ctl; /* 0x00 */
18 PAD(12);
19 __le32 serial_format; /* 0x10 */
20 PAD(12);
21 __le32 codec_msg_out; /* 0x20 */
22 PAD(12);
23 __le32 codec_msg_in; /* 0x30 */
24 PAD(12);
25 __le32 frame_count; /* 0x40 */
26 PAD(12);
27 __le32 frame_match; /* 0x50 */
28 PAD(12);
29 __le32 data_word_sizes; /* 0x60 */
30 PAD(12);
31 __le32 peak_level_sel; /* 0x70 */
32 PAD(12);
33 __le32 peak_level_in0; /* 0x80 */
34 PAD(12);
35 __le32 peak_level_in1; /* 0x90 */
36 PAD(12);
37 /* total size: 0x100 bytes */
38} __attribute__((__packed__));
39
40/* interrupt register is just a bitfield with
41 * interrupt enable and pending bits */
42#define I2S_REG_INTR_CTL 0x00
43# define I2S_INT_FRAME_COUNT (1<<31)
44# define I2S_PENDING_FRAME_COUNT (1<<30)
45# define I2S_INT_MESSAGE_FLAG (1<<29)
46# define I2S_PENDING_MESSAGE_FLAG (1<<28)
47# define I2S_INT_NEW_PEAK (1<<27)
48# define I2S_PENDING_NEW_PEAK (1<<26)
49# define I2S_INT_CLOCKS_STOPPED (1<<25)
50# define I2S_PENDING_CLOCKS_STOPPED (1<<24)
51# define I2S_INT_EXTERNAL_SYNC_ERROR (1<<23)
52# define I2S_PENDING_EXTERNAL_SYNC_ERROR (1<<22)
53# define I2S_INT_EXTERNAL_SYNC_OK (1<<21)
54# define I2S_PENDING_EXTERNAL_SYNC_OK (1<<20)
55# define I2S_INT_NEW_SAMPLE_RATE (1<<19)
56# define I2S_PENDING_NEW_SAMPLE_RATE (1<<18)
57# define I2S_INT_STATUS_FLAG (1<<17)
58# define I2S_PENDING_STATUS_FLAG (1<<16)
59
60/* serial format register is more interesting :)
61 * It contains:
62 * - clock source
63 * - MClk divisor
64 * - SClk divisor
65 * - SClk master flag
66 * - serial format (sony, i2s 64x, i2s 32x, dav, silabs)
67 * - external sample frequency interrupt (don't understand)
68 * - external sample frequency
69 */
70#define I2S_REG_SERIAL_FORMAT 0x10
71/* clock source. You get either 18.432, 45.1584 or 49.1520 MHz */
72# define I2S_SF_CLOCK_SOURCE_SHIFT 30
73# define I2S_SF_CLOCK_SOURCE_MASK (3<<I2S_SF_CLOCK_SOURCE_SHIFT)
74# define I2S_SF_CLOCK_SOURCE_18MHz (0<<I2S_SF_CLOCK_SOURCE_SHIFT)
75# define I2S_SF_CLOCK_SOURCE_45MHz (1<<I2S_SF_CLOCK_SOURCE_SHIFT)
76# define I2S_SF_CLOCK_SOURCE_49MHz (2<<I2S_SF_CLOCK_SOURCE_SHIFT)
77/* also, let's define the exact clock speeds here, in Hz */
78#define I2S_CLOCK_SPEED_18MHz 18432000
79#define I2S_CLOCK_SPEED_45MHz 45158400
80#define I2S_CLOCK_SPEED_49MHz 49152000
81/* MClk is the clock that drives the codec, usually called its 'system clock'.
82 * It is derived by taking only every 'divisor' tick of the clock.
83 */
84# define I2S_SF_MCLKDIV_SHIFT 24
85# define I2S_SF_MCLKDIV_MASK (0x1F<<I2S_SF_MCLKDIV_SHIFT)
86# define I2S_SF_MCLKDIV_1 (0x14<<I2S_SF_MCLKDIV_SHIFT)
87# define I2S_SF_MCLKDIV_3 (0x13<<I2S_SF_MCLKDIV_SHIFT)
88# define I2S_SF_MCLKDIV_5 (0x12<<I2S_SF_MCLKDIV_SHIFT)
89# define I2S_SF_MCLKDIV_14 (0x0E<<I2S_SF_MCLKDIV_SHIFT)
90# define I2S_SF_MCLKDIV_OTHER(div) (((div/2-1)<<I2S_SF_MCLKDIV_SHIFT)&I2S_SF_MCLKDIV_MASK)
91static inline int i2s_sf_mclkdiv(int div, int *out)
92{
93 int d;
94
95 switch(div) {
96 case 1: *out |= I2S_SF_MCLKDIV_1; return 0;
97 case 3: *out |= I2S_SF_MCLKDIV_3; return 0;
98 case 5: *out |= I2S_SF_MCLKDIV_5; return 0;
99 case 14: *out |= I2S_SF_MCLKDIV_14; return 0;
100 default:
101 if (div%2) return -1;
102 d = div/2-1;
103 if (d == 0x14 || d == 0x13 || d == 0x12 || d == 0x0E)
104 return -1;
105 *out |= I2S_SF_MCLKDIV_OTHER(div);
106 return 0;
107 }
108}
109/* SClk is the clock that drives the i2s wire bus. Note that it is
110 * derived from the MClk above by taking only every 'divisor' tick
111 * of MClk.
112 */
113# define I2S_SF_SCLKDIV_SHIFT 20
114# define I2S_SF_SCLKDIV_MASK (0xF<<I2S_SF_SCLKDIV_SHIFT)
115# define I2S_SF_SCLKDIV_1 (8<<I2S_SF_SCLKDIV_SHIFT)
116# define I2S_SF_SCLKDIV_3 (9<<I2S_SF_SCLKDIV_SHIFT)
117# define I2S_SF_SCLKDIV_OTHER(div) (((div/2-1)<<I2S_SF_SCLKDIV_SHIFT)&I2S_SF_SCLKDIV_MASK)
118static inline int i2s_sf_sclkdiv(int div, int *out)
119{
120 int d;
121
122 switch(div) {
123 case 1: *out |= I2S_SF_SCLKDIV_1; return 0;
124 case 3: *out |= I2S_SF_SCLKDIV_3; return 0;
125 default:
126 if (div%2) return -1;
127 d = div/2-1;
128 if (d == 8 || d == 9) return -1;
129 *out |= I2S_SF_SCLKDIV_OTHER(div);
130 return 0;
131 }
132}
133# define I2S_SF_SCLK_MASTER (1<<19)
134/* serial format is the way the data is put to the i2s wire bus */
135# define I2S_SF_SERIAL_FORMAT_SHIFT 16
136# define I2S_SF_SERIAL_FORMAT_MASK (7<<I2S_SF_SERIAL_FORMAT_SHIFT)
137# define I2S_SF_SERIAL_FORMAT_SONY (0<<I2S_SF_SERIAL_FORMAT_SHIFT)
138# define I2S_SF_SERIAL_FORMAT_I2S_64X (1<<I2S_SF_SERIAL_FORMAT_SHIFT)
139# define I2S_SF_SERIAL_FORMAT_I2S_32X (2<<I2S_SF_SERIAL_FORMAT_SHIFT)
140# define I2S_SF_SERIAL_FORMAT_I2S_DAV (4<<I2S_SF_SERIAL_FORMAT_SHIFT)
141# define I2S_SF_SERIAL_FORMAT_I2S_SILABS (5<<I2S_SF_SERIAL_FORMAT_SHIFT)
142/* unknown */
143# define I2S_SF_EXT_SAMPLE_FREQ_INT_SHIFT 12
144# define I2S_SF_EXT_SAMPLE_FREQ_INT_MASK (0xF<<I2S_SF_SAMPLE_FREQ_INT_SHIFT)
145/* probably gives external frequency? */
146# define I2S_SF_EXT_SAMPLE_FREQ_MASK 0xFFF
147
148/* used to send codec messages, but how isn't clear */
149#define I2S_REG_CODEC_MSG_OUT 0x20
150
151/* used to receive codec messages, but how isn't clear */
152#define I2S_REG_CODEC_MSG_IN 0x30
153
154/* frame count reg isn't clear to me yet, but probably useful */
155#define I2S_REG_FRAME_COUNT 0x40
156
157/* program to some value, and get interrupt if frame count reaches it */
158#define I2S_REG_FRAME_MATCH 0x50
159
160/* this register describes how the bus transfers data */
161#define I2S_REG_DATA_WORD_SIZES 0x60
162/* number of interleaved input channels */
163# define I2S_DWS_NUM_CHANNELS_IN_SHIFT 24
164# define I2S_DWS_NUM_CHANNELS_IN_MASK (0x1F<<I2S_DWS_NUM_CHANNELS_IN_SHIFT)
165/* word size of input data */
166# define I2S_DWS_DATA_IN_SIZE_SHIFT 16
167# define I2S_DWS_DATA_IN_16BIT (0<<I2S_DWS_DATA_IN_SIZE_SHIFT)
168# define I2S_DWS_DATA_IN_24BIT (3<<I2S_DWS_DATA_IN_SIZE_SHIFT)
169/* number of interleaved output channels */
170# define I2S_DWS_NUM_CHANNELS_OUT_SHIFT 8
171# define I2S_DWS_NUM_CHANNELS_OUT_MASK (0x1F<<I2S_DWS_NUM_CHANNELS_OUT_SHIFT)
172/* word size of output data */
173# define I2S_DWS_DATA_OUT_SIZE_SHIFT 0
174# define I2S_DWS_DATA_OUT_16BIT (0<<I2S_DWS_DATA_OUT_SIZE_SHIFT)
175# define I2S_DWS_DATA_OUT_24BIT (3<<I2S_DWS_DATA_OUT_SIZE_SHIFT)
176
177
178/* unknown */
179#define I2S_REG_PEAK_LEVEL_SEL 0x70
180
181/* unknown */
182#define I2S_REG_PEAK_LEVEL_IN0 0x80
183
184/* unknown */
185#define I2S_REG_PEAK_LEVEL_IN1 0x90
186
187#endif /* __I2SBUS_INTERFACE_H */
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c b/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c
new file mode 100644
index 000000000000..3049015a04f1
--- /dev/null
+++ b/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c
@@ -0,0 +1,1021 @@
1/*
2 * i2sbus driver -- pcm routines
3 *
4 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
5 *
6 * GPL v2, can be found in COPYING.
7 */
8
9#include <asm/io.h>
10#include <linux/delay.h>
11/* So apparently there's a reason for requiring driver.h
12 * to be included first, even if I don't know it... */
13#include <sound/driver.h>
14#include <sound/core.h>
15#include <asm/macio.h>
16#include <linux/pci.h>
17#include "../soundbus.h"
18#include "i2sbus.h"
19
20static inline void get_pcm_info(struct i2sbus_dev *i2sdev, int in,
21 struct pcm_info **pi, struct pcm_info **other)
22{
23 if (in) {
24 if (pi)
25 *pi = &i2sdev->in;
26 if (other)
27 *other = &i2sdev->out;
28 } else {
29 if (pi)
30 *pi = &i2sdev->out;
31 if (other)
32 *other = &i2sdev->in;
33 }
34}
35
36static int clock_and_divisors(int mclk, int sclk, int rate, int *out)
37{
38 /* sclk must be derived from mclk! */
39 if (mclk % sclk)
40 return -1;
41 /* derive sclk register value */
42 if (i2s_sf_sclkdiv(mclk / sclk, out))
43 return -1;
44
45 if (I2S_CLOCK_SPEED_18MHz % (rate * mclk) == 0) {
46 if (!i2s_sf_mclkdiv(I2S_CLOCK_SPEED_18MHz / (rate * mclk), out)) {
47 *out |= I2S_SF_CLOCK_SOURCE_18MHz;
48 return 0;
49 }
50 }
51 if (I2S_CLOCK_SPEED_45MHz % (rate * mclk) == 0) {
52 if (!i2s_sf_mclkdiv(I2S_CLOCK_SPEED_45MHz / (rate * mclk), out)) {
53 *out |= I2S_SF_CLOCK_SOURCE_45MHz;
54 return 0;
55 }
56 }
57 if (I2S_CLOCK_SPEED_49MHz % (rate * mclk) == 0) {
58 if (!i2s_sf_mclkdiv(I2S_CLOCK_SPEED_49MHz / (rate * mclk), out)) {
59 *out |= I2S_SF_CLOCK_SOURCE_49MHz;
60 return 0;
61 }
62 }
63 return -1;
64}
65
66#define CHECK_RATE(rate) \
67 do { if (rates & SNDRV_PCM_RATE_ ##rate) { \
68 int dummy; \
69 if (clock_and_divisors(sysclock_factor, \
70 bus_factor, rate, &dummy)) \
71 rates &= ~SNDRV_PCM_RATE_ ##rate; \
72 } } while (0)
73
74static int i2sbus_pcm_open(struct i2sbus_dev *i2sdev, int in)
75{
76 struct pcm_info *pi, *other;
77 struct soundbus_dev *sdev;
78 int masks_inited = 0, err;
79 struct codec_info_item *cii, *rev;
80 struct snd_pcm_hardware *hw;
81 u64 formats = 0;
82 unsigned int rates = 0;
83 struct transfer_info v;
84 int result = 0;
85 int bus_factor = 0, sysclock_factor = 0;
86 int found_this;
87
88 mutex_lock(&i2sdev->lock);
89
90 get_pcm_info(i2sdev, in, &pi, &other);
91
92 hw = &pi->substream->runtime->hw;
93 sdev = &i2sdev->sound;
94
95 if (pi->active) {
96 /* alsa messed up */
97 result = -EBUSY;
98 goto out_unlock;
99 }
100
101 /* we now need to assign the hw */
102 list_for_each_entry(cii, &sdev->codec_list, list) {
103 struct transfer_info *ti = cii->codec->transfers;
104 bus_factor = cii->codec->bus_factor;
105 sysclock_factor = cii->codec->sysclock_factor;
106 while (ti->formats && ti->rates) {
107 v = *ti;
108 if (ti->transfer_in == in
109 && cii->codec->usable(cii, ti, &v)) {
110 if (masks_inited) {
111 formats &= v.formats;
112 rates &= v.rates;
113 } else {
114 formats = v.formats;
115 rates = v.rates;
116 masks_inited = 1;
117 }
118 }
119 ti++;
120 }
121 }
122 if (!masks_inited || !bus_factor || !sysclock_factor) {
123 result = -ENODEV;
124 goto out_unlock;
125 }
126 /* bus dependent stuff */
127 hw->info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
128 SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_RESUME;
129
130 CHECK_RATE(5512);
131 CHECK_RATE(8000);
132 CHECK_RATE(11025);
133 CHECK_RATE(16000);
134 CHECK_RATE(22050);
135 CHECK_RATE(32000);
136 CHECK_RATE(44100);
137 CHECK_RATE(48000);
138 CHECK_RATE(64000);
139 CHECK_RATE(88200);
140 CHECK_RATE(96000);
141 CHECK_RATE(176400);
142 CHECK_RATE(192000);
143 hw->rates = rates;
144
145 /* well. the codec might want 24 bits only, and we'll
146 * ever only transfer 24 bits, but they are top-aligned!
147 * So for alsa, we claim that we're doing full 32 bit
148 * while in reality we'll ignore the lower 8 bits of
149 * that when doing playback (they're transferred as 0
150 * as far as I know, no codecs we have are 32-bit capable
151 * so I can't really test) and when doing recording we'll
152 * always have those lower 8 bits recorded as 0 */
153 if (formats & SNDRV_PCM_FMTBIT_S24_BE)
154 formats |= SNDRV_PCM_FMTBIT_S32_BE;
155 if (formats & SNDRV_PCM_FMTBIT_U24_BE)
156 formats |= SNDRV_PCM_FMTBIT_U32_BE;
157 /* now mask off what we can support. I suppose we could
158 * also support S24_3LE and some similar formats, but I
159 * doubt there's a codec that would be able to use that,
160 * so we don't support it here. */
161 hw->formats = formats & (SNDRV_PCM_FMTBIT_S16_BE |
162 SNDRV_PCM_FMTBIT_U16_BE |
163 SNDRV_PCM_FMTBIT_S32_BE |
164 SNDRV_PCM_FMTBIT_U32_BE);
165
166 /* we need to set the highest and lowest rate possible.
167 * These are the highest and lowest rates alsa can
168 * support properly in its bitfield.
169 * Below, we'll use that to restrict to the rate
170 * currently in use (if any). */
171 hw->rate_min = 5512;
172 hw->rate_max = 192000;
173 /* if the other stream is active, then we can only
174 * support what it is currently using.
175 * FIXME: I lied. This comment is wrong. We can support
176 * anything that works with the same serial format, ie.
177 * when recording 24 bit sound we can well play 16 bit
178 * sound at the same time iff using the same transfer mode.
179 */
180 if (other->active) {
181 /* FIXME: is this guaranteed by the alsa api? */
182 hw->formats &= (1ULL << i2sdev->format);
183 /* see above, restrict rates to the one we already have */
184 hw->rate_min = i2sdev->rate;
185 hw->rate_max = i2sdev->rate;
186 }
187
188 hw->channels_min = 2;
189 hw->channels_max = 2;
190 /* these are somewhat arbitrary */
191 hw->buffer_bytes_max = 131072;
192 hw->period_bytes_min = 256;
193 hw->period_bytes_max = 16384;
194 hw->periods_min = 3;
195 hw->periods_max = MAX_DBDMA_COMMANDS;
196 list_for_each_entry(cii, &sdev->codec_list, list) {
197 if (cii->codec->open) {
198 err = cii->codec->open(cii, pi->substream);
199 if (err) {
200 result = err;
201 /* unwind */
202 found_this = 0;
203 list_for_each_entry_reverse(rev,
204 &sdev->codec_list, list) {
205 if (found_this && rev->codec->close) {
206 rev->codec->close(rev,
207 pi->substream);
208 }
209 if (rev == cii)
210 found_this = 1;
211 }
212 goto out_unlock;
213 }
214 }
215 }
216
217 out_unlock:
218 mutex_unlock(&i2sdev->lock);
219 return result;
220}
221
222#undef CHECK_RATE
223
224static int i2sbus_pcm_close(struct i2sbus_dev *i2sdev, int in)
225{
226 struct codec_info_item *cii;
227 struct pcm_info *pi;
228 int err = 0, tmp;
229
230 mutex_lock(&i2sdev->lock);
231
232 get_pcm_info(i2sdev, in, &pi, NULL);
233
234 list_for_each_entry(cii, &i2sdev->sound.codec_list, list) {
235 if (cii->codec->close) {
236 tmp = cii->codec->close(cii, pi->substream);
237 if (tmp)
238 err = tmp;
239 }
240 }
241
242 pi->substream = NULL;
243 pi->active = 0;
244 mutex_unlock(&i2sdev->lock);
245 return err;
246}
247
248static int i2sbus_hw_params(struct snd_pcm_substream *substream,
249 struct snd_pcm_hw_params *params)
250{
251 return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
252}
253
254static int i2sbus_hw_free(struct snd_pcm_substream *substream)
255{
256 snd_pcm_lib_free_pages(substream);
257 return 0;
258}
259
260static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)
261{
262 /* whee. Hard work now. The user has selected a bitrate
263 * and bit format, so now we have to program our
264 * I2S controller appropriately. */
265 struct snd_pcm_runtime *runtime;
266 struct dbdma_cmd *command;
267 int i, periodsize;
268 dma_addr_t offset;
269 struct bus_info bi;
270 struct codec_info_item *cii;
271 int sfr = 0; /* serial format register */
272 int dws = 0; /* data word sizes reg */
273 int input_16bit;
274 struct pcm_info *pi, *other;
275 int cnt;
276 int result = 0;
277
278 mutex_lock(&i2sdev->lock);
279
280 get_pcm_info(i2sdev, in, &pi, &other);
281
282 if (pi->dbdma_ring.running) {
283 result = -EBUSY;
284 goto out_unlock;
285 }
286
287 runtime = pi->substream->runtime;
288 pi->active = 1;
289 if (other->active &&
290 ((i2sdev->format != runtime->format)
291 || (i2sdev->rate != runtime->rate))) {
292 result = -EINVAL;
293 goto out_unlock;
294 }
295
296 i2sdev->format = runtime->format;
297 i2sdev->rate = runtime->rate;
298
299 periodsize = snd_pcm_lib_period_bytes(pi->substream);
300 pi->current_period = 0;
301
302 /* generate dbdma command ring first */
303 command = pi->dbdma_ring.cmds;
304 offset = runtime->dma_addr;
305 for (i = 0; i < pi->substream->runtime->periods;
306 i++, command++, offset += periodsize) {
307 memset(command, 0, sizeof(struct dbdma_cmd));
308 command->command =
309 cpu_to_le16((in ? INPUT_MORE : OUTPUT_MORE) | INTR_ALWAYS);
310 command->phy_addr = cpu_to_le32(offset);
311 command->req_count = cpu_to_le16(periodsize);
312 command->xfer_status = cpu_to_le16(0);
313 }
314 /* last one branches back to first */
315 command--;
316 command->command |= cpu_to_le16(BR_ALWAYS);
317 command->cmd_dep = cpu_to_le32(pi->dbdma_ring.bus_cmd_start);
318
319 /* ok, let's set the serial format and stuff */
320 switch (runtime->format) {
321 /* 16 bit formats */
322 case SNDRV_PCM_FORMAT_S16_BE:
323 case SNDRV_PCM_FORMAT_U16_BE:
324 /* FIXME: if we add different bus factors we need to
325 * do more here!! */
326 bi.bus_factor = 0;
327 list_for_each_entry(cii, &i2sdev->sound.codec_list, list) {
328 bi.bus_factor = cii->codec->bus_factor;
329 break;
330 }
331 if (!bi.bus_factor) {
332 result = -ENODEV;
333 goto out_unlock;
334 }
335 input_16bit = 1;
336 break;
337 case SNDRV_PCM_FORMAT_S32_BE:
338 case SNDRV_PCM_FORMAT_U32_BE:
339 /* force 64x bus speed, otherwise the data cannot be
340 * transferred quickly enough! */
341 bi.bus_factor = 64;
342 input_16bit = 0;
343 break;
344 default:
345 result = -EINVAL;
346 goto out_unlock;
347 }
348 /* we assume all sysclocks are the same! */
349 list_for_each_entry(cii, &i2sdev->sound.codec_list, list) {
350 bi.sysclock_factor = cii->codec->sysclock_factor;
351 break;
352 }
353
354 if (clock_and_divisors(bi.sysclock_factor,
355 bi.bus_factor,
356 runtime->rate,
357 &sfr) < 0) {
358 result = -EINVAL;
359 goto out_unlock;
360 }
361 switch (bi.bus_factor) {
362 case 32:
363 sfr |= I2S_SF_SERIAL_FORMAT_I2S_32X;
364 break;
365 case 64:
366 sfr |= I2S_SF_SERIAL_FORMAT_I2S_64X;
367 break;
368 }
369 /* FIXME: THIS ASSUMES MASTER ALL THE TIME */
370 sfr |= I2S_SF_SCLK_MASTER;
371
372 list_for_each_entry(cii, &i2sdev->sound.codec_list, list) {
373 int err = 0;
374 if (cii->codec->prepare)
375 err = cii->codec->prepare(cii, &bi, pi->substream);
376 if (err) {
377 result = err;
378 goto out_unlock;
379 }
380 }
381 /* codecs are fine with it, so set our clocks */
382 if (input_16bit)
383 dws = (2 << I2S_DWS_NUM_CHANNELS_IN_SHIFT) |
384 (2 << I2S_DWS_NUM_CHANNELS_OUT_SHIFT) |
385 I2S_DWS_DATA_IN_16BIT | I2S_DWS_DATA_OUT_16BIT;
386 else
387 dws = (2 << I2S_DWS_NUM_CHANNELS_IN_SHIFT) |
388 (2 << I2S_DWS_NUM_CHANNELS_OUT_SHIFT) |
389 I2S_DWS_DATA_IN_24BIT | I2S_DWS_DATA_OUT_24BIT;
390
391 /* early exit if already programmed correctly */
392 /* not locking these is fine since we touch them only in this function */
393 if (in_le32(&i2sdev->intfregs->serial_format) == sfr
394 && in_le32(&i2sdev->intfregs->data_word_sizes) == dws)
395 goto out_unlock;
396
397 /* let's notify the codecs about clocks going away.
398 * For now we only do mastering on the i2s cell... */
399 list_for_each_entry(cii, &i2sdev->sound.codec_list, list)
400 if (cii->codec->switch_clock)
401 cii->codec->switch_clock(cii, CLOCK_SWITCH_PREPARE_SLAVE);
402
403 i2sbus_control_enable(i2sdev->control, i2sdev);
404 i2sbus_control_cell(i2sdev->control, i2sdev, 1);
405
406 out_le32(&i2sdev->intfregs->intr_ctl, I2S_PENDING_CLOCKS_STOPPED);
407
408 i2sbus_control_clock(i2sdev->control, i2sdev, 0);
409
410 msleep(1);
411
412 /* wait for clock stopped. This can apparently take a while... */
413 cnt = 100;
414 while (cnt-- &&
415 !(in_le32(&i2sdev->intfregs->intr_ctl) & I2S_PENDING_CLOCKS_STOPPED)) {
416 msleep(5);
417 }
418 out_le32(&i2sdev->intfregs->intr_ctl, I2S_PENDING_CLOCKS_STOPPED);
419
420 /* not locking these is fine since we touch them only in this function */
421 out_le32(&i2sdev->intfregs->serial_format, sfr);
422 out_le32(&i2sdev->intfregs->data_word_sizes, dws);
423
424 i2sbus_control_enable(i2sdev->control, i2sdev);
425 i2sbus_control_cell(i2sdev->control, i2sdev, 1);
426 i2sbus_control_clock(i2sdev->control, i2sdev, 1);
427 msleep(1);
428
429 list_for_each_entry(cii, &i2sdev->sound.codec_list, list)
430 if (cii->codec->switch_clock)
431 cii->codec->switch_clock(cii, CLOCK_SWITCH_SLAVE);
432
433 out_unlock:
434 mutex_unlock(&i2sdev->lock);
435 return result;
436}
437
438static struct dbdma_cmd STOP_CMD = {
439 .command = __constant_cpu_to_le16(DBDMA_STOP),
440};
441
442static int i2sbus_pcm_trigger(struct i2sbus_dev *i2sdev, int in, int cmd)
443{
444 struct codec_info_item *cii;
445 struct pcm_info *pi;
446 int timeout;
447 struct dbdma_cmd tmp;
448 int result = 0;
449 unsigned long flags;
450
451 spin_lock_irqsave(&i2sdev->low_lock, flags);
452
453 get_pcm_info(i2sdev, in, &pi, NULL);
454
455 switch (cmd) {
456 case SNDRV_PCM_TRIGGER_START:
457 case SNDRV_PCM_TRIGGER_RESUME:
458 if (pi->dbdma_ring.running) {
459 result = -EALREADY;
460 goto out_unlock;
461 }
462 list_for_each_entry(cii, &i2sdev->sound.codec_list, list)
463 if (cii->codec->start)
464 cii->codec->start(cii, pi->substream);
465 pi->dbdma_ring.running = 1;
466
467 /* reset dma engine */
468 out_le32(&pi->dbdma->control,
469 0 | (RUN | PAUSE | FLUSH | WAKE) << 16);
470 timeout = 100;
471 while (in_le32(&pi->dbdma->status) & RUN && timeout--)
472 udelay(1);
473 if (timeout <= 0) {
474 printk(KERN_ERR
475 "i2sbus: error waiting for dma reset\n");
476 result = -ENXIO;
477 goto out_unlock;
478 }
479
480 /* write dma command buffer address to the dbdma chip */
481 out_le32(&pi->dbdma->cmdptr, pi->dbdma_ring.bus_cmd_start);
482 /* post PCI write */
483 mb();
484 (void)in_le32(&pi->dbdma->status);
485
486 /* change first command to STOP */
487 tmp = *pi->dbdma_ring.cmds;
488 *pi->dbdma_ring.cmds = STOP_CMD;
489
490 /* set running state, remember that the first command is STOP */
491 out_le32(&pi->dbdma->control, RUN | (RUN << 16));
492 timeout = 100;
493 /* wait for STOP to be executed */
494 while (in_le32(&pi->dbdma->status) & ACTIVE && timeout--)
495 udelay(1);
496 if (timeout <= 0) {
497 printk(KERN_ERR "i2sbus: error waiting for dma stop\n");
498 result = -ENXIO;
499 goto out_unlock;
500 }
501 /* again, write dma command buffer address to the dbdma chip,
502 * this time of the first real command */
503 *pi->dbdma_ring.cmds = tmp;
504 out_le32(&pi->dbdma->cmdptr, pi->dbdma_ring.bus_cmd_start);
505 /* post write */
506 mb();
507 (void)in_le32(&pi->dbdma->status);
508
509 /* reset dma engine again */
510 out_le32(&pi->dbdma->control,
511 0 | (RUN | PAUSE | FLUSH | WAKE) << 16);
512 timeout = 100;
513 while (in_le32(&pi->dbdma->status) & RUN && timeout--)
514 udelay(1);
515 if (timeout <= 0) {
516 printk(KERN_ERR
517 "i2sbus: error waiting for dma reset\n");
518 result = -ENXIO;
519 goto out_unlock;
520 }
521
522 /* wake up the chip with the next descriptor */
523 out_le32(&pi->dbdma->control,
524 (RUN | WAKE) | ((RUN | WAKE) << 16));
525 /* get the frame count */
526 pi->frame_count = in_le32(&i2sdev->intfregs->frame_count);
527
528 /* off you go! */
529 break;
530 case SNDRV_PCM_TRIGGER_STOP:
531 case SNDRV_PCM_TRIGGER_SUSPEND:
532 if (!pi->dbdma_ring.running) {
533 result = -EALREADY;
534 goto out_unlock;
535 }
536
537 /* turn off all relevant bits */
538 out_le32(&pi->dbdma->control,
539 (RUN | WAKE | FLUSH | PAUSE) << 16);
540 {
541 /* FIXME: move to own function */
542 int timeout = 5000;
543 while ((in_le32(&pi->dbdma->status) & RUN)
544 && --timeout > 0)
545 udelay(1);
546 if (!timeout)
547 printk(KERN_ERR
548 "i2sbus: timed out turning "
549 "off dbdma engine!\n");
550 }
551
552 pi->dbdma_ring.running = 0;
553 list_for_each_entry(cii, &i2sdev->sound.codec_list, list)
554 if (cii->codec->stop)
555 cii->codec->stop(cii, pi->substream);
556 break;
557 default:
558 result = -EINVAL;
559 goto out_unlock;
560 }
561
562 out_unlock:
563 spin_unlock_irqrestore(&i2sdev->low_lock, flags);
564 return result;
565}
566
567static snd_pcm_uframes_t i2sbus_pcm_pointer(struct i2sbus_dev *i2sdev, int in)
568{
569 struct pcm_info *pi;
570 u32 fc;
571
572 get_pcm_info(i2sdev, in, &pi, NULL);
573
574 fc = in_le32(&i2sdev->intfregs->frame_count);
575 fc = fc - pi->frame_count;
576
577 return (bytes_to_frames(pi->substream->runtime,
578 pi->current_period *
579 snd_pcm_lib_period_bytes(pi->substream))
580 + fc) % pi->substream->runtime->buffer_size;
581}
582
583static inline void handle_interrupt(struct i2sbus_dev *i2sdev, int in)
584{
585 struct pcm_info *pi;
586 u32 fc;
587 u32 delta;
588
589 spin_lock(&i2sdev->low_lock);
590 get_pcm_info(i2sdev, in, &pi, NULL);
591
592 if (!pi->dbdma_ring.running) {
593 /* there was still an interrupt pending
594 * while we stopped. or maybe another
595 * processor (not the one that was stopping
596 * the DMA engine) was spinning above
597 * waiting for the lock. */
598 goto out_unlock;
599 }
600
601 fc = in_le32(&i2sdev->intfregs->frame_count);
602 /* a counter overflow does not change the calculation. */
603 delta = fc - pi->frame_count;
604
605 /* update current_period */
606 while (delta >= pi->substream->runtime->period_size) {
607 pi->current_period++;
608 delta = delta - pi->substream->runtime->period_size;
609 }
610
611 if (unlikely(delta)) {
612 /* Some interrupt came late, so check the dbdma.
613 * This special case exists to syncronize the frame_count with
614 * the dbdma transfer, but is hit every once in a while. */
615 int period;
616
617 period = (in_le32(&pi->dbdma->cmdptr)
618 - pi->dbdma_ring.bus_cmd_start)
619 / sizeof(struct dbdma_cmd);
620 pi->current_period = pi->current_period
621 % pi->substream->runtime->periods;
622
623 while (pi->current_period != period) {
624 pi->current_period++;
625 pi->current_period %= pi->substream->runtime->periods;
626 /* Set delta to zero, as the frame_count value is too
627 * high (otherwise the code path will not be executed).
628 * This corrects the fact that the frame_count is too
629 * low at the beginning due to buffering. */
630 delta = 0;
631 }
632 }
633
634 pi->frame_count = fc - delta;
635 pi->current_period %= pi->substream->runtime->periods;
636
637 spin_unlock(&i2sdev->low_lock);
638 /* may call _trigger again, hence needs to be unlocked */
639 snd_pcm_period_elapsed(pi->substream);
640 return;
641 out_unlock:
642 spin_unlock(&i2sdev->low_lock);
643}
644
645irqreturn_t i2sbus_tx_intr(int irq, void *devid, struct pt_regs *regs)
646{
647 handle_interrupt((struct i2sbus_dev *)devid, 0);
648 return IRQ_HANDLED;
649}
650
651irqreturn_t i2sbus_rx_intr(int irq, void *devid, struct pt_regs * regs)
652{
653 handle_interrupt((struct i2sbus_dev *)devid, 1);
654 return IRQ_HANDLED;
655}
656
657static int i2sbus_playback_open(struct snd_pcm_substream *substream)
658{
659 struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream);
660
661 if (!i2sdev)
662 return -EINVAL;
663 i2sdev->out.substream = substream;
664 return i2sbus_pcm_open(i2sdev, 0);
665}
666
667static int i2sbus_playback_close(struct snd_pcm_substream *substream)
668{
669 struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream);
670 int err;
671
672 if (!i2sdev)
673 return -EINVAL;
674 if (i2sdev->out.substream != substream)
675 return -EINVAL;
676 err = i2sbus_pcm_close(i2sdev, 0);
677 if (!err)
678 i2sdev->out.substream = NULL;
679 return err;
680}
681
682static int i2sbus_playback_prepare(struct snd_pcm_substream *substream)
683{
684 struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream);
685
686 if (!i2sdev)
687 return -EINVAL;
688 if (i2sdev->out.substream != substream)
689 return -EINVAL;
690 return i2sbus_pcm_prepare(i2sdev, 0);
691}
692
693static int i2sbus_playback_trigger(struct snd_pcm_substream *substream, int cmd)
694{
695 struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream);
696
697 if (!i2sdev)
698 return -EINVAL;
699 if (i2sdev->out.substream != substream)
700 return -EINVAL;
701 return i2sbus_pcm_trigger(i2sdev, 0, cmd);
702}
703
704static snd_pcm_uframes_t i2sbus_playback_pointer(struct snd_pcm_substream
705 *substream)
706{
707 struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream);
708
709 if (!i2sdev)
710 return -EINVAL;
711 if (i2sdev->out.substream != substream)
712 return 0;
713 return i2sbus_pcm_pointer(i2sdev, 0);
714}
715
716static struct snd_pcm_ops i2sbus_playback_ops = {
717 .open = i2sbus_playback_open,
718 .close = i2sbus_playback_close,
719 .ioctl = snd_pcm_lib_ioctl,
720 .hw_params = i2sbus_hw_params,
721 .hw_free = i2sbus_hw_free,
722 .prepare = i2sbus_playback_prepare,
723 .trigger = i2sbus_playback_trigger,
724 .pointer = i2sbus_playback_pointer,
725};
726
727static int i2sbus_record_open(struct snd_pcm_substream *substream)
728{
729 struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream);
730
731 if (!i2sdev)
732 return -EINVAL;
733 i2sdev->in.substream = substream;
734 return i2sbus_pcm_open(i2sdev, 1);
735}
736
737static int i2sbus_record_close(struct snd_pcm_substream *substream)
738{
739 struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream);
740 int err;
741
742 if (!i2sdev)
743 return -EINVAL;
744 if (i2sdev->in.substream != substream)
745 return -EINVAL;
746 err = i2sbus_pcm_close(i2sdev, 1);
747 if (!err)
748 i2sdev->in.substream = NULL;
749 return err;
750}
751
752static int i2sbus_record_prepare(struct snd_pcm_substream *substream)
753{
754 struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream);
755
756 if (!i2sdev)
757 return -EINVAL;
758 if (i2sdev->in.substream != substream)
759 return -EINVAL;
760 return i2sbus_pcm_prepare(i2sdev, 1);
761}
762
763static int i2sbus_record_trigger(struct snd_pcm_substream *substream, int cmd)
764{
765 struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream);
766
767 if (!i2sdev)
768 return -EINVAL;
769 if (i2sdev->in.substream != substream)
770 return -EINVAL;
771 return i2sbus_pcm_trigger(i2sdev, 1, cmd);
772}
773
774static snd_pcm_uframes_t i2sbus_record_pointer(struct snd_pcm_substream
775 *substream)
776{
777 struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream);
778
779 if (!i2sdev)
780 return -EINVAL;
781 if (i2sdev->in.substream != substream)
782 return 0;
783 return i2sbus_pcm_pointer(i2sdev, 1);
784}
785
786static struct snd_pcm_ops i2sbus_record_ops = {
787 .open = i2sbus_record_open,
788 .close = i2sbus_record_close,
789 .ioctl = snd_pcm_lib_ioctl,
790 .hw_params = i2sbus_hw_params,
791 .hw_free = i2sbus_hw_free,
792 .prepare = i2sbus_record_prepare,
793 .trigger = i2sbus_record_trigger,
794 .pointer = i2sbus_record_pointer,
795};
796
797static void i2sbus_private_free(struct snd_pcm *pcm)
798{
799 struct i2sbus_dev *i2sdev = snd_pcm_chip(pcm);
800 struct codec_info_item *p, *tmp;
801
802 i2sdev->sound.pcm = NULL;
803 i2sdev->out.created = 0;
804 i2sdev->in.created = 0;
805 list_for_each_entry_safe(p, tmp, &i2sdev->sound.codec_list, list) {
806 printk(KERN_ERR "i2sbus: a codec didn't unregister!\n");
807 list_del(&p->list);
808 module_put(p->codec->owner);
809 kfree(p);
810 }
811 soundbus_dev_put(&i2sdev->sound);
812 module_put(THIS_MODULE);
813}
814
815/* FIXME: this function needs an error handling strategy with labels */
816int
817i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card,
818 struct codec_info *ci, void *data)
819{
820 int err, in = 0, out = 0;
821 struct transfer_info *tmp;
822 struct i2sbus_dev *i2sdev = soundbus_dev_to_i2sbus_dev(dev);
823 struct codec_info_item *cii;
824
825 if (!dev->pcmname || dev->pcmid == -1) {
826 printk(KERN_ERR "i2sbus: pcm name and id must be set!\n");
827 return -EINVAL;
828 }
829
830 list_for_each_entry(cii, &dev->codec_list, list) {
831 if (cii->codec_data == data)
832 return -EALREADY;
833 }
834
835 if (!ci->transfers || !ci->transfers->formats
836 || !ci->transfers->rates || !ci->usable)
837 return -EINVAL;
838
839 /* we currently code the i2s transfer on the clock, and support only
840 * 32 and 64 */
841 if (ci->bus_factor != 32 && ci->bus_factor != 64)
842 return -EINVAL;
843
844 /* If you want to fix this, you need to keep track of what transport infos
845 * are to be used, which codecs they belong to, and then fix all the
846 * sysclock/busclock stuff above to depend on which is usable */
847 list_for_each_entry(cii, &dev->codec_list, list) {
848 if (cii->codec->sysclock_factor != ci->sysclock_factor) {
849 printk(KERN_DEBUG
850 "cannot yet handle multiple different sysclocks!\n");
851 return -EINVAL;
852 }
853 if (cii->codec->bus_factor != ci->bus_factor) {
854 printk(KERN_DEBUG
855 "cannot yet handle multiple different bus clocks!\n");
856 return -EINVAL;
857 }
858 }
859
860 tmp = ci->transfers;
861 while (tmp->formats && tmp->rates) {
862 if (tmp->transfer_in)
863 in = 1;
864 else
865 out = 1;
866 tmp++;
867 }
868
869 cii = kzalloc(sizeof(struct codec_info_item), GFP_KERNEL);
870 if (!cii) {
871 printk(KERN_DEBUG "i2sbus: failed to allocate cii\n");
872 return -ENOMEM;
873 }
874
875 /* use the private data to point to the codec info */
876 cii->sdev = soundbus_dev_get(dev);
877 cii->codec = ci;
878 cii->codec_data = data;
879
880 if (!cii->sdev) {
881 printk(KERN_DEBUG
882 "i2sbus: failed to get soundbus dev reference\n");
883 kfree(cii);
884 return -ENODEV;
885 }
886
887 if (!try_module_get(THIS_MODULE)) {
888 printk(KERN_DEBUG "i2sbus: failed to get module reference!\n");
889 soundbus_dev_put(dev);
890 kfree(cii);
891 return -EBUSY;
892 }
893
894 if (!try_module_get(ci->owner)) {
895 printk(KERN_DEBUG
896 "i2sbus: failed to get module reference to codec owner!\n");
897 module_put(THIS_MODULE);
898 soundbus_dev_put(dev);
899 kfree(cii);
900 return -EBUSY;
901 }
902
903 if (!dev->pcm) {
904 err = snd_pcm_new(card,
905 dev->pcmname,
906 dev->pcmid,
907 0,
908 0,
909 &dev->pcm);
910 if (err) {
911 printk(KERN_DEBUG "i2sbus: failed to create pcm\n");
912 kfree(cii);
913 module_put(ci->owner);
914 soundbus_dev_put(dev);
915 module_put(THIS_MODULE);
916 return err;
917 }
918 }
919
920 /* ALSA yet again sucks.
921 * If it is ever fixed, remove this line. See below. */
922 out = in = 1;
923
924 if (!i2sdev->out.created && out) {
925 if (dev->pcm->card != card) {
926 /* eh? */
927 printk(KERN_ERR
928 "Can't attach same bus to different cards!\n");
929 module_put(ci->owner);
930 kfree(cii);
931 soundbus_dev_put(dev);
932 module_put(THIS_MODULE);
933 return -EINVAL;
934 }
935 if ((err =
936 snd_pcm_new_stream(dev->pcm, SNDRV_PCM_STREAM_PLAYBACK, 1))) {
937 module_put(ci->owner);
938 kfree(cii);
939 soundbus_dev_put(dev);
940 module_put(THIS_MODULE);
941 return err;
942 }
943 snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_PLAYBACK,
944 &i2sbus_playback_ops);
945 i2sdev->out.created = 1;
946 }
947
948 if (!i2sdev->in.created && in) {
949 if (dev->pcm->card != card) {
950 printk(KERN_ERR
951 "Can't attach same bus to different cards!\n");
952 module_put(ci->owner);
953 kfree(cii);
954 soundbus_dev_put(dev);
955 module_put(THIS_MODULE);
956 return -EINVAL;
957 }
958 if ((err =
959 snd_pcm_new_stream(dev->pcm, SNDRV_PCM_STREAM_CAPTURE, 1))) {
960 module_put(ci->owner);
961 kfree(cii);
962 soundbus_dev_put(dev);
963 module_put(THIS_MODULE);
964 return err;
965 }
966 snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_CAPTURE,
967 &i2sbus_record_ops);
968 i2sdev->in.created = 1;
969 }
970
971 /* so we have to register the pcm after adding any substream
972 * to it because alsa doesn't create the devices for the
973 * substreams when we add them later.
974 * Therefore, force in and out on both busses (above) and
975 * register the pcm now instead of just after creating it.
976 */
977 err = snd_device_register(card, dev->pcm);
978 if (err) {
979 printk(KERN_ERR "i2sbus: error registering new pcm\n");
980 module_put(ci->owner);
981 kfree(cii);
982 soundbus_dev_put(dev);
983 module_put(THIS_MODULE);
984 return err;
985 }
986 /* no errors any more, so let's add this to our list */
987 list_add(&cii->list, &dev->codec_list);
988
989 dev->pcm->private_data = i2sdev;
990 dev->pcm->private_free = i2sbus_private_free;
991
992 /* well, we really should support scatter/gather DMA */
993 snd_pcm_lib_preallocate_pages_for_all(
994 dev->pcm, SNDRV_DMA_TYPE_DEV,
995 snd_dma_pci_data(macio_get_pci_dev(i2sdev->macio)),
996 64 * 1024, 64 * 1024);
997
998 return 0;
999}
1000
1001void i2sbus_detach_codec(struct soundbus_dev *dev, void *data)
1002{
1003 struct codec_info_item *cii = NULL, *i;
1004
1005 list_for_each_entry(i, &dev->codec_list, list) {
1006 if (i->codec_data == data) {
1007 cii = i;
1008 break;
1009 }
1010 }
1011 if (cii) {
1012 list_del(&cii->list);
1013 module_put(cii->codec->owner);
1014 kfree(cii);
1015 }
1016 /* no more codecs, but still a pcm? */
1017 if (list_empty(&dev->codec_list) && dev->pcm) {
1018 /* the actual cleanup is done by the callback above! */
1019 snd_device_free(dev->pcm->card, dev->pcm);
1020 }
1021}
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus.h b/sound/aoa/soundbus/i2sbus/i2sbus.h
new file mode 100644
index 000000000000..cfa5162e3b0f
--- /dev/null
+++ b/sound/aoa/soundbus/i2sbus/i2sbus.h
@@ -0,0 +1,112 @@
1/*
2 * i2sbus driver -- private definitions
3 *
4 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
5 *
6 * GPL v2, can be found in COPYING.
7 */
8#ifndef __I2SBUS_H
9#define __I2SBUS_H
10#include <asm/dbdma.h>
11#include <linux/interrupt.h>
12#include <sound/pcm.h>
13#include <linux/spinlock.h>
14#include <linux/mutex.h>
15#include <asm/prom.h>
16#include "i2sbus-interface.h"
17#include "i2sbus-control.h"
18#include "../soundbus.h"
19
20struct i2sbus_control {
21 volatile struct i2s_control_regs __iomem *controlregs;
22 struct resource rsrc;
23 struct list_head list;
24};
25
26#define MAX_DBDMA_COMMANDS 32
27
28struct dbdma_command_mem {
29 dma_addr_t bus_addr;
30 dma_addr_t bus_cmd_start;
31 struct dbdma_cmd *cmds;
32 void *space;
33 int size;
34 u32 running:1;
35};
36
37struct pcm_info {
38 u32 created:1, /* has this direction been created with alsa? */
39 active:1; /* is this stream active? */
40 /* runtime information */
41 struct snd_pcm_substream *substream;
42 int current_period;
43 u32 frame_count;
44 struct dbdma_command_mem dbdma_ring;
45 volatile struct dbdma_regs __iomem *dbdma;
46};
47
48struct i2sbus_dev {
49 struct soundbus_dev sound;
50 struct macio_dev *macio;
51 struct i2sbus_control *control;
52 volatile struct i2s_interface_regs __iomem *intfregs;
53
54 struct resource resources[3];
55 struct resource *allocated_resource[3];
56 int interrupts[3];
57 char rnames[3][32];
58
59 /* info about currently active substreams */
60 struct pcm_info out, in;
61 snd_pcm_format_t format;
62 unsigned int rate;
63
64 /* list for a single controller */
65 struct list_head item;
66 /* number of bus on controller */
67 int bus_number;
68 /* for use by control layer */
69 struct pmf_function *enable,
70 *cell_enable,
71 *cell_disable,
72 *clock_enable,
73 *clock_disable;
74
75 /* locks */
76 /* spinlock for low-level interrupt locking */
77 spinlock_t low_lock;
78 /* mutex for high-level consistency */
79 struct mutex lock;
80};
81
82#define soundbus_dev_to_i2sbus_dev(sdev) \
83 container_of(sdev, struct i2sbus_dev, sound)
84
85/* pcm specific functions */
86extern int
87i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card,
88 struct codec_info *ci, void *data);
89extern void
90i2sbus_detach_codec(struct soundbus_dev *dev, void *data);
91extern irqreturn_t
92i2sbus_tx_intr(int irq, void *devid, struct pt_regs *regs);
93extern irqreturn_t
94i2sbus_rx_intr(int irq, void *devid, struct pt_regs *regs);
95
96/* control specific functions */
97extern int i2sbus_control_init(struct macio_dev* dev,
98 struct i2sbus_control **c);
99extern void i2sbus_control_destroy(struct i2sbus_control *c);
100extern int i2sbus_control_add_dev(struct i2sbus_control *c,
101 struct i2sbus_dev *i2sdev);
102extern void i2sbus_control_remove_dev(struct i2sbus_control *c,
103 struct i2sbus_dev *i2sdev);
104extern int i2sbus_control_enable(struct i2sbus_control *c,
105 struct i2sbus_dev *i2sdev);
106extern int i2sbus_control_cell(struct i2sbus_control *c,
107 struct i2sbus_dev *i2sdev,
108 int enable);
109extern int i2sbus_control_clock(struct i2sbus_control *c,
110 struct i2sbus_dev *i2sdev,
111 int enable);
112#endif /* __I2SBUS_H */
diff --git a/sound/aoa/soundbus/soundbus.h b/sound/aoa/soundbus/soundbus.h
new file mode 100644
index 000000000000..5c27297835d7
--- /dev/null
+++ b/sound/aoa/soundbus/soundbus.h
@@ -0,0 +1,202 @@
1/*
2 * soundbus generic definitions
3 *
4 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
5 *
6 * GPL v2, can be found in COPYING.
7 */
8#ifndef __SOUNDBUS_H
9#define __SOUNDBUS_H
10
11#include <asm/of_device.h>
12#include <sound/pcm.h>
13#include <linux/list.h>
14
15
16/* When switching from master to slave or the other way around,
17 * you don't want to have the codec chip acting as clock source
18 * while the bus still is.
19 * More importantly, while switch from slave to master, you need
20 * to turn off the chip's master function first, but then there's
21 * no clock for a while and other chips might reset, so we notify
22 * their drivers after having switched.
23 * The constants here are codec-point of view, so when we switch
24 * the soundbus to master we tell the codec we're going to switch
25 * and give it CLOCK_SWITCH_PREPARE_SLAVE!
26 */
27enum clock_switch {
28 CLOCK_SWITCH_PREPARE_SLAVE,
29 CLOCK_SWITCH_PREPARE_MASTER,
30 CLOCK_SWITCH_SLAVE,
31 CLOCK_SWITCH_MASTER,
32 CLOCK_SWITCH_NOTIFY,
33};
34
35/* information on a transfer the codec can take */
36struct transfer_info {
37 u64 formats; /* SNDRV_PCM_FMTBIT_* */
38 unsigned int rates; /* SNDRV_PCM_RATE_* */
39 /* flags */
40 u32 transfer_in:1, /* input = 1, output = 0 */
41 must_be_clock_source:1;
42 /* for codecs to distinguish among their TIs */
43 int tag;
44};
45
46struct codec_info_item {
47 struct codec_info *codec;
48 void *codec_data;
49 struct soundbus_dev *sdev;
50 /* internal, to be used by the soundbus provider */
51 struct list_head list;
52};
53
54/* for prepare, where the codecs need to know
55 * what we're going to drive the bus with */
56struct bus_info {
57 /* see below */
58 int sysclock_factor;
59 int bus_factor;
60};
61
62/* information on the codec itself, plus function pointers */
63struct codec_info {
64 /* the module this lives in */
65 struct module *owner;
66
67 /* supported transfer possibilities, array terminated by
68 * formats or rates being 0. */
69 struct transfer_info *transfers;
70
71 /* Master clock speed factor
72 * to be used (master clock speed = sysclock_factor * sampling freq)
73 * Unused if the soundbus provider has no such notion.
74 */
75 int sysclock_factor;
76
77 /* Bus factor, bus clock speed = bus_factor * sampling freq)
78 * Unused if the soundbus provider has no such notion.
79 */
80 int bus_factor;
81
82 /* operations */
83 /* clock switching, see above */
84 int (*switch_clock)(struct codec_info_item *cii,
85 enum clock_switch clock);
86
87 /* called for each transfer_info when the user
88 * opens the pcm device to determine what the
89 * hardware can support at this point in time.
90 * That can depend on other user-switchable controls.
91 * Return 1 if usable, 0 if not.
92 * out points to another instance of a transfer_info
93 * which is initialised to the values in *ti, and
94 * it's format and rate values can be modified by
95 * the callback if it is necessary to further restrict
96 * the formats that can be used at the moment, for
97 * example when one codec has multiple logical codec
98 * info structs for multiple inputs.
99 */
100 int (*usable)(struct codec_info_item *cii,
101 struct transfer_info *ti,
102 struct transfer_info *out);
103
104 /* called when pcm stream is opened, probably not implemented
105 * most of the time since it isn't too useful */
106 int (*open)(struct codec_info_item *cii,
107 struct snd_pcm_substream *substream);
108
109 /* called when the pcm stream is closed, at this point
110 * the user choices can all be unlocked (see below) */
111 int (*close)(struct codec_info_item *cii,
112 struct snd_pcm_substream *substream);
113
114 /* if the codec must forbid some user choices because
115 * they are not valid with the substream/transfer info,
116 * it must do so here. Example: no digital output for
117 * incompatible framerate, say 8KHz, on Onyx.
118 * If the selected stuff in the substream is NOT
119 * compatible, you have to reject this call! */
120 int (*prepare)(struct codec_info_item *cii,
121 struct bus_info *bi,
122 struct snd_pcm_substream *substream);
123
124 /* start() is called before data is pushed to the codec.
125 * Note that start() must be atomic! */
126 int (*start)(struct codec_info_item *cii,
127 struct snd_pcm_substream *substream);
128
129 /* stop() is called after data is no longer pushed to the codec.
130 * Note that stop() must be atomic! */
131 int (*stop)(struct codec_info_item *cii,
132 struct snd_pcm_substream *substream);
133
134 int (*suspend)(struct codec_info_item *cii, pm_message_t state);
135 int (*resume)(struct codec_info_item *cii);
136};
137
138/* information on a soundbus device */
139struct soundbus_dev {
140 /* the bus it belongs to */
141 struct list_head onbuslist;
142
143 /* the of device it represents */
144 struct of_device ofdev;
145
146 /* what modules go by */
147 char modalias[32];
148
149 /* These fields must be before attach_codec can be called.
150 * They should be set by the owner of the alsa card object
151 * that is needed, and whoever sets them must make sure
152 * that they are unique within that alsa card object. */
153 char *pcmname;
154 int pcmid;
155
156 /* this is assigned by the soundbus provider in attach_codec */
157 struct snd_pcm *pcm;
158
159 /* operations */
160 /* attach a codec to this soundbus, give the alsa
161 * card object the PCMs for this soundbus should be in.
162 * The 'data' pointer must be unique, it is used as the
163 * key for detach_codec(). */
164 int (*attach_codec)(struct soundbus_dev *dev, struct snd_card *card,
165 struct codec_info *ci, void *data);
166 void (*detach_codec)(struct soundbus_dev *dev, void *data);
167 /* TODO: suspend/resume */
168
169 /* private for the soundbus provider */
170 struct list_head codec_list;
171 u32 have_out:1, have_in:1;
172};
173#define to_soundbus_device(d) container_of(d, struct soundbus_dev, ofdev.dev)
174#define of_to_soundbus_device(d) container_of(d, struct soundbus_dev, ofdev)
175
176extern int soundbus_add_one(struct soundbus_dev *dev);
177extern void soundbus_remove_one(struct soundbus_dev *dev);
178
179extern struct soundbus_dev *soundbus_dev_get(struct soundbus_dev *dev);
180extern void soundbus_dev_put(struct soundbus_dev *dev);
181
182struct soundbus_driver {
183 char *name;
184 struct module *owner;
185
186 /* we don't implement any matching at all */
187
188 int (*probe)(struct soundbus_dev* dev);
189 int (*remove)(struct soundbus_dev* dev);
190
191 int (*suspend)(struct soundbus_dev* dev, pm_message_t state);
192 int (*resume)(struct soundbus_dev* dev);
193 int (*shutdown)(struct soundbus_dev* dev);
194
195 struct device_driver driver;
196};
197#define to_soundbus_driver(drv) container_of(drv,struct soundbus_driver, driver)
198
199extern int soundbus_register_driver(struct soundbus_driver *drv);
200extern void soundbus_unregister_driver(struct soundbus_driver *drv);
201
202#endif /* __SOUNDBUS_H */
diff --git a/sound/aoa/soundbus/sysfs.c b/sound/aoa/soundbus/sysfs.c
new file mode 100644
index 000000000000..d31f8146952a
--- /dev/null
+++ b/sound/aoa/soundbus/sysfs.c
@@ -0,0 +1,43 @@
1#include <linux/config.h>
2#include <linux/kernel.h>
3#include <linux/stat.h>
4/* FIX UP */
5#include "soundbus.h"
6
7#define soundbus_config_of_attr(field, format_string) \
8static ssize_t \
9field##_show (struct device *dev, struct device_attribute *attr, \
10 char *buf) \
11{ \
12 struct soundbus_dev *mdev = to_soundbus_device (dev); \
13 return sprintf (buf, format_string, mdev->ofdev.node->field); \
14}
15
16static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
17 char *buf)
18{
19 struct soundbus_dev *sdev = to_soundbus_device(dev);
20 struct of_device *of = &sdev->ofdev;
21 int length;
22
23 if (*sdev->modalias) {
24 strlcpy(buf, sdev->modalias, sizeof(sdev->modalias) + 1);
25 strcat(buf, "\n");
26 length = strlen(buf);
27 } else {
28 length = sprintf(buf, "of:N%sT%s\n",
29 of->node->name, of->node->type);
30 }
31
32 return length;
33}
34
35soundbus_config_of_attr (name, "%s\n");
36soundbus_config_of_attr (type, "%s\n");
37
38struct device_attribute soundbus_dev_attrs[] = {
39 __ATTR_RO(name),
40 __ATTR_RO(type),
41 __ATTR_RO(modalias),
42 __ATTR_NULL
43};
diff --git a/sound/arm/sa11xx-uda1341.c b/sound/arm/sa11xx-uda1341.c
index 13057d92f08a..b88fb0c5a68a 100644
--- a/sound/arm/sa11xx-uda1341.c
+++ b/sound/arm/sa11xx-uda1341.c
@@ -112,7 +112,7 @@ MODULE_LICENSE("GPL");
112MODULE_DESCRIPTION("SA1100/SA1111 + UDA1341TS driver for ALSA"); 112MODULE_DESCRIPTION("SA1100/SA1111 + UDA1341TS driver for ALSA");
113MODULE_SUPPORTED_DEVICE("{{UDA1341,iPAQ H3600 UDA1341TS}}"); 113MODULE_SUPPORTED_DEVICE("{{UDA1341,iPAQ H3600 UDA1341TS}}");
114 114
115static char *id = NULL; /* ID for this card */ 115static char *id; /* ID for this card */
116 116
117module_param(id, charp, 0444); 117module_param(id, charp, 0444);
118MODULE_PARM_DESC(id, "ID string for SA1100/SA1111 + UDA1341TS soundcard."); 118MODULE_PARM_DESC(id, "ID string for SA1100/SA1111 + UDA1341TS soundcard.");
@@ -984,11 +984,15 @@ static int __init sa11xx_uda1341_init(void)
984 if ((err = platform_driver_register(&sa11xx_uda1341_driver)) < 0) 984 if ((err = platform_driver_register(&sa11xx_uda1341_driver)) < 0)
985 return err; 985 return err;
986 device = platform_device_register_simple(SA11XX_UDA1341_DRIVER, -1, NULL, 0); 986 device = platform_device_register_simple(SA11XX_UDA1341_DRIVER, -1, NULL, 0);
987 if (IS_ERR(device)) { 987 if (!IS_ERR(device)) {
988 platform_driver_unregister(&sa11xx_uda1341_driver); 988 if (platform_get_drvdata(device))
989 return PTR_ERR(device); 989 return 0;
990 } 990 platform_device_unregister(device);
991 return 0; 991 err = -ENODEV
992 } else
993 err = PTR_ERR(device);
994 platform_driver_unregister(&sa11xx_uda1341_driver);
995 return err;
992} 996}
993 997
994static void __exit sa11xx_uda1341_exit(void) 998static void __exit sa11xx_uda1341_exit(void)
diff --git a/sound/core/control.c b/sound/core/control.c
index 22565c9b9603..bb397eaa7187 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -176,6 +176,8 @@ void snd_ctl_notify(struct snd_card *card, unsigned int mask,
176 read_unlock(&card->ctl_files_rwlock); 176 read_unlock(&card->ctl_files_rwlock);
177} 177}
178 178
179EXPORT_SYMBOL(snd_ctl_notify);
180
179/** 181/**
180 * snd_ctl_new - create a control instance from the template 182 * snd_ctl_new - create a control instance from the template
181 * @control: the control template 183 * @control: the control template
@@ -204,6 +206,8 @@ struct snd_kcontrol *snd_ctl_new(struct snd_kcontrol *control, unsigned int acce
204 return kctl; 206 return kctl;
205} 207}
206 208
209EXPORT_SYMBOL(snd_ctl_new);
210
207/** 211/**
208 * snd_ctl_new1 - create a control instance from the template 212 * snd_ctl_new1 - create a control instance from the template
209 * @ncontrol: the initialization record 213 * @ncontrol: the initialization record
@@ -242,6 +246,8 @@ struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new *ncontrol,
242 return snd_ctl_new(&kctl, access); 246 return snd_ctl_new(&kctl, access);
243} 247}
244 248
249EXPORT_SYMBOL(snd_ctl_new1);
250
245/** 251/**
246 * snd_ctl_free_one - release the control instance 252 * snd_ctl_free_one - release the control instance
247 * @kcontrol: the control instance 253 * @kcontrol: the control instance
@@ -259,6 +265,8 @@ void snd_ctl_free_one(struct snd_kcontrol *kcontrol)
259 } 265 }
260} 266}
261 267
268EXPORT_SYMBOL(snd_ctl_free_one);
269
262static unsigned int snd_ctl_hole_check(struct snd_card *card, 270static unsigned int snd_ctl_hole_check(struct snd_card *card,
263 unsigned int count) 271 unsigned int count)
264{ 272{
@@ -347,6 +355,8 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
347 return err; 355 return err;
348} 356}
349 357
358EXPORT_SYMBOL(snd_ctl_add);
359
350/** 360/**
351 * snd_ctl_remove - remove the control from the card and release it 361 * snd_ctl_remove - remove the control from the card and release it
352 * @card: the card instance 362 * @card: the card instance
@@ -373,6 +383,8 @@ int snd_ctl_remove(struct snd_card *card, struct snd_kcontrol *kcontrol)
373 return 0; 383 return 0;
374} 384}
375 385
386EXPORT_SYMBOL(snd_ctl_remove);
387
376/** 388/**
377 * snd_ctl_remove_id - remove the control of the given id and release it 389 * snd_ctl_remove_id - remove the control of the given id and release it
378 * @card: the card instance 390 * @card: the card instance
@@ -399,6 +411,8 @@ int snd_ctl_remove_id(struct snd_card *card, struct snd_ctl_elem_id *id)
399 return ret; 411 return ret;
400} 412}
401 413
414EXPORT_SYMBOL(snd_ctl_remove_id);
415
402/** 416/**
403 * snd_ctl_remove_unlocked_id - remove the unlocked control of the given id and release it 417 * snd_ctl_remove_unlocked_id - remove the unlocked control of the given id and release it
404 * @file: active control handle 418 * @file: active control handle
@@ -461,6 +475,8 @@ int snd_ctl_rename_id(struct snd_card *card, struct snd_ctl_elem_id *src_id,
461 return 0; 475 return 0;
462} 476}
463 477
478EXPORT_SYMBOL(snd_ctl_rename_id);
479
464/** 480/**
465 * snd_ctl_find_numid - find the control instance with the given number-id 481 * snd_ctl_find_numid - find the control instance with the given number-id
466 * @card: the card instance 482 * @card: the card instance
@@ -487,6 +503,8 @@ struct snd_kcontrol *snd_ctl_find_numid(struct snd_card *card, unsigned int numi
487 return NULL; 503 return NULL;
488} 504}
489 505
506EXPORT_SYMBOL(snd_ctl_find_numid);
507
490/** 508/**
491 * snd_ctl_find_id - find the control instance with the given id 509 * snd_ctl_find_id - find the control instance with the given id
492 * @card: the card instance 510 * @card: the card instance
@@ -527,6 +545,8 @@ struct snd_kcontrol *snd_ctl_find_id(struct snd_card *card,
527 return NULL; 545 return NULL;
528} 546}
529 547
548EXPORT_SYMBOL(snd_ctl_find_id);
549
530static int snd_ctl_card_info(struct snd_card *card, struct snd_ctl_file * ctl, 550static int snd_ctl_card_info(struct snd_card *card, struct snd_ctl_file * ctl,
531 unsigned int cmd, void __user *arg) 551 unsigned int cmd, void __user *arg)
532{ 552{
@@ -704,6 +724,8 @@ int snd_ctl_elem_read(struct snd_card *card, struct snd_ctl_elem_value *control)
704 return result; 724 return result;
705} 725}
706 726
727EXPORT_SYMBOL(snd_ctl_elem_read);
728
707static int snd_ctl_elem_read_user(struct snd_card *card, 729static int snd_ctl_elem_read_user(struct snd_card *card,
708 struct snd_ctl_elem_value __user *_control) 730 struct snd_ctl_elem_value __user *_control)
709{ 731{
@@ -767,6 +789,8 @@ int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
767 return result; 789 return result;
768} 790}
769 791
792EXPORT_SYMBOL(snd_ctl_elem_write);
793
770static int snd_ctl_elem_write_user(struct snd_ctl_file *file, 794static int snd_ctl_elem_write_user(struct snd_ctl_file *file,
771 struct snd_ctl_elem_value __user *_control) 795 struct snd_ctl_elem_value __user *_control)
772{ 796{
@@ -1199,11 +1223,15 @@ int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn)
1199 return _snd_ctl_register_ioctl(fcn, &snd_control_ioctls); 1223 return _snd_ctl_register_ioctl(fcn, &snd_control_ioctls);
1200} 1224}
1201 1225
1226EXPORT_SYMBOL(snd_ctl_register_ioctl);
1227
1202#ifdef CONFIG_COMPAT 1228#ifdef CONFIG_COMPAT
1203int snd_ctl_register_ioctl_compat(snd_kctl_ioctl_func_t fcn) 1229int snd_ctl_register_ioctl_compat(snd_kctl_ioctl_func_t fcn)
1204{ 1230{
1205 return _snd_ctl_register_ioctl(fcn, &snd_control_compat_ioctls); 1231 return _snd_ctl_register_ioctl(fcn, &snd_control_compat_ioctls);
1206} 1232}
1233
1234EXPORT_SYMBOL(snd_ctl_register_ioctl_compat);
1207#endif 1235#endif
1208 1236
1209/* 1237/*
@@ -1236,12 +1264,15 @@ int snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn)
1236 return _snd_ctl_unregister_ioctl(fcn, &snd_control_ioctls); 1264 return _snd_ctl_unregister_ioctl(fcn, &snd_control_ioctls);
1237} 1265}
1238 1266
1267EXPORT_SYMBOL(snd_ctl_unregister_ioctl);
1268
1239#ifdef CONFIG_COMPAT 1269#ifdef CONFIG_COMPAT
1240int snd_ctl_unregister_ioctl_compat(snd_kctl_ioctl_func_t fcn) 1270int snd_ctl_unregister_ioctl_compat(snd_kctl_ioctl_func_t fcn)
1241{ 1271{
1242 return _snd_ctl_unregister_ioctl(fcn, &snd_control_compat_ioctls); 1272 return _snd_ctl_unregister_ioctl(fcn, &snd_control_compat_ioctls);
1243} 1273}
1244 1274
1275EXPORT_SYMBOL(snd_ctl_unregister_ioctl_compat);
1245#endif 1276#endif
1246 1277
1247static int snd_ctl_fasync(int fd, struct file * file, int on) 1278static int snd_ctl_fasync(int fd, struct file * file, int on)
diff --git a/sound/core/device.c b/sound/core/device.c
index b1cf6ec56784..6ce4da4a1081 100644
--- a/sound/core/device.c
+++ b/sound/core/device.c
@@ -63,6 +63,8 @@ int snd_device_new(struct snd_card *card, snd_device_type_t type,
63 return 0; 63 return 0;
64} 64}
65 65
66EXPORT_SYMBOL(snd_device_new);
67
66/** 68/**
67 * snd_device_free - release the device from the card 69 * snd_device_free - release the device from the card
68 * @card: the card instance 70 * @card: the card instance
@@ -107,6 +109,8 @@ int snd_device_free(struct snd_card *card, void *device_data)
107 return -ENXIO; 109 return -ENXIO;
108} 110}
109 111
112EXPORT_SYMBOL(snd_device_free);
113
110/** 114/**
111 * snd_device_disconnect - disconnect the device 115 * snd_device_disconnect - disconnect the device
112 * @card: the card instance 116 * @card: the card instance
@@ -182,6 +186,8 @@ int snd_device_register(struct snd_card *card, void *device_data)
182 return -ENXIO; 186 return -ENXIO;
183} 187}
184 188
189EXPORT_SYMBOL(snd_device_register);
190
185/* 191/*
186 * register all the devices on the card. 192 * register all the devices on the card.
187 * called from init.c 193 * called from init.c
diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c
index 2524e66eccdd..8bd0dcc93eba 100644
--- a/sound/core/hwdep.c
+++ b/sound/core/hwdep.c
@@ -486,7 +486,6 @@ static void __init snd_hwdep_proc_init(void)
486 struct snd_info_entry *entry; 486 struct snd_info_entry *entry;
487 487
488 if ((entry = snd_info_create_module_entry(THIS_MODULE, "hwdep", NULL)) != NULL) { 488 if ((entry = snd_info_create_module_entry(THIS_MODULE, "hwdep", NULL)) != NULL) {
489 entry->c.text.read_size = PAGE_SIZE;
490 entry->c.text.read = snd_hwdep_proc_read; 489 entry->c.text.read = snd_hwdep_proc_read;
491 if (snd_info_register(entry) < 0) { 490 if (snd_info_register(entry) < 0) {
492 snd_info_free_entry(entry); 491 snd_info_free_entry(entry);
diff --git a/sound/core/info.c b/sound/core/info.c
index 2582b74d3199..10c1772bf3ea 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -21,7 +21,6 @@
21 21
22#include <sound/driver.h> 22#include <sound/driver.h>
23#include <linux/init.h> 23#include <linux/init.h>
24#include <linux/vmalloc.h>
25#include <linux/time.h> 24#include <linux/time.h>
26#include <linux/smp_lock.h> 25#include <linux/smp_lock.h>
27#include <linux/string.h> 26#include <linux/string.h>
@@ -82,6 +81,24 @@ static int snd_info_version_init(void);
82static int snd_info_version_done(void); 81static int snd_info_version_done(void);
83 82
84 83
84/* resize the proc r/w buffer */
85static int resize_info_buffer(struct snd_info_buffer *buffer,
86 unsigned int nsize)
87{
88 char *nbuf;
89
90 nsize = PAGE_ALIGN(nsize);
91 nbuf = kmalloc(nsize, GFP_KERNEL);
92 if (! nbuf)
93 return -ENOMEM;
94
95 memcpy(nbuf, buffer->buffer, buffer->len);
96 kfree(buffer->buffer);
97 buffer->buffer = nbuf;
98 buffer->len = nsize;
99 return 0;
100}
101
85/** 102/**
86 * snd_iprintf - printf on the procfs buffer 103 * snd_iprintf - printf on the procfs buffer
87 * @buffer: the procfs buffer 104 * @buffer: the procfs buffer
@@ -95,30 +112,43 @@ int snd_iprintf(struct snd_info_buffer *buffer, char *fmt,...)
95{ 112{
96 va_list args; 113 va_list args;
97 int len, res; 114 int len, res;
115 int err = 0;
98 116
117 might_sleep();
99 if (buffer->stop || buffer->error) 118 if (buffer->stop || buffer->error)
100 return 0; 119 return 0;
101 len = buffer->len - buffer->size; 120 len = buffer->len - buffer->size;
102 va_start(args, fmt); 121 va_start(args, fmt);
103 res = vsnprintf(buffer->curr, len, fmt, args); 122 for (;;) {
104 va_end(args); 123 res = vsnprintf(buffer->buffer + buffer->curr, len, fmt, args);
105 if (res >= len) { 124 if (res < len)
106 buffer->stop = 1; 125 break;
107 return 0; 126 err = resize_info_buffer(buffer, buffer->len + PAGE_SIZE);
127 if (err < 0)
128 break;
129 len = buffer->len - buffer->size;
108 } 130 }
131 va_end(args);
132
133 if (err < 0)
134 return err;
109 buffer->curr += res; 135 buffer->curr += res;
110 buffer->size += res; 136 buffer->size += res;
111 return res; 137 return res;
112} 138}
113 139
140EXPORT_SYMBOL(snd_iprintf);
141
114/* 142/*
115 143
116 */ 144 */
117 145
118static struct proc_dir_entry *snd_proc_root = NULL; 146static struct proc_dir_entry *snd_proc_root;
119struct snd_info_entry *snd_seq_root = NULL; 147struct snd_info_entry *snd_seq_root;
148EXPORT_SYMBOL(snd_seq_root);
149
120#ifdef CONFIG_SND_OSSEMUL 150#ifdef CONFIG_SND_OSSEMUL
121struct snd_info_entry *snd_oss_root = NULL; 151struct snd_info_entry *snd_oss_root;
122#endif 152#endif
123 153
124static inline void snd_info_entry_prepare(struct proc_dir_entry *de) 154static inline void snd_info_entry_prepare(struct proc_dir_entry *de)
@@ -221,7 +251,7 @@ static ssize_t snd_info_entry_write(struct file *file, const char __user *buffer
221 struct snd_info_private_data *data; 251 struct snd_info_private_data *data;
222 struct snd_info_entry *entry; 252 struct snd_info_entry *entry;
223 struct snd_info_buffer *buf; 253 struct snd_info_buffer *buf;
224 size_t size = 0; 254 ssize_t size = 0;
225 loff_t pos; 255 loff_t pos;
226 256
227 data = file->private_data; 257 data = file->private_data;
@@ -237,14 +267,20 @@ static ssize_t snd_info_entry_write(struct file *file, const char __user *buffer
237 buf = data->wbuffer; 267 buf = data->wbuffer;
238 if (buf == NULL) 268 if (buf == NULL)
239 return -EIO; 269 return -EIO;
240 if (pos >= buf->len) 270 mutex_lock(&entry->access);
241 return -ENOMEM; 271 if (pos + count >= buf->len) {
242 size = buf->len - pos; 272 if (resize_info_buffer(buf, pos + count)) {
243 size = min(count, size); 273 mutex_unlock(&entry->access);
244 if (copy_from_user(buf->buffer + pos, buffer, size)) 274 return -ENOMEM;
275 }
276 }
277 if (copy_from_user(buf->buffer + pos, buffer, count)) {
278 mutex_unlock(&entry->access);
245 return -EFAULT; 279 return -EFAULT;
246 if ((long)buf->size < pos + size) 280 }
247 buf->size = pos + size; 281 buf->size = pos + count;
282 mutex_unlock(&entry->access);
283 size = count;
248 break; 284 break;
249 case SNDRV_INFO_CONTENT_DATA: 285 case SNDRV_INFO_CONTENT_DATA:
250 if (entry->c.ops->write) 286 if (entry->c.ops->write)
@@ -279,18 +315,14 @@ static int snd_info_entry_open(struct inode *inode, struct file *file)
279 } 315 }
280 mode = file->f_flags & O_ACCMODE; 316 mode = file->f_flags & O_ACCMODE;
281 if (mode == O_RDONLY || mode == O_RDWR) { 317 if (mode == O_RDONLY || mode == O_RDWR) {
282 if ((entry->content == SNDRV_INFO_CONTENT_TEXT && 318 if ((entry->content == SNDRV_INFO_CONTENT_DATA &&
283 !entry->c.text.read_size) ||
284 (entry->content == SNDRV_INFO_CONTENT_DATA &&
285 entry->c.ops->read == NULL)) { 319 entry->c.ops->read == NULL)) {
286 err = -ENODEV; 320 err = -ENODEV;
287 goto __error; 321 goto __error;
288 } 322 }
289 } 323 }
290 if (mode == O_WRONLY || mode == O_RDWR) { 324 if (mode == O_WRONLY || mode == O_RDWR) {
291 if ((entry->content == SNDRV_INFO_CONTENT_TEXT && 325 if ((entry->content == SNDRV_INFO_CONTENT_DATA &&
292 !entry->c.text.write_size) ||
293 (entry->content == SNDRV_INFO_CONTENT_DATA &&
294 entry->c.ops->write == NULL)) { 326 entry->c.ops->write == NULL)) {
295 err = -ENODEV; 327 err = -ENODEV;
296 goto __error; 328 goto __error;
@@ -306,49 +338,23 @@ static int snd_info_entry_open(struct inode *inode, struct file *file)
306 case SNDRV_INFO_CONTENT_TEXT: 338 case SNDRV_INFO_CONTENT_TEXT:
307 if (mode == O_RDONLY || mode == O_RDWR) { 339 if (mode == O_RDONLY || mode == O_RDWR) {
308 buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); 340 buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
309 if (buffer == NULL) { 341 if (buffer == NULL)
310 kfree(data); 342 goto __nomem;
311 err = -ENOMEM;
312 goto __error;
313 }
314 buffer->len = (entry->c.text.read_size +
315 (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
316 buffer->buffer = vmalloc(buffer->len);
317 if (buffer->buffer == NULL) {
318 kfree(buffer);
319 kfree(data);
320 err = -ENOMEM;
321 goto __error;
322 }
323 buffer->curr = buffer->buffer;
324 data->rbuffer = buffer; 343 data->rbuffer = buffer;
344 buffer->len = PAGE_SIZE;
345 buffer->buffer = kmalloc(buffer->len, GFP_KERNEL);
346 if (buffer->buffer == NULL)
347 goto __nomem;
325 } 348 }
326 if (mode == O_WRONLY || mode == O_RDWR) { 349 if (mode == O_WRONLY || mode == O_RDWR) {
327 buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); 350 buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
328 if (buffer == NULL) { 351 if (buffer == NULL)
329 if (mode == O_RDWR) { 352 goto __nomem;
330 vfree(data->rbuffer->buffer);
331 kfree(data->rbuffer);
332 }
333 kfree(data);
334 err = -ENOMEM;
335 goto __error;
336 }
337 buffer->len = (entry->c.text.write_size +
338 (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
339 buffer->buffer = vmalloc(buffer->len);
340 if (buffer->buffer == NULL) {
341 if (mode == O_RDWR) {
342 vfree(data->rbuffer->buffer);
343 kfree(data->rbuffer);
344 }
345 kfree(buffer);
346 kfree(data);
347 err = -ENOMEM;
348 goto __error;
349 }
350 buffer->curr = buffer->buffer;
351 data->wbuffer = buffer; 353 data->wbuffer = buffer;
354 buffer->len = PAGE_SIZE;
355 buffer->buffer = kmalloc(buffer->len, GFP_KERNEL);
356 if (buffer->buffer == NULL)
357 goto __nomem;
352 } 358 }
353 break; 359 break;
354 case SNDRV_INFO_CONTENT_DATA: /* data */ 360 case SNDRV_INFO_CONTENT_DATA: /* data */
@@ -373,6 +379,17 @@ static int snd_info_entry_open(struct inode *inode, struct file *file)
373 } 379 }
374 return 0; 380 return 0;
375 381
382 __nomem:
383 if (data->rbuffer) {
384 kfree(data->rbuffer->buffer);
385 kfree(data->rbuffer);
386 }
387 if (data->wbuffer) {
388 kfree(data->wbuffer->buffer);
389 kfree(data->wbuffer);
390 }
391 kfree(data);
392 err = -ENOMEM;
376 __error: 393 __error:
377 module_put(entry->module); 394 module_put(entry->module);
378 __error1: 395 __error1:
@@ -391,11 +408,11 @@ static int snd_info_entry_release(struct inode *inode, struct file *file)
391 entry = data->entry; 408 entry = data->entry;
392 switch (entry->content) { 409 switch (entry->content) {
393 case SNDRV_INFO_CONTENT_TEXT: 410 case SNDRV_INFO_CONTENT_TEXT:
394 if (mode == O_RDONLY || mode == O_RDWR) { 411 if (data->rbuffer) {
395 vfree(data->rbuffer->buffer); 412 kfree(data->rbuffer->buffer);
396 kfree(data->rbuffer); 413 kfree(data->rbuffer);
397 } 414 }
398 if (mode == O_WRONLY || mode == O_RDWR) { 415 if (data->wbuffer) {
399 if (entry->c.text.write) { 416 if (entry->c.text.write) {
400 entry->c.text.write(entry, data->wbuffer); 417 entry->c.text.write(entry, data->wbuffer);
401 if (data->wbuffer->error) { 418 if (data->wbuffer->error) {
@@ -404,7 +421,7 @@ static int snd_info_entry_release(struct inode *inode, struct file *file)
404 data->wbuffer->error); 421 data->wbuffer->error);
405 } 422 }
406 } 423 }
407 vfree(data->wbuffer->buffer); 424 kfree(data->wbuffer->buffer);
408 kfree(data->wbuffer); 425 kfree(data->wbuffer);
409 } 426 }
410 break; 427 break;
@@ -664,29 +681,29 @@ int snd_info_get_line(struct snd_info_buffer *buffer, char *line, int len)
664 if (len <= 0 || buffer->stop || buffer->error) 681 if (len <= 0 || buffer->stop || buffer->error)
665 return 1; 682 return 1;
666 while (--len > 0) { 683 while (--len > 0) {
667 c = *buffer->curr++; 684 c = buffer->buffer[buffer->curr++];
668 if (c == '\n') { 685 if (c == '\n') {
669 if ((buffer->curr - buffer->buffer) >= (long)buffer->size) { 686 if (buffer->curr >= buffer->size)
670 buffer->stop = 1; 687 buffer->stop = 1;
671 }
672 break; 688 break;
673 } 689 }
674 *line++ = c; 690 *line++ = c;
675 if ((buffer->curr - buffer->buffer) >= (long)buffer->size) { 691 if (buffer->curr >= buffer->size) {
676 buffer->stop = 1; 692 buffer->stop = 1;
677 break; 693 break;
678 } 694 }
679 } 695 }
680 while (c != '\n' && !buffer->stop) { 696 while (c != '\n' && !buffer->stop) {
681 c = *buffer->curr++; 697 c = buffer->buffer[buffer->curr++];
682 if ((buffer->curr - buffer->buffer) >= (long)buffer->size) { 698 if (buffer->curr >= buffer->size)
683 buffer->stop = 1; 699 buffer->stop = 1;
684 }
685 } 700 }
686 *line = '\0'; 701 *line = '\0';
687 return 0; 702 return 0;
688} 703}
689 704
705EXPORT_SYMBOL(snd_info_get_line);
706
690/** 707/**
691 * snd_info_get_str - parse a string token 708 * snd_info_get_str - parse a string token
692 * @dest: the buffer to store the string token 709 * @dest: the buffer to store the string token
@@ -723,6 +740,8 @@ char *snd_info_get_str(char *dest, char *src, int len)
723 return src; 740 return src;
724} 741}
725 742
743EXPORT_SYMBOL(snd_info_get_str);
744
726/** 745/**
727 * snd_info_create_entry - create an info entry 746 * snd_info_create_entry - create an info entry
728 * @name: the proc file name 747 * @name: the proc file name
@@ -774,6 +793,8 @@ struct snd_info_entry *snd_info_create_module_entry(struct module * module,
774 return entry; 793 return entry;
775} 794}
776 795
796EXPORT_SYMBOL(snd_info_create_module_entry);
797
777/** 798/**
778 * snd_info_create_card_entry - create an info entry for the given card 799 * snd_info_create_card_entry - create an info entry for the given card
779 * @card: the card instance 800 * @card: the card instance
@@ -797,6 +818,8 @@ struct snd_info_entry *snd_info_create_card_entry(struct snd_card *card,
797 return entry; 818 return entry;
798} 819}
799 820
821EXPORT_SYMBOL(snd_info_create_card_entry);
822
800static int snd_info_dev_free_entry(struct snd_device *device) 823static int snd_info_dev_free_entry(struct snd_device *device)
801{ 824{
802 struct snd_info_entry *entry = device->device_data; 825 struct snd_info_entry *entry = device->device_data;
@@ -867,6 +890,8 @@ int snd_card_proc_new(struct snd_card *card, const char *name,
867 return 0; 890 return 0;
868} 891}
869 892
893EXPORT_SYMBOL(snd_card_proc_new);
894
870/** 895/**
871 * snd_info_free_entry - release the info entry 896 * snd_info_free_entry - release the info entry
872 * @entry: the info entry 897 * @entry: the info entry
@@ -883,6 +908,8 @@ void snd_info_free_entry(struct snd_info_entry * entry)
883 kfree(entry); 908 kfree(entry);
884} 909}
885 910
911EXPORT_SYMBOL(snd_info_free_entry);
912
886/** 913/**
887 * snd_info_register - register the info entry 914 * snd_info_register - register the info entry
888 * @entry: the info entry 915 * @entry: the info entry
@@ -913,6 +940,8 @@ int snd_info_register(struct snd_info_entry * entry)
913 return 0; 940 return 0;
914} 941}
915 942
943EXPORT_SYMBOL(snd_info_register);
944
916/** 945/**
917 * snd_info_unregister - de-register the info entry 946 * snd_info_unregister - de-register the info entry
918 * @entry: the info entry 947 * @entry: the info entry
@@ -937,11 +966,13 @@ int snd_info_unregister(struct snd_info_entry * entry)
937 return 0; 966 return 0;
938} 967}
939 968
969EXPORT_SYMBOL(snd_info_unregister);
970
940/* 971/*
941 972
942 */ 973 */
943 974
944static struct snd_info_entry *snd_info_version_entry = NULL; 975static struct snd_info_entry *snd_info_version_entry;
945 976
946static void snd_info_version_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) 977static void snd_info_version_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
947{ 978{
@@ -958,7 +989,6 @@ static int __init snd_info_version_init(void)
958 entry = snd_info_create_module_entry(THIS_MODULE, "version", NULL); 989 entry = snd_info_create_module_entry(THIS_MODULE, "version", NULL);
959 if (entry == NULL) 990 if (entry == NULL)
960 return -ENOMEM; 991 return -ENOMEM;
961 entry->c.text.read_size = 256;
962 entry->c.text.read = snd_info_version_read; 992 entry->c.text.read = snd_info_version_read;
963 if (snd_info_register(entry) < 0) { 993 if (snd_info_register(entry) < 0) {
964 snd_info_free_entry(entry); 994 snd_info_free_entry(entry);
diff --git a/sound/core/info_oss.c b/sound/core/info_oss.c
index f9ce854b3d11..bb2c40d0ab66 100644
--- a/sound/core/info_oss.c
+++ b/sound/core/info_oss.c
@@ -64,6 +64,8 @@ int snd_oss_info_register(int dev, int num, char *string)
64 return 0; 64 return 0;
65} 65}
66 66
67EXPORT_SYMBOL(snd_oss_info_register);
68
67extern void snd_card_info_read_oss(struct snd_info_buffer *buffer); 69extern void snd_card_info_read_oss(struct snd_info_buffer *buffer);
68 70
69static int snd_sndstat_show_strings(struct snd_info_buffer *buf, char *id, int dev) 71static int snd_sndstat_show_strings(struct snd_info_buffer *buf, char *id, int dev)
@@ -117,7 +119,6 @@ int snd_info_minor_register(void)
117 119
118 memset(snd_sndstat_strings, 0, sizeof(snd_sndstat_strings)); 120 memset(snd_sndstat_strings, 0, sizeof(snd_sndstat_strings));
119 if ((entry = snd_info_create_module_entry(THIS_MODULE, "sndstat", snd_oss_root)) != NULL) { 121 if ((entry = snd_info_create_module_entry(THIS_MODULE, "sndstat", snd_oss_root)) != NULL) {
120 entry->c.text.read_size = 2048;
121 entry->c.text.read = snd_sndstat_proc_read; 122 entry->c.text.read = snd_sndstat_proc_read;
122 if (snd_info_register(entry) < 0) { 123 if (snd_info_register(entry) < 0) {
123 snd_info_free_entry(entry); 124 snd_info_free_entry(entry);
diff --git a/sound/core/init.c b/sound/core/init.c
index 39ed2e5bb0af..4d9258884e44 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -38,12 +38,15 @@ struct snd_shutdown_f_ops {
38 struct snd_shutdown_f_ops *next; 38 struct snd_shutdown_f_ops *next;
39}; 39};
40 40
41unsigned int snd_cards_lock = 0; /* locked for registering/using */ 41static unsigned int snd_cards_lock; /* locked for registering/using */
42struct snd_card *snd_cards[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = NULL}; 42struct snd_card *snd_cards[SNDRV_CARDS];
43DEFINE_RWLOCK(snd_card_rwlock); 43EXPORT_SYMBOL(snd_cards);
44
45static DEFINE_MUTEX(snd_card_mutex);
44 46
45#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) 47#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
46int (*snd_mixer_oss_notify_callback)(struct snd_card *card, int free_flag); 48int (*snd_mixer_oss_notify_callback)(struct snd_card *card, int free_flag);
49EXPORT_SYMBOL(snd_mixer_oss_notify_callback);
47#endif 50#endif
48 51
49#ifdef CONFIG_PROC_FS 52#ifdef CONFIG_PROC_FS
@@ -66,7 +69,6 @@ static inline int init_info_for_card(struct snd_card *card)
66 snd_printd("unable to create card entry\n"); 69 snd_printd("unable to create card entry\n");
67 return err; 70 return err;
68 } 71 }
69 entry->c.text.read_size = PAGE_SIZE;
70 entry->c.text.read = snd_card_id_read; 72 entry->c.text.read = snd_card_id_read;
71 if (snd_info_register(entry) < 0) { 73 if (snd_info_register(entry) < 0) {
72 snd_info_free_entry(entry); 74 snd_info_free_entry(entry);
@@ -110,7 +112,7 @@ struct snd_card *snd_card_new(int idx, const char *xid,
110 strlcpy(card->id, xid, sizeof(card->id)); 112 strlcpy(card->id, xid, sizeof(card->id));
111 } 113 }
112 err = 0; 114 err = 0;
113 write_lock(&snd_card_rwlock); 115 mutex_lock(&snd_card_mutex);
114 if (idx < 0) { 116 if (idx < 0) {
115 int idx2; 117 int idx2;
116 for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++) 118 for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++)
@@ -128,12 +130,12 @@ struct snd_card *snd_card_new(int idx, const char *xid,
128 else 130 else
129 err = -ENODEV; 131 err = -ENODEV;
130 if (idx < 0 || err < 0) { 132 if (idx < 0 || err < 0) {
131 write_unlock(&snd_card_rwlock); 133 mutex_unlock(&snd_card_mutex);
132 snd_printk(KERN_ERR "cannot find the slot for index %d (range 0-%i)\n", idx, snd_ecards_limit - 1); 134 snd_printk(KERN_ERR "cannot find the slot for index %d (range 0-%i)\n", idx, snd_ecards_limit - 1);
133 goto __error; 135 goto __error;
134 } 136 }
135 snd_cards_lock |= 1 << idx; /* lock it */ 137 snd_cards_lock |= 1 << idx; /* lock it */
136 write_unlock(&snd_card_rwlock); 138 mutex_unlock(&snd_card_mutex);
137 card->number = idx; 139 card->number = idx;
138 card->module = module; 140 card->module = module;
139 INIT_LIST_HEAD(&card->devices); 141 INIT_LIST_HEAD(&card->devices);
@@ -169,6 +171,19 @@ struct snd_card *snd_card_new(int idx, const char *xid,
169 return NULL; 171 return NULL;
170} 172}
171 173
174EXPORT_SYMBOL(snd_card_new);
175
176/* return non-zero if a card is already locked */
177int snd_card_locked(int card)
178{
179 int locked;
180
181 mutex_lock(&snd_card_mutex);
182 locked = snd_cards_lock & (1 << card);
183 mutex_unlock(&snd_card_mutex);
184 return locked;
185}
186
172static loff_t snd_disconnect_llseek(struct file *file, loff_t offset, int orig) 187static loff_t snd_disconnect_llseek(struct file *file, loff_t offset, int orig)
173{ 188{
174 return -ENODEV; 189 return -ENODEV;
@@ -236,9 +251,9 @@ int snd_card_disconnect(struct snd_card *card)
236 spin_unlock(&card->files_lock); 251 spin_unlock(&card->files_lock);
237 252
238 /* phase 1: disable fops (user space) operations for ALSA API */ 253 /* phase 1: disable fops (user space) operations for ALSA API */
239 write_lock(&snd_card_rwlock); 254 mutex_lock(&snd_card_mutex);
240 snd_cards[card->number] = NULL; 255 snd_cards[card->number] = NULL;
241 write_unlock(&snd_card_rwlock); 256 mutex_unlock(&snd_card_mutex);
242 257
243 /* phase 2: replace file->f_op with special dummy operations */ 258 /* phase 2: replace file->f_op with special dummy operations */
244 259
@@ -298,6 +313,8 @@ int snd_card_disconnect(struct snd_card *card)
298 return 0; 313 return 0;
299} 314}
300 315
316EXPORT_SYMBOL(snd_card_disconnect);
317
301/** 318/**
302 * snd_card_free - frees given soundcard structure 319 * snd_card_free - frees given soundcard structure
303 * @card: soundcard structure 320 * @card: soundcard structure
@@ -315,9 +332,9 @@ int snd_card_free(struct snd_card *card)
315 332
316 if (card == NULL) 333 if (card == NULL)
317 return -EINVAL; 334 return -EINVAL;
318 write_lock(&snd_card_rwlock); 335 mutex_lock(&snd_card_mutex);
319 snd_cards[card->number] = NULL; 336 snd_cards[card->number] = NULL;
320 write_unlock(&snd_card_rwlock); 337 mutex_unlock(&snd_card_mutex);
321 338
322#ifdef CONFIG_PM 339#ifdef CONFIG_PM
323 wake_up(&card->power_sleep); 340 wake_up(&card->power_sleep);
@@ -353,13 +370,15 @@ int snd_card_free(struct snd_card *card)
353 card->s_f_ops = s_f_ops->next; 370 card->s_f_ops = s_f_ops->next;
354 kfree(s_f_ops); 371 kfree(s_f_ops);
355 } 372 }
356 write_lock(&snd_card_rwlock); 373 mutex_lock(&snd_card_mutex);
357 snd_cards_lock &= ~(1 << card->number); 374 snd_cards_lock &= ~(1 << card->number);
358 write_unlock(&snd_card_rwlock); 375 mutex_unlock(&snd_card_mutex);
359 kfree(card); 376 kfree(card);
360 return 0; 377 return 0;
361} 378}
362 379
380EXPORT_SYMBOL(snd_card_free);
381
363static void snd_card_free_thread(void * __card) 382static void snd_card_free_thread(void * __card)
364{ 383{
365 struct snd_card *card = __card; 384 struct snd_card *card = __card;
@@ -405,6 +424,8 @@ int snd_card_free_in_thread(struct snd_card *card)
405 return -EFAULT; 424 return -EFAULT;
406} 425}
407 426
427EXPORT_SYMBOL(snd_card_free_in_thread);
428
408static void choose_default_id(struct snd_card *card) 429static void choose_default_id(struct snd_card *card)
409{ 430{
410 int i, len, idx_flag = 0, loops = SNDRV_CARDS; 431 int i, len, idx_flag = 0, loops = SNDRV_CARDS;
@@ -487,16 +508,16 @@ int snd_card_register(struct snd_card *card)
487 snd_assert(card != NULL, return -EINVAL); 508 snd_assert(card != NULL, return -EINVAL);
488 if ((err = snd_device_register_all(card)) < 0) 509 if ((err = snd_device_register_all(card)) < 0)
489 return err; 510 return err;
490 write_lock(&snd_card_rwlock); 511 mutex_lock(&snd_card_mutex);
491 if (snd_cards[card->number]) { 512 if (snd_cards[card->number]) {
492 /* already registered */ 513 /* already registered */
493 write_unlock(&snd_card_rwlock); 514 mutex_unlock(&snd_card_mutex);
494 return 0; 515 return 0;
495 } 516 }
496 if (card->id[0] == '\0') 517 if (card->id[0] == '\0')
497 choose_default_id(card); 518 choose_default_id(card);
498 snd_cards[card->number] = card; 519 snd_cards[card->number] = card;
499 write_unlock(&snd_card_rwlock); 520 mutex_unlock(&snd_card_mutex);
500 init_info_for_card(card); 521 init_info_for_card(card);
501#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) 522#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
502 if (snd_mixer_oss_notify_callback) 523 if (snd_mixer_oss_notify_callback)
@@ -505,8 +526,10 @@ int snd_card_register(struct snd_card *card)
505 return 0; 526 return 0;
506} 527}
507 528
529EXPORT_SYMBOL(snd_card_register);
530
508#ifdef CONFIG_PROC_FS 531#ifdef CONFIG_PROC_FS
509static struct snd_info_entry *snd_card_info_entry = NULL; 532static struct snd_info_entry *snd_card_info_entry;
510 533
511static void snd_card_info_read(struct snd_info_entry *entry, 534static void snd_card_info_read(struct snd_info_entry *entry,
512 struct snd_info_buffer *buffer) 535 struct snd_info_buffer *buffer)
@@ -515,7 +538,7 @@ static void snd_card_info_read(struct snd_info_entry *entry,
515 struct snd_card *card; 538 struct snd_card *card;
516 539
517 for (idx = count = 0; idx < SNDRV_CARDS; idx++) { 540 for (idx = count = 0; idx < SNDRV_CARDS; idx++) {
518 read_lock(&snd_card_rwlock); 541 mutex_lock(&snd_card_mutex);
519 if ((card = snd_cards[idx]) != NULL) { 542 if ((card = snd_cards[idx]) != NULL) {
520 count++; 543 count++;
521 snd_iprintf(buffer, "%2i [%-15s]: %s - %s\n", 544 snd_iprintf(buffer, "%2i [%-15s]: %s - %s\n",
@@ -526,7 +549,7 @@ static void snd_card_info_read(struct snd_info_entry *entry,
526 snd_iprintf(buffer, " %s\n", 549 snd_iprintf(buffer, " %s\n",
527 card->longname); 550 card->longname);
528 } 551 }
529 read_unlock(&snd_card_rwlock); 552 mutex_unlock(&snd_card_mutex);
530 } 553 }
531 if (!count) 554 if (!count)
532 snd_iprintf(buffer, "--- no soundcards ---\n"); 555 snd_iprintf(buffer, "--- no soundcards ---\n");
@@ -540,12 +563,12 @@ void snd_card_info_read_oss(struct snd_info_buffer *buffer)
540 struct snd_card *card; 563 struct snd_card *card;
541 564
542 for (idx = count = 0; idx < SNDRV_CARDS; idx++) { 565 for (idx = count = 0; idx < SNDRV_CARDS; idx++) {
543 read_lock(&snd_card_rwlock); 566 mutex_lock(&snd_card_mutex);
544 if ((card = snd_cards[idx]) != NULL) { 567 if ((card = snd_cards[idx]) != NULL) {
545 count++; 568 count++;
546 snd_iprintf(buffer, "%s\n", card->longname); 569 snd_iprintf(buffer, "%s\n", card->longname);
547 } 570 }
548 read_unlock(&snd_card_rwlock); 571 mutex_unlock(&snd_card_mutex);
549 } 572 }
550 if (!count) { 573 if (!count) {
551 snd_iprintf(buffer, "--- no soundcards ---\n"); 574 snd_iprintf(buffer, "--- no soundcards ---\n");
@@ -563,11 +586,11 @@ static void snd_card_module_info_read(struct snd_info_entry *entry,
563 struct snd_card *card; 586 struct snd_card *card;
564 587
565 for (idx = 0; idx < SNDRV_CARDS; idx++) { 588 for (idx = 0; idx < SNDRV_CARDS; idx++) {
566 read_lock(&snd_card_rwlock); 589 mutex_lock(&snd_card_mutex);
567 if ((card = snd_cards[idx]) != NULL) 590 if ((card = snd_cards[idx]) != NULL)
568 snd_iprintf(buffer, "%2i %s\n", 591 snd_iprintf(buffer, "%2i %s\n",
569 idx, card->module->name); 592 idx, card->module->name);
570 read_unlock(&snd_card_rwlock); 593 mutex_unlock(&snd_card_mutex);
571 } 594 }
572} 595}
573#endif 596#endif
@@ -579,7 +602,6 @@ int __init snd_card_info_init(void)
579 entry = snd_info_create_module_entry(THIS_MODULE, "cards", NULL); 602 entry = snd_info_create_module_entry(THIS_MODULE, "cards", NULL);
580 if (! entry) 603 if (! entry)
581 return -ENOMEM; 604 return -ENOMEM;
582 entry->c.text.read_size = PAGE_SIZE;
583 entry->c.text.read = snd_card_info_read; 605 entry->c.text.read = snd_card_info_read;
584 if (snd_info_register(entry) < 0) { 606 if (snd_info_register(entry) < 0) {
585 snd_info_free_entry(entry); 607 snd_info_free_entry(entry);
@@ -590,7 +612,6 @@ int __init snd_card_info_init(void)
590#ifdef MODULE 612#ifdef MODULE
591 entry = snd_info_create_module_entry(THIS_MODULE, "modules", NULL); 613 entry = snd_info_create_module_entry(THIS_MODULE, "modules", NULL);
592 if (entry) { 614 if (entry) {
593 entry->c.text.read_size = PAGE_SIZE;
594 entry->c.text.read = snd_card_module_info_read; 615 entry->c.text.read = snd_card_module_info_read;
595 if (snd_info_register(entry) < 0) 616 if (snd_info_register(entry) < 0)
596 snd_info_free_entry(entry); 617 snd_info_free_entry(entry);
@@ -644,6 +665,8 @@ int snd_component_add(struct snd_card *card, const char *component)
644 return 0; 665 return 0;
645} 666}
646 667
668EXPORT_SYMBOL(snd_component_add);
669
647/** 670/**
648 * snd_card_file_add - add the file to the file list of the card 671 * snd_card_file_add - add the file to the file list of the card
649 * @card: soundcard structure 672 * @card: soundcard structure
@@ -676,6 +699,8 @@ int snd_card_file_add(struct snd_card *card, struct file *file)
676 return 0; 699 return 0;
677} 700}
678 701
702EXPORT_SYMBOL(snd_card_file_add);
703
679/** 704/**
680 * snd_card_file_remove - remove the file from the file list 705 * snd_card_file_remove - remove the file from the file list
681 * @card: soundcard structure 706 * @card: soundcard structure
@@ -717,6 +742,8 @@ int snd_card_file_remove(struct snd_card *card, struct file *file)
717 return 0; 742 return 0;
718} 743}
719 744
745EXPORT_SYMBOL(snd_card_file_remove);
746
720#ifdef CONFIG_PM 747#ifdef CONFIG_PM
721/** 748/**
722 * snd_power_wait - wait until the power-state is changed. 749 * snd_power_wait - wait until the power-state is changed.
@@ -753,4 +780,5 @@ int snd_power_wait(struct snd_card *card, unsigned int power_state)
753 return result; 780 return result;
754} 781}
755 782
783EXPORT_SYMBOL(snd_power_wait);
756#endif /* CONFIG_PM */ 784#endif /* CONFIG_PM */
diff --git a/sound/core/isadma.c b/sound/core/isadma.c
index 1a378951da5b..d52398727f0a 100644
--- a/sound/core/isadma.c
+++ b/sound/core/isadma.c
@@ -56,6 +56,8 @@ void snd_dma_program(unsigned long dma,
56 release_dma_lock(flags); 56 release_dma_lock(flags);
57} 57}
58 58
59EXPORT_SYMBOL(snd_dma_program);
60
59/** 61/**
60 * snd_dma_disable - stop the ISA DMA transfer 62 * snd_dma_disable - stop the ISA DMA transfer
61 * @dma: the dma number 63 * @dma: the dma number
@@ -72,6 +74,8 @@ void snd_dma_disable(unsigned long dma)
72 release_dma_lock(flags); 74 release_dma_lock(flags);
73} 75}
74 76
77EXPORT_SYMBOL(snd_dma_disable);
78
75/** 79/**
76 * snd_dma_pointer - return the current pointer to DMA transfer buffer in bytes 80 * snd_dma_pointer - return the current pointer to DMA transfer buffer in bytes
77 * @dma: the dma number 81 * @dma: the dma number
@@ -101,3 +105,5 @@ unsigned int snd_dma_pointer(unsigned long dma, unsigned int size)
101 else 105 else
102 return size - result; 106 return size - result;
103} 107}
108
109EXPORT_SYMBOL(snd_dma_pointer);
diff --git a/sound/core/memory.c b/sound/core/memory.c
index 862d62d2e144..fe59850be868 100644
--- a/sound/core/memory.c
+++ b/sound/core/memory.c
@@ -21,6 +21,7 @@
21 */ 21 */
22 22
23#include <linux/config.h> 23#include <linux/config.h>
24#include <linux/module.h>
24#include <asm/io.h> 25#include <asm/io.h>
25#include <asm/uaccess.h> 26#include <asm/uaccess.h>
26 27
@@ -55,6 +56,8 @@ int copy_to_user_fromio(void __user *dst, const volatile void __iomem *src, size
55#endif 56#endif
56} 57}
57 58
59EXPORT_SYMBOL(copy_to_user_fromio);
60
58/** 61/**
59 * copy_from_user_toio - copy data from user-space to mmio-space 62 * copy_from_user_toio - copy data from user-space to mmio-space
60 * @dst: the destination pointer on mmio-space 63 * @dst: the destination pointer on mmio-space
@@ -85,3 +88,5 @@ int copy_from_user_toio(volatile void __iomem *dst, const void __user *src, size
85 return 0; 88 return 0;
86#endif 89#endif
87} 90}
91
92EXPORT_SYMBOL(copy_from_user_toio);
diff --git a/sound/core/misc.c b/sound/core/misc.c
index b53e563c09e6..03fc711f4127 100644
--- a/sound/core/misc.c
+++ b/sound/core/misc.c
@@ -34,6 +34,8 @@ void release_and_free_resource(struct resource *res)
34 } 34 }
35} 35}
36 36
37EXPORT_SYMBOL(release_and_free_resource);
38
37#ifdef CONFIG_SND_VERBOSE_PRINTK 39#ifdef CONFIG_SND_VERBOSE_PRINTK
38void snd_verbose_printk(const char *file, int line, const char *format, ...) 40void snd_verbose_printk(const char *file, int line, const char *format, ...)
39{ 41{
@@ -51,6 +53,8 @@ void snd_verbose_printk(const char *file, int line, const char *format, ...)
51 vprintk(format, args); 53 vprintk(format, args);
52 va_end(args); 54 va_end(args);
53} 55}
56
57EXPORT_SYMBOL(snd_verbose_printk);
54#endif 58#endif
55 59
56#if defined(CONFIG_SND_DEBUG) && defined(CONFIG_SND_VERBOSE_PRINTK) 60#if defined(CONFIG_SND_DEBUG) && defined(CONFIG_SND_VERBOSE_PRINTK)
@@ -71,4 +75,6 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...)
71 va_end(args); 75 va_end(args);
72 76
73} 77}
78
79EXPORT_SYMBOL(snd_verbose_printd);
74#endif 80#endif
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index 9c68bc3f97aa..71b5080fa66d 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -1182,9 +1182,7 @@ static void snd_mixer_oss_proc_init(struct snd_mixer_oss *mixer)
1182 return; 1182 return;
1183 entry->content = SNDRV_INFO_CONTENT_TEXT; 1183 entry->content = SNDRV_INFO_CONTENT_TEXT;
1184 entry->mode = S_IFREG | S_IRUGO | S_IWUSR; 1184 entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
1185 entry->c.text.read_size = 8192;
1186 entry->c.text.read = snd_mixer_oss_proc_read; 1185 entry->c.text.read = snd_mixer_oss_proc_read;
1187 entry->c.text.write_size = 8192;
1188 entry->c.text.write = snd_mixer_oss_proc_write; 1186 entry->c.text.write = snd_mixer_oss_proc_write;
1189 entry->private_data = mixer; 1187 entry->private_data = mixer;
1190 if (snd_info_register(entry) < 0) { 1188 if (snd_info_register(entry) < 0) {
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index ac990bf0b48f..f5ff4f4a16ee 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -45,7 +45,7 @@
45 45
46#define OSS_ALSAEMULVER _SIOR ('M', 249, int) 46#define OSS_ALSAEMULVER _SIOR ('M', 249, int)
47 47
48static int dsp_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 0}; 48static int dsp_map[SNDRV_CARDS];
49static int adsp_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1}; 49static int adsp_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1};
50static int nonblock_open = 1; 50static int nonblock_open = 1;
51 51
@@ -78,6 +78,487 @@ static inline void snd_leave_user(mm_segment_t fs)
78 set_fs(fs); 78 set_fs(fs);
79} 79}
80 80
81/*
82 * helper functions to process hw_params
83 */
84static int snd_interval_refine_min(struct snd_interval *i, unsigned int min, int openmin)
85{
86 int changed = 0;
87 if (i->min < min) {
88 i->min = min;
89 i->openmin = openmin;
90 changed = 1;
91 } else if (i->min == min && !i->openmin && openmin) {
92 i->openmin = 1;
93 changed = 1;
94 }
95 if (i->integer) {
96 if (i->openmin) {
97 i->min++;
98 i->openmin = 0;
99 }
100 }
101 if (snd_interval_checkempty(i)) {
102 snd_interval_none(i);
103 return -EINVAL;
104 }
105 return changed;
106}
107
108static int snd_interval_refine_max(struct snd_interval *i, unsigned int max, int openmax)
109{
110 int changed = 0;
111 if (i->max > max) {
112 i->max = max;
113 i->openmax = openmax;
114 changed = 1;
115 } else if (i->max == max && !i->openmax && openmax) {
116 i->openmax = 1;
117 changed = 1;
118 }
119 if (i->integer) {
120 if (i->openmax) {
121 i->max--;
122 i->openmax = 0;
123 }
124 }
125 if (snd_interval_checkempty(i)) {
126 snd_interval_none(i);
127 return -EINVAL;
128 }
129 return changed;
130}
131
132static int snd_interval_refine_set(struct snd_interval *i, unsigned int val)
133{
134 struct snd_interval t;
135 t.empty = 0;
136 t.min = t.max = val;
137 t.openmin = t.openmax = 0;
138 t.integer = 1;
139 return snd_interval_refine(i, &t);
140}
141
142/**
143 * snd_pcm_hw_param_value_min
144 * @params: the hw_params instance
145 * @var: parameter to retrieve
146 * @dir: pointer to the direction (-1,0,1) or NULL
147 *
148 * Return the minimum value for field PAR.
149 */
150static unsigned int
151snd_pcm_hw_param_value_min(const struct snd_pcm_hw_params *params,
152 snd_pcm_hw_param_t var, int *dir)
153{
154 if (hw_is_mask(var)) {
155 if (dir)
156 *dir = 0;
157 return snd_mask_min(hw_param_mask_c(params, var));
158 }
159 if (hw_is_interval(var)) {
160 const struct snd_interval *i = hw_param_interval_c(params, var);
161 if (dir)
162 *dir = i->openmin;
163 return snd_interval_min(i);
164 }
165 return -EINVAL;
166}
167
168/**
169 * snd_pcm_hw_param_value_max
170 * @params: the hw_params instance
171 * @var: parameter to retrieve
172 * @dir: pointer to the direction (-1,0,1) or NULL
173 *
174 * Return the maximum value for field PAR.
175 */
176static unsigned int
177snd_pcm_hw_param_value_max(const struct snd_pcm_hw_params *params,
178 snd_pcm_hw_param_t var, int *dir)
179{
180 if (hw_is_mask(var)) {
181 if (dir)
182 *dir = 0;
183 return snd_mask_max(hw_param_mask_c(params, var));
184 }
185 if (hw_is_interval(var)) {
186 const struct snd_interval *i = hw_param_interval_c(params, var);
187 if (dir)
188 *dir = - (int) i->openmax;
189 return snd_interval_max(i);
190 }
191 return -EINVAL;
192}
193
194static int _snd_pcm_hw_param_mask(struct snd_pcm_hw_params *params,
195 snd_pcm_hw_param_t var,
196 const struct snd_mask *val)
197{
198 int changed;
199 changed = snd_mask_refine(hw_param_mask(params, var), val);
200 if (changed) {
201 params->cmask |= 1 << var;
202 params->rmask |= 1 << var;
203 }
204 return changed;
205}
206
207static int snd_pcm_hw_param_mask(struct snd_pcm_substream *pcm,
208 struct snd_pcm_hw_params *params,
209 snd_pcm_hw_param_t var,
210 const struct snd_mask *val)
211{
212 int changed = _snd_pcm_hw_param_mask(params, var, val);
213 if (changed < 0)
214 return changed;
215 if (params->rmask) {
216 int err = snd_pcm_hw_refine(pcm, params);
217 if (err < 0)
218 return err;
219 }
220 return 0;
221}
222
223static int _snd_pcm_hw_param_min(struct snd_pcm_hw_params *params,
224 snd_pcm_hw_param_t var, unsigned int val,
225 int dir)
226{
227 int changed;
228 int open = 0;
229 if (dir) {
230 if (dir > 0) {
231 open = 1;
232 } else if (dir < 0) {
233 if (val > 0) {
234 open = 1;
235 val--;
236 }
237 }
238 }
239 if (hw_is_mask(var))
240 changed = snd_mask_refine_min(hw_param_mask(params, var),
241 val + !!open);
242 else if (hw_is_interval(var))
243 changed = snd_interval_refine_min(hw_param_interval(params, var),
244 val, open);
245 else
246 return -EINVAL;
247 if (changed) {
248 params->cmask |= 1 << var;
249 params->rmask |= 1 << var;
250 }
251 return changed;
252}
253
254/**
255 * snd_pcm_hw_param_min
256 * @pcm: PCM instance
257 * @params: the hw_params instance
258 * @var: parameter to retrieve
259 * @val: minimal value
260 * @dir: pointer to the direction (-1,0,1) or NULL
261 *
262 * Inside configuration space defined by PARAMS remove from PAR all
263 * values < VAL. Reduce configuration space accordingly.
264 * Return new minimum or -EINVAL if the configuration space is empty
265 */
266static int snd_pcm_hw_param_min(struct snd_pcm_substream *pcm,
267 struct snd_pcm_hw_params *params,
268 snd_pcm_hw_param_t var, unsigned int val,
269 int *dir)
270{
271 int changed = _snd_pcm_hw_param_min(params, var, val, dir ? *dir : 0);
272 if (changed < 0)
273 return changed;
274 if (params->rmask) {
275 int err = snd_pcm_hw_refine(pcm, params);
276 if (err < 0)
277 return err;
278 }
279 return snd_pcm_hw_param_value_min(params, var, dir);
280}
281
282static int _snd_pcm_hw_param_max(struct snd_pcm_hw_params *params,
283 snd_pcm_hw_param_t var, unsigned int val,
284 int dir)
285{
286 int changed;
287 int open = 0;
288 if (dir) {
289 if (dir < 0) {
290 open = 1;
291 } else if (dir > 0) {
292 open = 1;
293 val++;
294 }
295 }
296 if (hw_is_mask(var)) {
297 if (val == 0 && open) {
298 snd_mask_none(hw_param_mask(params, var));
299 changed = -EINVAL;
300 } else
301 changed = snd_mask_refine_max(hw_param_mask(params, var),
302 val - !!open);
303 } else if (hw_is_interval(var))
304 changed = snd_interval_refine_max(hw_param_interval(params, var),
305 val, open);
306 else
307 return -EINVAL;
308 if (changed) {
309 params->cmask |= 1 << var;
310 params->rmask |= 1 << var;
311 }
312 return changed;
313}
314
315/**
316 * snd_pcm_hw_param_max
317 * @pcm: PCM instance
318 * @params: the hw_params instance
319 * @var: parameter to retrieve
320 * @val: maximal value
321 * @dir: pointer to the direction (-1,0,1) or NULL
322 *
323 * Inside configuration space defined by PARAMS remove from PAR all
324 * values >= VAL + 1. Reduce configuration space accordingly.
325 * Return new maximum or -EINVAL if the configuration space is empty
326 */
327static int snd_pcm_hw_param_max(struct snd_pcm_substream *pcm,
328 struct snd_pcm_hw_params *params,
329 snd_pcm_hw_param_t var, unsigned int val,
330 int *dir)
331{
332 int changed = _snd_pcm_hw_param_max(params, var, val, dir ? *dir : 0);
333 if (changed < 0)
334 return changed;
335 if (params->rmask) {
336 int err = snd_pcm_hw_refine(pcm, params);
337 if (err < 0)
338 return err;
339 }
340 return snd_pcm_hw_param_value_max(params, var, dir);
341}
342
343static int boundary_sub(int a, int adir,
344 int b, int bdir,
345 int *c, int *cdir)
346{
347 adir = adir < 0 ? -1 : (adir > 0 ? 1 : 0);
348 bdir = bdir < 0 ? -1 : (bdir > 0 ? 1 : 0);
349 *c = a - b;
350 *cdir = adir - bdir;
351 if (*cdir == -2) {
352 (*c)--;
353 } else if (*cdir == 2) {
354 (*c)++;
355 }
356 return 0;
357}
358
359static int boundary_lt(unsigned int a, int adir,
360 unsigned int b, int bdir)
361{
362 if (adir < 0) {
363 a--;
364 adir = 1;
365 } else if (adir > 0)
366 adir = 1;
367 if (bdir < 0) {
368 b--;
369 bdir = 1;
370 } else if (bdir > 0)
371 bdir = 1;
372 return a < b || (a == b && adir < bdir);
373}
374
375/* Return 1 if min is nearer to best than max */
376static int boundary_nearer(int min, int mindir,
377 int best, int bestdir,
378 int max, int maxdir)
379{
380 int dmin, dmindir;
381 int dmax, dmaxdir;
382 boundary_sub(best, bestdir, min, mindir, &dmin, &dmindir);
383 boundary_sub(max, maxdir, best, bestdir, &dmax, &dmaxdir);
384 return boundary_lt(dmin, dmindir, dmax, dmaxdir);
385}
386
387/**
388 * snd_pcm_hw_param_near
389 * @pcm: PCM instance
390 * @params: the hw_params instance
391 * @var: parameter to retrieve
392 * @best: value to set
393 * @dir: pointer to the direction (-1,0,1) or NULL
394 *
395 * Inside configuration space defined by PARAMS set PAR to the available value
396 * nearest to VAL. Reduce configuration space accordingly.
397 * This function cannot be called for SNDRV_PCM_HW_PARAM_ACCESS,
398 * SNDRV_PCM_HW_PARAM_FORMAT, SNDRV_PCM_HW_PARAM_SUBFORMAT.
399 * Return the value found.
400 */
401static int snd_pcm_hw_param_near(struct snd_pcm_substream *pcm,
402 struct snd_pcm_hw_params *params,
403 snd_pcm_hw_param_t var, unsigned int best,
404 int *dir)
405{
406 struct snd_pcm_hw_params *save = NULL;
407 int v;
408 unsigned int saved_min;
409 int last = 0;
410 int min, max;
411 int mindir, maxdir;
412 int valdir = dir ? *dir : 0;
413 /* FIXME */
414 if (best > INT_MAX)
415 best = INT_MAX;
416 min = max = best;
417 mindir = maxdir = valdir;
418 if (maxdir > 0)
419 maxdir = 0;
420 else if (maxdir == 0)
421 maxdir = -1;
422 else {
423 maxdir = 1;
424 max--;
425 }
426 save = kmalloc(sizeof(*save), GFP_KERNEL);
427 if (save == NULL)
428 return -ENOMEM;
429 *save = *params;
430 saved_min = min;
431 min = snd_pcm_hw_param_min(pcm, params, var, min, &mindir);
432 if (min >= 0) {
433 struct snd_pcm_hw_params *params1;
434 if (max < 0)
435 goto _end;
436 if ((unsigned int)min == saved_min && mindir == valdir)
437 goto _end;
438 params1 = kmalloc(sizeof(*params1), GFP_KERNEL);
439 if (params1 == NULL) {
440 kfree(save);
441 return -ENOMEM;
442 }
443 *params1 = *save;
444 max = snd_pcm_hw_param_max(pcm, params1, var, max, &maxdir);
445 if (max < 0) {
446 kfree(params1);
447 goto _end;
448 }
449 if (boundary_nearer(max, maxdir, best, valdir, min, mindir)) {
450 *params = *params1;
451 last = 1;
452 }
453 kfree(params1);
454 } else {
455 *params = *save;
456 max = snd_pcm_hw_param_max(pcm, params, var, max, &maxdir);
457 snd_assert(max >= 0, return -EINVAL);
458 last = 1;
459 }
460 _end:
461 kfree(save);
462 if (last)
463 v = snd_pcm_hw_param_last(pcm, params, var, dir);
464 else
465 v = snd_pcm_hw_param_first(pcm, params, var, dir);
466 snd_assert(v >= 0, return -EINVAL);
467 return v;
468}
469
470static int _snd_pcm_hw_param_set(struct snd_pcm_hw_params *params,
471 snd_pcm_hw_param_t var, unsigned int val,
472 int dir)
473{
474 int changed;
475 if (hw_is_mask(var)) {
476 struct snd_mask *m = hw_param_mask(params, var);
477 if (val == 0 && dir < 0) {
478 changed = -EINVAL;
479 snd_mask_none(m);
480 } else {
481 if (dir > 0)
482 val++;
483 else if (dir < 0)
484 val--;
485 changed = snd_mask_refine_set(hw_param_mask(params, var), val);
486 }
487 } else if (hw_is_interval(var)) {
488 struct snd_interval *i = hw_param_interval(params, var);
489 if (val == 0 && dir < 0) {
490 changed = -EINVAL;
491 snd_interval_none(i);
492 } else if (dir == 0)
493 changed = snd_interval_refine_set(i, val);
494 else {
495 struct snd_interval t;
496 t.openmin = 1;
497 t.openmax = 1;
498 t.empty = 0;
499 t.integer = 0;
500 if (dir < 0) {
501 t.min = val - 1;
502 t.max = val;
503 } else {
504 t.min = val;
505 t.max = val+1;
506 }
507 changed = snd_interval_refine(i, &t);
508 }
509 } else
510 return -EINVAL;
511 if (changed) {
512 params->cmask |= 1 << var;
513 params->rmask |= 1 << var;
514 }
515 return changed;
516}
517
518/**
519 * snd_pcm_hw_param_set
520 * @pcm: PCM instance
521 * @params: the hw_params instance
522 * @var: parameter to retrieve
523 * @val: value to set
524 * @dir: pointer to the direction (-1,0,1) or NULL
525 *
526 * Inside configuration space defined by PARAMS remove from PAR all
527 * values != VAL. Reduce configuration space accordingly.
528 * Return VAL or -EINVAL if the configuration space is empty
529 */
530static int snd_pcm_hw_param_set(struct snd_pcm_substream *pcm,
531 struct snd_pcm_hw_params *params,
532 snd_pcm_hw_param_t var, unsigned int val,
533 int dir)
534{
535 int changed = _snd_pcm_hw_param_set(params, var, val, dir);
536 if (changed < 0)
537 return changed;
538 if (params->rmask) {
539 int err = snd_pcm_hw_refine(pcm, params);
540 if (err < 0)
541 return err;
542 }
543 return snd_pcm_hw_param_value(params, var, NULL);
544}
545
546static int _snd_pcm_hw_param_setinteger(struct snd_pcm_hw_params *params,
547 snd_pcm_hw_param_t var)
548{
549 int changed;
550 changed = snd_interval_setinteger(hw_param_interval(params, var));
551 if (changed) {
552 params->cmask |= 1 << var;
553 params->rmask |= 1 << var;
554 }
555 return changed;
556}
557
558/*
559 * plugin
560 */
561
81#ifdef CONFIG_SND_PCM_OSS_PLUGINS 562#ifdef CONFIG_SND_PCM_OSS_PLUGINS
82static int snd_pcm_oss_plugin_clear(struct snd_pcm_substream *substream) 563static int snd_pcm_oss_plugin_clear(struct snd_pcm_substream *substream)
83{ 564{
@@ -203,7 +684,7 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream,
203 oss_buffer_size = snd_pcm_plug_client_size(substream, 684 oss_buffer_size = snd_pcm_plug_client_size(substream,
204 snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, NULL)) * oss_frame_size; 685 snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, NULL)) * oss_frame_size;
205 oss_buffer_size = 1 << ld2(oss_buffer_size); 686 oss_buffer_size = 1 << ld2(oss_buffer_size);
206 if (atomic_read(&runtime->mmap_count)) { 687 if (atomic_read(&substream->mmap_count)) {
207 if (oss_buffer_size > runtime->oss.mmap_bytes) 688 if (oss_buffer_size > runtime->oss.mmap_bytes)
208 oss_buffer_size = runtime->oss.mmap_bytes; 689 oss_buffer_size = runtime->oss.mmap_bytes;
209 } 690 }
@@ -338,7 +819,7 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
338 goto failure; 819 goto failure;
339 } 820 }
340 821
341 if (atomic_read(&runtime->mmap_count)) 822 if (atomic_read(&substream->mmap_count))
342 direct = 1; 823 direct = 1;
343 else 824 else
344 direct = substream->oss.setup.direct; 825 direct = substream->oss.setup.direct;
@@ -347,7 +828,7 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
347 _snd_pcm_hw_param_setinteger(sparams, SNDRV_PCM_HW_PARAM_PERIODS); 828 _snd_pcm_hw_param_setinteger(sparams, SNDRV_PCM_HW_PARAM_PERIODS);
348 _snd_pcm_hw_param_min(sparams, SNDRV_PCM_HW_PARAM_PERIODS, 2, 0); 829 _snd_pcm_hw_param_min(sparams, SNDRV_PCM_HW_PARAM_PERIODS, 2, 0);
349 snd_mask_none(&mask); 830 snd_mask_none(&mask);
350 if (atomic_read(&runtime->mmap_count)) 831 if (atomic_read(&substream->mmap_count))
351 snd_mask_set(&mask, SNDRV_PCM_ACCESS_MMAP_INTERLEAVED); 832 snd_mask_set(&mask, SNDRV_PCM_ACCESS_MMAP_INTERLEAVED);
352 else { 833 else {
353 snd_mask_set(&mask, SNDRV_PCM_ACCESS_RW_INTERLEAVED); 834 snd_mask_set(&mask, SNDRV_PCM_ACCESS_RW_INTERLEAVED);
@@ -466,7 +947,8 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
466 } else { 947 } else {
467 sw_params->start_threshold = runtime->boundary; 948 sw_params->start_threshold = runtime->boundary;
468 } 949 }
469 if (atomic_read(&runtime->mmap_count) || substream->stream == SNDRV_PCM_STREAM_CAPTURE) 950 if (atomic_read(&substream->mmap_count) ||
951 substream->stream == SNDRV_PCM_STREAM_CAPTURE)
470 sw_params->stop_threshold = runtime->boundary; 952 sw_params->stop_threshold = runtime->boundary;
471 else 953 else
472 sw_params->stop_threshold = runtime->buffer_size; 954 sw_params->stop_threshold = runtime->buffer_size;
@@ -476,7 +958,7 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
476 sw_params->avail_min = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 958 sw_params->avail_min = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
477 1 : runtime->period_size; 959 1 : runtime->period_size;
478 sw_params->xfer_align = 1; 960 sw_params->xfer_align = 1;
479 if (atomic_read(&runtime->mmap_count) || 961 if (atomic_read(&substream->mmap_count) ||
480 substream->oss.setup.nosilence) { 962 substream->oss.setup.nosilence) {
481 sw_params->silence_threshold = 0; 963 sw_params->silence_threshold = 0;
482 sw_params->silence_size = 0; 964 sw_params->silence_size = 0;
@@ -820,7 +1302,7 @@ static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const cha
820 ssize_t tmp; 1302 ssize_t tmp;
821 struct snd_pcm_runtime *runtime = substream->runtime; 1303 struct snd_pcm_runtime *runtime = substream->runtime;
822 1304
823 if (atomic_read(&runtime->mmap_count)) 1305 if (atomic_read(&substream->mmap_count))
824 return -ENXIO; 1306 return -ENXIO;
825 1307
826 if ((tmp = snd_pcm_oss_make_ready(substream)) < 0) 1308 if ((tmp = snd_pcm_oss_make_ready(substream)) < 0)
@@ -850,7 +1332,7 @@ static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const cha
850 if (runtime->oss.period_ptr == 0 || 1332 if (runtime->oss.period_ptr == 0 ||
851 runtime->oss.period_ptr == runtime->oss.buffer_used) 1333 runtime->oss.period_ptr == runtime->oss.buffer_used)
852 runtime->oss.buffer_used = 0; 1334 runtime->oss.buffer_used = 0;
853 else if ((substream->ffile->f_flags & O_NONBLOCK) != 0) 1335 else if ((substream->f_flags & O_NONBLOCK) != 0)
854 return xfer > 0 ? xfer : -EAGAIN; 1336 return xfer > 0 ? xfer : -EAGAIN;
855 } 1337 }
856 } else { 1338 } else {
@@ -863,7 +1345,7 @@ static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const cha
863 buf += tmp; 1345 buf += tmp;
864 bytes -= tmp; 1346 bytes -= tmp;
865 xfer += tmp; 1347 xfer += tmp;
866 if ((substream->ffile->f_flags & O_NONBLOCK) != 0 && 1348 if ((substream->f_flags & O_NONBLOCK) != 0 &&
867 tmp != runtime->oss.period_bytes) 1349 tmp != runtime->oss.period_bytes)
868 break; 1350 break;
869 } 1351 }
@@ -910,7 +1392,7 @@ static ssize_t snd_pcm_oss_read1(struct snd_pcm_substream *substream, char __use
910 ssize_t tmp; 1392 ssize_t tmp;
911 struct snd_pcm_runtime *runtime = substream->runtime; 1393 struct snd_pcm_runtime *runtime = substream->runtime;
912 1394
913 if (atomic_read(&runtime->mmap_count)) 1395 if (atomic_read(&substream->mmap_count))
914 return -ENXIO; 1396 return -ENXIO;
915 1397
916 if ((tmp = snd_pcm_oss_make_ready(substream)) < 0) 1398 if ((tmp = snd_pcm_oss_make_ready(substream)) < 0)
@@ -1040,7 +1522,7 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
1040 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; 1522 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
1041 if (substream != NULL) { 1523 if (substream != NULL) {
1042 runtime = substream->runtime; 1524 runtime = substream->runtime;
1043 if (atomic_read(&runtime->mmap_count)) 1525 if (atomic_read(&substream->mmap_count))
1044 goto __direct; 1526 goto __direct;
1045 if ((err = snd_pcm_oss_make_ready(substream)) < 0) 1527 if ((err = snd_pcm_oss_make_ready(substream)) < 0)
1046 return err; 1528 return err;
@@ -1101,10 +1583,10 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
1101 * finish sync: drain the buffer 1583 * finish sync: drain the buffer
1102 */ 1584 */
1103 __direct: 1585 __direct:
1104 saved_f_flags = substream->ffile->f_flags; 1586 saved_f_flags = substream->f_flags;
1105 substream->ffile->f_flags &= ~O_NONBLOCK; 1587 substream->f_flags &= ~O_NONBLOCK;
1106 err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL); 1588 err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);
1107 substream->ffile->f_flags = saved_f_flags; 1589 substream->f_flags = saved_f_flags;
1108 if (err < 0) 1590 if (err < 0)
1109 return err; 1591 return err;
1110 runtime->oss.prepare = 1; 1592 runtime->oss.prepare = 1;
@@ -1209,7 +1691,7 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file)
1209 1691
1210 if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) 1692 if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
1211 return err; 1693 return err;
1212 if (atomic_read(&substream->runtime->mmap_count)) 1694 if (atomic_read(&substream->mmap_count))
1213 direct = 1; 1695 direct = 1;
1214 else 1696 else
1215 direct = substream->oss.setup.direct; 1697 direct = substream->oss.setup.direct;
@@ -1419,7 +1901,7 @@ static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int tr
1419 if (trigger & PCM_ENABLE_OUTPUT) { 1901 if (trigger & PCM_ENABLE_OUTPUT) {
1420 if (runtime->oss.trigger) 1902 if (runtime->oss.trigger)
1421 goto _skip1; 1903 goto _skip1;
1422 if (atomic_read(&psubstream->runtime->mmap_count)) 1904 if (atomic_read(&psubstream->mmap_count))
1423 snd_pcm_oss_simulate_fill(psubstream, runtime->hw_ptr_interrupt); 1905 snd_pcm_oss_simulate_fill(psubstream, runtime->hw_ptr_interrupt);
1424 runtime->oss.trigger = 1; 1906 runtime->oss.trigger = 1;
1425 runtime->start_threshold = 1; 1907 runtime->start_threshold = 1;
@@ -1537,7 +2019,7 @@ static int snd_pcm_oss_get_ptr(struct snd_pcm_oss_file *pcm_oss_file, int stream
1537 if (err < 0) 2019 if (err < 0)
1538 return err; 2020 return err;
1539 info.ptr = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr % runtime->buffer_size); 2021 info.ptr = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr % runtime->buffer_size);
1540 if (atomic_read(&runtime->mmap_count)) { 2022 if (atomic_read(&substream->mmap_count)) {
1541 snd_pcm_sframes_t n; 2023 snd_pcm_sframes_t n;
1542 n = (delay = runtime->hw_ptr_interrupt) - runtime->oss.prev_hw_ptr_interrupt; 2024 n = (delay = runtime->hw_ptr_interrupt) - runtime->oss.prev_hw_ptr_interrupt;
1543 if (n < 0) 2025 if (n < 0)
@@ -1683,9 +2165,9 @@ static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream,
1683 substream->oss.oss = 1; 2165 substream->oss.oss = 1;
1684 substream->oss.setup = *setup; 2166 substream->oss.setup = *setup;
1685 if (setup->nonblock) 2167 if (setup->nonblock)
1686 substream->ffile->f_flags |= O_NONBLOCK; 2168 substream->f_flags |= O_NONBLOCK;
1687 else if (setup->block) 2169 else if (setup->block)
1688 substream->ffile->f_flags &= ~O_NONBLOCK; 2170 substream->f_flags &= ~O_NONBLOCK;
1689 runtime = substream->runtime; 2171 runtime = substream->runtime;
1690 runtime->oss.params = 1; 2172 runtime->oss.params = 1;
1691 runtime->oss.trigger = 1; 2173 runtime->oss.trigger = 1;
@@ -1742,6 +2224,7 @@ static int snd_pcm_oss_open_file(struct file *file,
1742 (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX)) 2224 (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX))
1743 f_mode = FMODE_WRITE; 2225 f_mode = FMODE_WRITE;
1744 2226
2227 file->f_flags &= ~O_APPEND;
1745 for (idx = 0; idx < 2; idx++) { 2228 for (idx = 0; idx < 2; idx++) {
1746 if (setup[idx].disable) 2229 if (setup[idx].disable)
1747 continue; 2230 continue;
@@ -2059,6 +2542,7 @@ static ssize_t snd_pcm_oss_read(struct file *file, char __user *buf, size_t coun
2059 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; 2542 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
2060 if (substream == NULL) 2543 if (substream == NULL)
2061 return -ENXIO; 2544 return -ENXIO;
2545 substream->f_flags = file->f_flags & O_NONBLOCK;
2062#ifndef OSS_DEBUG 2546#ifndef OSS_DEBUG
2063 return snd_pcm_oss_read1(substream, buf, count); 2547 return snd_pcm_oss_read1(substream, buf, count);
2064#else 2548#else
@@ -2080,6 +2564,7 @@ static ssize_t snd_pcm_oss_write(struct file *file, const char __user *buf, size
2080 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; 2564 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
2081 if (substream == NULL) 2565 if (substream == NULL)
2082 return -ENXIO; 2566 return -ENXIO;
2567 substream->f_flags = file->f_flags & O_NONBLOCK;
2083 result = snd_pcm_oss_write1(substream, buf, count); 2568 result = snd_pcm_oss_write1(substream, buf, count);
2084#ifdef OSS_DEBUG 2569#ifdef OSS_DEBUG
2085 printk("pcm_oss: write %li bytes (wrote %li bytes)\n", (long)count, (long)result); 2570 printk("pcm_oss: write %li bytes (wrote %li bytes)\n", (long)count, (long)result);
@@ -2090,7 +2575,7 @@ static ssize_t snd_pcm_oss_write(struct file *file, const char __user *buf, size
2090static int snd_pcm_oss_playback_ready(struct snd_pcm_substream *substream) 2575static int snd_pcm_oss_playback_ready(struct snd_pcm_substream *substream)
2091{ 2576{
2092 struct snd_pcm_runtime *runtime = substream->runtime; 2577 struct snd_pcm_runtime *runtime = substream->runtime;
2093 if (atomic_read(&runtime->mmap_count)) 2578 if (atomic_read(&substream->mmap_count))
2094 return runtime->oss.prev_hw_ptr_interrupt != runtime->hw_ptr_interrupt; 2579 return runtime->oss.prev_hw_ptr_interrupt != runtime->hw_ptr_interrupt;
2095 else 2580 else
2096 return snd_pcm_playback_avail(runtime) >= runtime->oss.period_frames; 2581 return snd_pcm_playback_avail(runtime) >= runtime->oss.period_frames;
@@ -2099,7 +2584,7 @@ static int snd_pcm_oss_playback_ready(struct snd_pcm_substream *substream)
2099static int snd_pcm_oss_capture_ready(struct snd_pcm_substream *substream) 2584static int snd_pcm_oss_capture_ready(struct snd_pcm_substream *substream)
2100{ 2585{
2101 struct snd_pcm_runtime *runtime = substream->runtime; 2586 struct snd_pcm_runtime *runtime = substream->runtime;
2102 if (atomic_read(&runtime->mmap_count)) 2587 if (atomic_read(&substream->mmap_count))
2103 return runtime->oss.prev_hw_ptr_interrupt != runtime->hw_ptr_interrupt; 2588 return runtime->oss.prev_hw_ptr_interrupt != runtime->hw_ptr_interrupt;
2104 else 2589 else
2105 return snd_pcm_capture_avail(runtime) >= runtime->oss.period_frames; 2590 return snd_pcm_capture_avail(runtime) >= runtime->oss.period_frames;
@@ -2342,9 +2827,7 @@ static void snd_pcm_oss_proc_init(struct snd_pcm *pcm)
2342 if ((entry = snd_info_create_card_entry(pcm->card, "oss", pstr->proc_root)) != NULL) { 2827 if ((entry = snd_info_create_card_entry(pcm->card, "oss", pstr->proc_root)) != NULL) {
2343 entry->content = SNDRV_INFO_CONTENT_TEXT; 2828 entry->content = SNDRV_INFO_CONTENT_TEXT;
2344 entry->mode = S_IFREG | S_IRUGO | S_IWUSR; 2829 entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
2345 entry->c.text.read_size = 8192;
2346 entry->c.text.read = snd_pcm_oss_proc_read; 2830 entry->c.text.read = snd_pcm_oss_proc_read;
2347 entry->c.text.write_size = 8192;
2348 entry->c.text.write = snd_pcm_oss_proc_write; 2831 entry->c.text.write = snd_pcm_oss_proc_write;
2349 entry->private_data = pstr; 2832 entry->private_data = pstr;
2350 if (snd_info_register(entry) < 0) { 2833 if (snd_info_register(entry) < 0) {
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 84b00038236d..7581edd7b9ff 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -351,10 +351,8 @@ static void snd_pcm_substream_proc_hw_params_read(struct snd_info_entry *entry,
351 snd_iprintf(buffer, "closed\n"); 351 snd_iprintf(buffer, "closed\n");
352 return; 352 return;
353 } 353 }
354 snd_pcm_stream_lock_irq(substream);
355 if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { 354 if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
356 snd_iprintf(buffer, "no setup\n"); 355 snd_iprintf(buffer, "no setup\n");
357 snd_pcm_stream_unlock_irq(substream);
358 return; 356 return;
359 } 357 }
360 snd_iprintf(buffer, "access: %s\n", snd_pcm_access_name(runtime->access)); 358 snd_iprintf(buffer, "access: %s\n", snd_pcm_access_name(runtime->access));
@@ -375,7 +373,6 @@ static void snd_pcm_substream_proc_hw_params_read(struct snd_info_entry *entry,
375 snd_iprintf(buffer, "OSS period frames: %lu\n", (unsigned long)runtime->oss.period_frames); 373 snd_iprintf(buffer, "OSS period frames: %lu\n", (unsigned long)runtime->oss.period_frames);
376 } 374 }
377#endif 375#endif
378 snd_pcm_stream_unlock_irq(substream);
379} 376}
380 377
381static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry, 378static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry,
@@ -387,10 +384,8 @@ static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry,
387 snd_iprintf(buffer, "closed\n"); 384 snd_iprintf(buffer, "closed\n");
388 return; 385 return;
389 } 386 }
390 snd_pcm_stream_lock_irq(substream);
391 if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { 387 if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
392 snd_iprintf(buffer, "no setup\n"); 388 snd_iprintf(buffer, "no setup\n");
393 snd_pcm_stream_unlock_irq(substream);
394 return; 389 return;
395 } 390 }
396 snd_iprintf(buffer, "tstamp_mode: %s\n", snd_pcm_tstamp_mode_name(runtime->tstamp_mode)); 391 snd_iprintf(buffer, "tstamp_mode: %s\n", snd_pcm_tstamp_mode_name(runtime->tstamp_mode));
@@ -403,7 +398,6 @@ static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry,
403 snd_iprintf(buffer, "silence_threshold: %lu\n", runtime->silence_threshold); 398 snd_iprintf(buffer, "silence_threshold: %lu\n", runtime->silence_threshold);
404 snd_iprintf(buffer, "silence_size: %lu\n", runtime->silence_size); 399 snd_iprintf(buffer, "silence_size: %lu\n", runtime->silence_size);
405 snd_iprintf(buffer, "boundary: %lu\n", runtime->boundary); 400 snd_iprintf(buffer, "boundary: %lu\n", runtime->boundary);
406 snd_pcm_stream_unlock_irq(substream);
407} 401}
408 402
409static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry, 403static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry,
@@ -472,7 +466,7 @@ static int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr)
472 pstr->proc_root = entry; 466 pstr->proc_root = entry;
473 467
474 if ((entry = snd_info_create_card_entry(pcm->card, "info", pstr->proc_root)) != NULL) { 468 if ((entry = snd_info_create_card_entry(pcm->card, "info", pstr->proc_root)) != NULL) {
475 snd_info_set_text_ops(entry, pstr, 256, snd_pcm_stream_proc_info_read); 469 snd_info_set_text_ops(entry, pstr, snd_pcm_stream_proc_info_read);
476 if (snd_info_register(entry) < 0) { 470 if (snd_info_register(entry) < 0) {
477 snd_info_free_entry(entry); 471 snd_info_free_entry(entry);
478 entry = NULL; 472 entry = NULL;
@@ -483,9 +477,7 @@ static int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr)
483#ifdef CONFIG_SND_PCM_XRUN_DEBUG 477#ifdef CONFIG_SND_PCM_XRUN_DEBUG
484 if ((entry = snd_info_create_card_entry(pcm->card, "xrun_debug", 478 if ((entry = snd_info_create_card_entry(pcm->card, "xrun_debug",
485 pstr->proc_root)) != NULL) { 479 pstr->proc_root)) != NULL) {
486 entry->c.text.read_size = 64;
487 entry->c.text.read = snd_pcm_xrun_debug_read; 480 entry->c.text.read = snd_pcm_xrun_debug_read;
488 entry->c.text.write_size = 64;
489 entry->c.text.write = snd_pcm_xrun_debug_write; 481 entry->c.text.write = snd_pcm_xrun_debug_write;
490 entry->mode |= S_IWUSR; 482 entry->mode |= S_IWUSR;
491 entry->private_data = pstr; 483 entry->private_data = pstr;
@@ -537,7 +529,8 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream)
537 substream->proc_root = entry; 529 substream->proc_root = entry;
538 530
539 if ((entry = snd_info_create_card_entry(card, "info", substream->proc_root)) != NULL) { 531 if ((entry = snd_info_create_card_entry(card, "info", substream->proc_root)) != NULL) {
540 snd_info_set_text_ops(entry, substream, 256, snd_pcm_substream_proc_info_read); 532 snd_info_set_text_ops(entry, substream,
533 snd_pcm_substream_proc_info_read);
541 if (snd_info_register(entry) < 0) { 534 if (snd_info_register(entry) < 0) {
542 snd_info_free_entry(entry); 535 snd_info_free_entry(entry);
543 entry = NULL; 536 entry = NULL;
@@ -546,7 +539,8 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream)
546 substream->proc_info_entry = entry; 539 substream->proc_info_entry = entry;
547 540
548 if ((entry = snd_info_create_card_entry(card, "hw_params", substream->proc_root)) != NULL) { 541 if ((entry = snd_info_create_card_entry(card, "hw_params", substream->proc_root)) != NULL) {
549 snd_info_set_text_ops(entry, substream, 256, snd_pcm_substream_proc_hw_params_read); 542 snd_info_set_text_ops(entry, substream,
543 snd_pcm_substream_proc_hw_params_read);
550 if (snd_info_register(entry) < 0) { 544 if (snd_info_register(entry) < 0) {
551 snd_info_free_entry(entry); 545 snd_info_free_entry(entry);
552 entry = NULL; 546 entry = NULL;
@@ -555,7 +549,8 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream)
555 substream->proc_hw_params_entry = entry; 549 substream->proc_hw_params_entry = entry;
556 550
557 if ((entry = snd_info_create_card_entry(card, "sw_params", substream->proc_root)) != NULL) { 551 if ((entry = snd_info_create_card_entry(card, "sw_params", substream->proc_root)) != NULL) {
558 snd_info_set_text_ops(entry, substream, 256, snd_pcm_substream_proc_sw_params_read); 552 snd_info_set_text_ops(entry, substream,
553 snd_pcm_substream_proc_sw_params_read);
559 if (snd_info_register(entry) < 0) { 554 if (snd_info_register(entry) < 0) {
560 snd_info_free_entry(entry); 555 snd_info_free_entry(entry);
561 entry = NULL; 556 entry = NULL;
@@ -564,7 +559,8 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream)
564 substream->proc_sw_params_entry = entry; 559 substream->proc_sw_params_entry = entry;
565 560
566 if ((entry = snd_info_create_card_entry(card, "status", substream->proc_root)) != NULL) { 561 if ((entry = snd_info_create_card_entry(card, "status", substream->proc_root)) != NULL) {
567 snd_info_set_text_ops(entry, substream, 256, snd_pcm_substream_proc_status_read); 562 snd_info_set_text_ops(entry, substream,
563 snd_pcm_substream_proc_status_read);
568 if (snd_info_register(entry) < 0) { 564 if (snd_info_register(entry) < 0) {
569 snd_info_free_entry(entry); 565 snd_info_free_entry(entry);
570 entry = NULL; 566 entry = NULL;
@@ -666,11 +662,14 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
666 INIT_LIST_HEAD(&substream->self_group.substreams); 662 INIT_LIST_HEAD(&substream->self_group.substreams);
667 list_add_tail(&substream->link_list, &substream->self_group.substreams); 663 list_add_tail(&substream->link_list, &substream->self_group.substreams);
668 spin_lock_init(&substream->timer_lock); 664 spin_lock_init(&substream->timer_lock);
665 atomic_set(&substream->mmap_count, 0);
669 prev = substream; 666 prev = substream;
670 } 667 }
671 return 0; 668 return 0;
672} 669}
673 670
671EXPORT_SYMBOL(snd_pcm_new_stream);
672
674/** 673/**
675 * snd_pcm_new - create a new PCM instance 674 * snd_pcm_new - create a new PCM instance
676 * @card: the card instance 675 * @card: the card instance
@@ -730,6 +729,8 @@ int snd_pcm_new(struct snd_card *card, char *id, int device,
730 return 0; 729 return 0;
731} 730}
732 731
732EXPORT_SYMBOL(snd_pcm_new);
733
733static void snd_pcm_free_stream(struct snd_pcm_str * pstr) 734static void snd_pcm_free_stream(struct snd_pcm_str * pstr)
734{ 735{
735 struct snd_pcm_substream *substream, *substream_next; 736 struct snd_pcm_substream *substream, *substream_next;
@@ -829,6 +830,26 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
829 return -EINVAL; 830 return -EINVAL;
830 } 831 }
831 832
833 if (file->f_flags & O_APPEND) {
834 if (prefer_subdevice < 0) {
835 if (pstr->substream_count > 1)
836 return -EINVAL; /* must be unique */
837 substream = pstr->substream;
838 } else {
839 for (substream = pstr->substream; substream;
840 substream = substream->next)
841 if (substream->number == prefer_subdevice)
842 break;
843 }
844 if (! substream)
845 return -ENODEV;
846 if (! SUBSTREAM_BUSY(substream))
847 return -EBADFD;
848 substream->ref_count++;
849 *rsubstream = substream;
850 return 0;
851 }
852
832 if (prefer_subdevice >= 0) { 853 if (prefer_subdevice >= 0) {
833 for (substream = pstr->substream; substream; substream = substream->next) 854 for (substream = pstr->substream; substream; substream = substream->next)
834 if (!SUBSTREAM_BUSY(substream) && substream->number == prefer_subdevice) 855 if (!SUBSTREAM_BUSY(substream) && substream->number == prefer_subdevice)
@@ -864,7 +885,6 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
864 memset((void*)runtime->control, 0, size); 885 memset((void*)runtime->control, 0, size);
865 886
866 init_waitqueue_head(&runtime->sleep); 887 init_waitqueue_head(&runtime->sleep);
867 atomic_set(&runtime->mmap_count, 0);
868 init_timer(&runtime->tick_timer); 888 init_timer(&runtime->tick_timer);
869 runtime->tick_timer.function = snd_pcm_tick_timer_func; 889 runtime->tick_timer.function = snd_pcm_tick_timer_func;
870 runtime->tick_timer.data = (unsigned long) substream; 890 runtime->tick_timer.data = (unsigned long) substream;
@@ -873,7 +893,8 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
873 893
874 substream->runtime = runtime; 894 substream->runtime = runtime;
875 substream->private_data = pcm->private_data; 895 substream->private_data = pcm->private_data;
876 substream->ffile = file; 896 substream->ref_count = 1;
897 substream->f_flags = file->f_flags;
877 pstr->substream_opened++; 898 pstr->substream_opened++;
878 *rsubstream = substream; 899 *rsubstream = substream;
879 return 0; 900 return 0;
@@ -882,7 +903,7 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
882void snd_pcm_detach_substream(struct snd_pcm_substream *substream) 903void snd_pcm_detach_substream(struct snd_pcm_substream *substream)
883{ 904{
884 struct snd_pcm_runtime *runtime; 905 struct snd_pcm_runtime *runtime;
885 substream->file = NULL; 906
886 runtime = substream->runtime; 907 runtime = substream->runtime;
887 snd_assert(runtime != NULL, return); 908 snd_assert(runtime != NULL, return);
888 if (runtime->private_free != NULL) 909 if (runtime->private_free != NULL)
@@ -1022,6 +1043,8 @@ int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree)
1022 return 0; 1043 return 0;
1023} 1044}
1024 1045
1046EXPORT_SYMBOL(snd_pcm_notify);
1047
1025#ifdef CONFIG_PROC_FS 1048#ifdef CONFIG_PROC_FS
1026/* 1049/*
1027 * Info interface 1050 * Info interface
@@ -1049,15 +1072,14 @@ static void snd_pcm_proc_read(struct snd_info_entry *entry,
1049 mutex_unlock(&register_mutex); 1072 mutex_unlock(&register_mutex);
1050} 1073}
1051 1074
1052static struct snd_info_entry *snd_pcm_proc_entry = NULL; 1075static struct snd_info_entry *snd_pcm_proc_entry;
1053 1076
1054static void snd_pcm_proc_init(void) 1077static void snd_pcm_proc_init(void)
1055{ 1078{
1056 struct snd_info_entry *entry; 1079 struct snd_info_entry *entry;
1057 1080
1058 if ((entry = snd_info_create_module_entry(THIS_MODULE, "pcm", NULL)) != NULL) { 1081 if ((entry = snd_info_create_module_entry(THIS_MODULE, "pcm", NULL)) != NULL) {
1059 snd_info_set_text_ops(entry, NULL, SNDRV_CARDS * SNDRV_PCM_DEVICES * 128, 1082 snd_info_set_text_ops(entry, NULL, snd_pcm_proc_read);
1060 snd_pcm_proc_read);
1061 if (snd_info_register(entry) < 0) { 1083 if (snd_info_register(entry) < 0) {
1062 snd_info_free_entry(entry); 1084 snd_info_free_entry(entry);
1063 entry = NULL; 1085 entry = NULL;
@@ -1099,33 +1121,3 @@ static void __exit alsa_pcm_exit(void)
1099 1121
1100module_init(alsa_pcm_init) 1122module_init(alsa_pcm_init)
1101module_exit(alsa_pcm_exit) 1123module_exit(alsa_pcm_exit)
1102
1103EXPORT_SYMBOL(snd_pcm_new);
1104EXPORT_SYMBOL(snd_pcm_new_stream);
1105EXPORT_SYMBOL(snd_pcm_notify);
1106EXPORT_SYMBOL(snd_pcm_open_substream);
1107EXPORT_SYMBOL(snd_pcm_release_substream);
1108 /* pcm_native.c */
1109EXPORT_SYMBOL(snd_pcm_link_rwlock);
1110#ifdef CONFIG_PM
1111EXPORT_SYMBOL(snd_pcm_suspend);
1112EXPORT_SYMBOL(snd_pcm_suspend_all);
1113#endif
1114EXPORT_SYMBOL(snd_pcm_kernel_ioctl);
1115EXPORT_SYMBOL(snd_pcm_mmap_data);
1116#if SNDRV_PCM_INFO_MMAP_IOMEM
1117EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem);
1118#endif
1119 /* pcm_misc.c */
1120EXPORT_SYMBOL(snd_pcm_format_signed);
1121EXPORT_SYMBOL(snd_pcm_format_unsigned);
1122EXPORT_SYMBOL(snd_pcm_format_linear);
1123EXPORT_SYMBOL(snd_pcm_format_little_endian);
1124EXPORT_SYMBOL(snd_pcm_format_big_endian);
1125EXPORT_SYMBOL(snd_pcm_format_width);
1126EXPORT_SYMBOL(snd_pcm_format_physical_width);
1127EXPORT_SYMBOL(snd_pcm_format_size);
1128EXPORT_SYMBOL(snd_pcm_format_silence_64);
1129EXPORT_SYMBOL(snd_pcm_format_set_silence);
1130EXPORT_SYMBOL(snd_pcm_build_linear_format);
1131EXPORT_SYMBOL(snd_pcm_limit_hw_rates);
diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c
index e5133033de5e..2b8aab6fd6cd 100644
--- a/sound/core/pcm_compat.c
+++ b/sound/core/pcm_compat.c
@@ -497,9 +497,9 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l
497 case SNDRV_PCM_IOCTL_LINK: 497 case SNDRV_PCM_IOCTL_LINK:
498 case SNDRV_PCM_IOCTL_UNLINK: 498 case SNDRV_PCM_IOCTL_UNLINK:
499 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 499 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
500 return snd_pcm_playback_ioctl1(substream, cmd, argp); 500 return snd_pcm_playback_ioctl1(file, substream, cmd, argp);
501 else 501 else
502 return snd_pcm_capture_ioctl1(substream, cmd, argp); 502 return snd_pcm_capture_ioctl1(file, substream, cmd, argp);
503 case SNDRV_PCM_IOCTL_HW_REFINE32: 503 case SNDRV_PCM_IOCTL_HW_REFINE32:
504 return snd_pcm_ioctl_hw_params_compat(substream, 1, argp); 504 return snd_pcm_ioctl_hw_params_compat(substream, 1, argp);
505 case SNDRV_PCM_IOCTL_HW_PARAMS32: 505 case SNDRV_PCM_IOCTL_HW_PARAMS32:
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index eedc6cb038bb..0bb142a28539 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -289,6 +289,7 @@ void snd_pcm_set_ops(struct snd_pcm *pcm, int direction, struct snd_pcm_ops *ops
289 substream->ops = ops; 289 substream->ops = ops;
290} 290}
291 291
292EXPORT_SYMBOL(snd_pcm_set_ops);
292 293
293/** 294/**
294 * snd_pcm_sync - set the PCM sync id 295 * snd_pcm_sync - set the PCM sync id
@@ -306,13 +307,12 @@ void snd_pcm_set_sync(struct snd_pcm_substream *substream)
306 runtime->sync.id32[3] = -1; 307 runtime->sync.id32[3] = -1;
307} 308}
308 309
310EXPORT_SYMBOL(snd_pcm_set_sync);
311
309/* 312/*
310 * Standard ioctl routine 313 * Standard ioctl routine
311 */ 314 */
312 315
313/* Code taken from alsa-lib */
314#define assert(a) snd_assert((a), return -EINVAL)
315
316static inline unsigned int div32(unsigned int a, unsigned int b, 316static inline unsigned int div32(unsigned int a, unsigned int b,
317 unsigned int *r) 317 unsigned int *r)
318{ 318{
@@ -369,56 +369,6 @@ static inline unsigned int muldiv32(unsigned int a, unsigned int b,
369 return n; 369 return n;
370} 370}
371 371
372static int snd_interval_refine_min(struct snd_interval *i, unsigned int min, int openmin)
373{
374 int changed = 0;
375 assert(!snd_interval_empty(i));
376 if (i->min < min) {
377 i->min = min;
378 i->openmin = openmin;
379 changed = 1;
380 } else if (i->min == min && !i->openmin && openmin) {
381 i->openmin = 1;
382 changed = 1;
383 }
384 if (i->integer) {
385 if (i->openmin) {
386 i->min++;
387 i->openmin = 0;
388 }
389 }
390 if (snd_interval_checkempty(i)) {
391 snd_interval_none(i);
392 return -EINVAL;
393 }
394 return changed;
395}
396
397static int snd_interval_refine_max(struct snd_interval *i, unsigned int max, int openmax)
398{
399 int changed = 0;
400 assert(!snd_interval_empty(i));
401 if (i->max > max) {
402 i->max = max;
403 i->openmax = openmax;
404 changed = 1;
405 } else if (i->max == max && !i->openmax && openmax) {
406 i->openmax = 1;
407 changed = 1;
408 }
409 if (i->integer) {
410 if (i->openmax) {
411 i->max--;
412 i->openmax = 0;
413 }
414 }
415 if (snd_interval_checkempty(i)) {
416 snd_interval_none(i);
417 return -EINVAL;
418 }
419 return changed;
420}
421
422/** 372/**
423 * snd_interval_refine - refine the interval value of configurator 373 * snd_interval_refine - refine the interval value of configurator
424 * @i: the interval value to refine 374 * @i: the interval value to refine
@@ -433,7 +383,7 @@ static int snd_interval_refine_max(struct snd_interval *i, unsigned int max, int
433int snd_interval_refine(struct snd_interval *i, const struct snd_interval *v) 383int snd_interval_refine(struct snd_interval *i, const struct snd_interval *v)
434{ 384{
435 int changed = 0; 385 int changed = 0;
436 assert(!snd_interval_empty(i)); 386 snd_assert(!snd_interval_empty(i), return -EINVAL);
437 if (i->min < v->min) { 387 if (i->min < v->min) {
438 i->min = v->min; 388 i->min = v->min;
439 i->openmin = v->openmin; 389 i->openmin = v->openmin;
@@ -472,9 +422,11 @@ int snd_interval_refine(struct snd_interval *i, const struct snd_interval *v)
472 return changed; 422 return changed;
473} 423}
474 424
425EXPORT_SYMBOL(snd_interval_refine);
426
475static int snd_interval_refine_first(struct snd_interval *i) 427static int snd_interval_refine_first(struct snd_interval *i)
476{ 428{
477 assert(!snd_interval_empty(i)); 429 snd_assert(!snd_interval_empty(i), return -EINVAL);
478 if (snd_interval_single(i)) 430 if (snd_interval_single(i))
479 return 0; 431 return 0;
480 i->max = i->min; 432 i->max = i->min;
@@ -486,7 +438,7 @@ static int snd_interval_refine_first(struct snd_interval *i)
486 438
487static int snd_interval_refine_last(struct snd_interval *i) 439static int snd_interval_refine_last(struct snd_interval *i)
488{ 440{
489 assert(!snd_interval_empty(i)); 441 snd_assert(!snd_interval_empty(i), return -EINVAL);
490 if (snd_interval_single(i)) 442 if (snd_interval_single(i))
491 return 0; 443 return 0;
492 i->min = i->max; 444 i->min = i->max;
@@ -496,16 +448,6 @@ static int snd_interval_refine_last(struct snd_interval *i)
496 return 1; 448 return 1;
497} 449}
498 450
499static int snd_interval_refine_set(struct snd_interval *i, unsigned int val)
500{
501 struct snd_interval t;
502 t.empty = 0;
503 t.min = t.max = val;
504 t.openmin = t.openmax = 0;
505 t.integer = 1;
506 return snd_interval_refine(i, &t);
507}
508
509void snd_interval_mul(const struct snd_interval *a, const struct snd_interval *b, struct snd_interval *c) 451void snd_interval_mul(const struct snd_interval *a, const struct snd_interval *b, struct snd_interval *c)
510{ 452{
511 if (a->empty || b->empty) { 453 if (a->empty || b->empty) {
@@ -621,7 +563,6 @@ void snd_interval_mulkdiv(const struct snd_interval *a, unsigned int k,
621 c->integer = 0; 563 c->integer = 0;
622} 564}
623 565
624#undef assert
625/* ---- */ 566/* ---- */
626 567
627 568
@@ -727,6 +668,8 @@ int snd_interval_ratnum(struct snd_interval *i,
727 return err; 668 return err;
728} 669}
729 670
671EXPORT_SYMBOL(snd_interval_ratnum);
672
730/** 673/**
731 * snd_interval_ratden - refine the interval value 674 * snd_interval_ratden - refine the interval value
732 * @i: interval to refine 675 * @i: interval to refine
@@ -877,6 +820,8 @@ int snd_interval_list(struct snd_interval *i, unsigned int count, unsigned int *
877 return changed; 820 return changed;
878} 821}
879 822
823EXPORT_SYMBOL(snd_interval_list);
824
880static int snd_interval_step(struct snd_interval *i, unsigned int min, unsigned int step) 825static int snd_interval_step(struct snd_interval *i, unsigned int min, unsigned int step)
881{ 826{
882 unsigned int n; 827 unsigned int n;
@@ -953,6 +898,8 @@ int snd_pcm_hw_rule_add(struct snd_pcm_runtime *runtime, unsigned int cond,
953 return 0; 898 return 0;
954} 899}
955 900
901EXPORT_SYMBOL(snd_pcm_hw_rule_add);
902
956/** 903/**
957 * snd_pcm_hw_constraint_mask 904 * snd_pcm_hw_constraint_mask
958 * @runtime: PCM runtime instance 905 * @runtime: PCM runtime instance
@@ -1007,6 +954,8 @@ int snd_pcm_hw_constraint_integer(struct snd_pcm_runtime *runtime, snd_pcm_hw_pa
1007 return snd_interval_setinteger(constrs_interval(constrs, var)); 954 return snd_interval_setinteger(constrs_interval(constrs, var));
1008} 955}
1009 956
957EXPORT_SYMBOL(snd_pcm_hw_constraint_integer);
958
1010/** 959/**
1011 * snd_pcm_hw_constraint_minmax 960 * snd_pcm_hw_constraint_minmax
1012 * @runtime: PCM runtime instance 961 * @runtime: PCM runtime instance
@@ -1028,6 +977,8 @@ int snd_pcm_hw_constraint_minmax(struct snd_pcm_runtime *runtime, snd_pcm_hw_par
1028 return snd_interval_refine(constrs_interval(constrs, var), &t); 977 return snd_interval_refine(constrs_interval(constrs, var), &t);
1029} 978}
1030 979
980EXPORT_SYMBOL(snd_pcm_hw_constraint_minmax);
981
1031static int snd_pcm_hw_rule_list(struct snd_pcm_hw_params *params, 982static int snd_pcm_hw_rule_list(struct snd_pcm_hw_params *params,
1032 struct snd_pcm_hw_rule *rule) 983 struct snd_pcm_hw_rule *rule)
1033{ 984{
@@ -1055,6 +1006,8 @@ int snd_pcm_hw_constraint_list(struct snd_pcm_runtime *runtime,
1055 var, -1); 1006 var, -1);
1056} 1007}
1057 1008
1009EXPORT_SYMBOL(snd_pcm_hw_constraint_list);
1010
1058static int snd_pcm_hw_rule_ratnums(struct snd_pcm_hw_params *params, 1011static int snd_pcm_hw_rule_ratnums(struct snd_pcm_hw_params *params,
1059 struct snd_pcm_hw_rule *rule) 1012 struct snd_pcm_hw_rule *rule)
1060{ 1013{
@@ -1087,6 +1040,8 @@ int snd_pcm_hw_constraint_ratnums(struct snd_pcm_runtime *runtime,
1087 var, -1); 1040 var, -1);
1088} 1041}
1089 1042
1043EXPORT_SYMBOL(snd_pcm_hw_constraint_ratnums);
1044
1090static int snd_pcm_hw_rule_ratdens(struct snd_pcm_hw_params *params, 1045static int snd_pcm_hw_rule_ratdens(struct snd_pcm_hw_params *params,
1091 struct snd_pcm_hw_rule *rule) 1046 struct snd_pcm_hw_rule *rule)
1092{ 1047{
@@ -1118,6 +1073,8 @@ int snd_pcm_hw_constraint_ratdens(struct snd_pcm_runtime *runtime,
1118 var, -1); 1073 var, -1);
1119} 1074}
1120 1075
1076EXPORT_SYMBOL(snd_pcm_hw_constraint_ratdens);
1077
1121static int snd_pcm_hw_rule_msbits(struct snd_pcm_hw_params *params, 1078static int snd_pcm_hw_rule_msbits(struct snd_pcm_hw_params *params,
1122 struct snd_pcm_hw_rule *rule) 1079 struct snd_pcm_hw_rule *rule)
1123{ 1080{
@@ -1149,6 +1106,8 @@ int snd_pcm_hw_constraint_msbits(struct snd_pcm_runtime *runtime,
1149 SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1); 1106 SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1);
1150} 1107}
1151 1108
1109EXPORT_SYMBOL(snd_pcm_hw_constraint_msbits);
1110
1152static int snd_pcm_hw_rule_step(struct snd_pcm_hw_params *params, 1111static int snd_pcm_hw_rule_step(struct snd_pcm_hw_params *params,
1153 struct snd_pcm_hw_rule *rule) 1112 struct snd_pcm_hw_rule *rule)
1154{ 1113{
@@ -1173,6 +1132,8 @@ int snd_pcm_hw_constraint_step(struct snd_pcm_runtime *runtime,
1173 var, -1); 1132 var, -1);
1174} 1133}
1175 1134
1135EXPORT_SYMBOL(snd_pcm_hw_constraint_step);
1136
1176static int snd_pcm_hw_rule_pow2(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) 1137static int snd_pcm_hw_rule_pow2(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule)
1177{ 1138{
1178 static int pow2_sizes[] = { 1139 static int pow2_sizes[] = {
@@ -1200,11 +1161,7 @@ int snd_pcm_hw_constraint_pow2(struct snd_pcm_runtime *runtime,
1200 var, -1); 1161 var, -1);
1201} 1162}
1202 1163
1203/* To use the same code we have in alsa-lib */ 1164EXPORT_SYMBOL(snd_pcm_hw_constraint_pow2);
1204#define assert(i) snd_assert((i), return -EINVAL)
1205#ifndef INT_MIN
1206#define INT_MIN ((int)((unsigned int)INT_MAX+1))
1207#endif
1208 1165
1209static void _snd_pcm_hw_param_any(struct snd_pcm_hw_params *params, 1166static void _snd_pcm_hw_param_any(struct snd_pcm_hw_params *params,
1210 snd_pcm_hw_param_t var) 1167 snd_pcm_hw_param_t var)
@@ -1224,18 +1181,6 @@ static void _snd_pcm_hw_param_any(struct snd_pcm_hw_params *params,
1224 snd_BUG(); 1181 snd_BUG();
1225} 1182}
1226 1183
1227#if 0
1228/*
1229 * snd_pcm_hw_param_any
1230 */
1231int snd_pcm_hw_param_any(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params,
1232 snd_pcm_hw_param_t var)
1233{
1234 _snd_pcm_hw_param_any(params, var);
1235 return snd_pcm_hw_refine(pcm, params);
1236}
1237#endif /* 0 */
1238
1239void _snd_pcm_hw_params_any(struct snd_pcm_hw_params *params) 1184void _snd_pcm_hw_params_any(struct snd_pcm_hw_params *params)
1240{ 1185{
1241 unsigned int k; 1186 unsigned int k;
@@ -1247,18 +1192,7 @@ void _snd_pcm_hw_params_any(struct snd_pcm_hw_params *params)
1247 params->info = ~0U; 1192 params->info = ~0U;
1248} 1193}
1249 1194
1250#if 0 1195EXPORT_SYMBOL(_snd_pcm_hw_params_any);
1251/*
1252 * snd_pcm_hw_params_any
1253 *
1254 * Fill PARAMS with full configuration space boundaries
1255 */
1256int snd_pcm_hw_params_any(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params)
1257{
1258 _snd_pcm_hw_params_any(params);
1259 return snd_pcm_hw_refine(pcm, params);
1260}
1261#endif /* 0 */
1262 1196
1263/** 1197/**
1264 * snd_pcm_hw_param_value 1198 * snd_pcm_hw_param_value
@@ -1269,8 +1203,8 @@ int snd_pcm_hw_params_any(struct snd_pcm_substream *pcm, struct snd_pcm_hw_param
1269 * Return the value for field PAR if it's fixed in configuration space 1203 * Return the value for field PAR if it's fixed in configuration space
1270 * defined by PARAMS. Return -EINVAL otherwise 1204 * defined by PARAMS. Return -EINVAL otherwise
1271 */ 1205 */
1272static int snd_pcm_hw_param_value(const struct snd_pcm_hw_params *params, 1206int snd_pcm_hw_param_value(const struct snd_pcm_hw_params *params,
1273 snd_pcm_hw_param_t var, int *dir) 1207 snd_pcm_hw_param_t var, int *dir)
1274{ 1208{
1275 if (hw_is_mask(var)) { 1209 if (hw_is_mask(var)) {
1276 const struct snd_mask *mask = hw_param_mask_c(params, var); 1210 const struct snd_mask *mask = hw_param_mask_c(params, var);
@@ -1288,61 +1222,10 @@ static int snd_pcm_hw_param_value(const struct snd_pcm_hw_params *params,
1288 *dir = i->openmin; 1222 *dir = i->openmin;
1289 return snd_interval_value(i); 1223 return snd_interval_value(i);
1290 } 1224 }
1291 assert(0);
1292 return -EINVAL;
1293}
1294
1295/**
1296 * snd_pcm_hw_param_value_min
1297 * @params: the hw_params instance
1298 * @var: parameter to retrieve
1299 * @dir: pointer to the direction (-1,0,1) or NULL
1300 *
1301 * Return the minimum value for field PAR.
1302 */
1303unsigned int snd_pcm_hw_param_value_min(const struct snd_pcm_hw_params *params,
1304 snd_pcm_hw_param_t var, int *dir)
1305{
1306 if (hw_is_mask(var)) {
1307 if (dir)
1308 *dir = 0;
1309 return snd_mask_min(hw_param_mask_c(params, var));
1310 }
1311 if (hw_is_interval(var)) {
1312 const struct snd_interval *i = hw_param_interval_c(params, var);
1313 if (dir)
1314 *dir = i->openmin;
1315 return snd_interval_min(i);
1316 }
1317 assert(0);
1318 return -EINVAL; 1225 return -EINVAL;
1319} 1226}
1320 1227
1321/** 1228EXPORT_SYMBOL(snd_pcm_hw_param_value);
1322 * snd_pcm_hw_param_value_max
1323 * @params: the hw_params instance
1324 * @var: parameter to retrieve
1325 * @dir: pointer to the direction (-1,0,1) or NULL
1326 *
1327 * Return the maximum value for field PAR.
1328 */
1329unsigned int snd_pcm_hw_param_value_max(const struct snd_pcm_hw_params *params,
1330 snd_pcm_hw_param_t var, int *dir)
1331{
1332 if (hw_is_mask(var)) {
1333 if (dir)
1334 *dir = 0;
1335 return snd_mask_max(hw_param_mask_c(params, var));
1336 }
1337 if (hw_is_interval(var)) {
1338 const struct snd_interval *i = hw_param_interval_c(params, var);
1339 if (dir)
1340 *dir = - (int) i->openmax;
1341 return snd_interval_max(i);
1342 }
1343 assert(0);
1344 return -EINVAL;
1345}
1346 1229
1347void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params, 1230void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params,
1348 snd_pcm_hw_param_t var) 1231 snd_pcm_hw_param_t var)
@@ -1360,42 +1243,7 @@ void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params,
1360 } 1243 }
1361} 1244}
1362 1245
1363int _snd_pcm_hw_param_setinteger(struct snd_pcm_hw_params *params, 1246EXPORT_SYMBOL(_snd_pcm_hw_param_setempty);
1364 snd_pcm_hw_param_t var)
1365{
1366 int changed;
1367 assert(hw_is_interval(var));
1368 changed = snd_interval_setinteger(hw_param_interval(params, var));
1369 if (changed) {
1370 params->cmask |= 1 << var;
1371 params->rmask |= 1 << var;
1372 }
1373 return changed;
1374}
1375
1376#if 0
1377/*
1378 * snd_pcm_hw_param_setinteger
1379 *
1380 * Inside configuration space defined by PARAMS remove from PAR all
1381 * non integer values. Reduce configuration space accordingly.
1382 * Return -EINVAL if the configuration space is empty
1383 */
1384int snd_pcm_hw_param_setinteger(struct snd_pcm_substream *pcm,
1385 struct snd_pcm_hw_params *params,
1386 snd_pcm_hw_param_t var)
1387{
1388 int changed = _snd_pcm_hw_param_setinteger(params, var);
1389 if (changed < 0)
1390 return changed;
1391 if (params->rmask) {
1392 int err = snd_pcm_hw_refine(pcm, params);
1393 if (err < 0)
1394 return err;
1395 }
1396 return 0;
1397}
1398#endif /* 0 */
1399 1247
1400static int _snd_pcm_hw_param_first(struct snd_pcm_hw_params *params, 1248static int _snd_pcm_hw_param_first(struct snd_pcm_hw_params *params,
1401 snd_pcm_hw_param_t var) 1249 snd_pcm_hw_param_t var)
@@ -1405,10 +1253,8 @@ static int _snd_pcm_hw_param_first(struct snd_pcm_hw_params *params,
1405 changed = snd_mask_refine_first(hw_param_mask(params, var)); 1253 changed = snd_mask_refine_first(hw_param_mask(params, var));
1406 else if (hw_is_interval(var)) 1254 else if (hw_is_interval(var))
1407 changed = snd_interval_refine_first(hw_param_interval(params, var)); 1255 changed = snd_interval_refine_first(hw_param_interval(params, var));
1408 else { 1256 else
1409 assert(0);
1410 return -EINVAL; 1257 return -EINVAL;
1411 }
1412 if (changed) { 1258 if (changed) {
1413 params->cmask |= 1 << var; 1259 params->cmask |= 1 << var;
1414 params->rmask |= 1 << var; 1260 params->rmask |= 1 << var;
@@ -1428,20 +1274,22 @@ static int _snd_pcm_hw_param_first(struct snd_pcm_hw_params *params,
1428 * values > minimum. Reduce configuration space accordingly. 1274 * values > minimum. Reduce configuration space accordingly.
1429 * Return the minimum. 1275 * Return the minimum.
1430 */ 1276 */
1431static int snd_pcm_hw_param_first(struct snd_pcm_substream *pcm, 1277int snd_pcm_hw_param_first(struct snd_pcm_substream *pcm,
1432 struct snd_pcm_hw_params *params, 1278 struct snd_pcm_hw_params *params,
1433 snd_pcm_hw_param_t var, int *dir) 1279 snd_pcm_hw_param_t var, int *dir)
1434{ 1280{
1435 int changed = _snd_pcm_hw_param_first(params, var); 1281 int changed = _snd_pcm_hw_param_first(params, var);
1436 if (changed < 0) 1282 if (changed < 0)
1437 return changed; 1283 return changed;
1438 if (params->rmask) { 1284 if (params->rmask) {
1439 int err = snd_pcm_hw_refine(pcm, params); 1285 int err = snd_pcm_hw_refine(pcm, params);
1440 assert(err >= 0); 1286 snd_assert(err >= 0, return err);
1441 } 1287 }
1442 return snd_pcm_hw_param_value(params, var, dir); 1288 return snd_pcm_hw_param_value(params, var, dir);
1443} 1289}
1444 1290
1291EXPORT_SYMBOL(snd_pcm_hw_param_first);
1292
1445static int _snd_pcm_hw_param_last(struct snd_pcm_hw_params *params, 1293static int _snd_pcm_hw_param_last(struct snd_pcm_hw_params *params,
1446 snd_pcm_hw_param_t var) 1294 snd_pcm_hw_param_t var)
1447{ 1295{
@@ -1450,10 +1298,8 @@ static int _snd_pcm_hw_param_last(struct snd_pcm_hw_params *params,
1450 changed = snd_mask_refine_last(hw_param_mask(params, var)); 1298 changed = snd_mask_refine_last(hw_param_mask(params, var));
1451 else if (hw_is_interval(var)) 1299 else if (hw_is_interval(var))
1452 changed = snd_interval_refine_last(hw_param_interval(params, var)); 1300 changed = snd_interval_refine_last(hw_param_interval(params, var));
1453 else { 1301 else
1454 assert(0);
1455 return -EINVAL; 1302 return -EINVAL;
1456 }
1457 if (changed) { 1303 if (changed) {
1458 params->cmask |= 1 << var; 1304 params->cmask |= 1 << var;
1459 params->rmask |= 1 << var; 1305 params->rmask |= 1 << var;
@@ -1473,381 +1319,21 @@ static int _snd_pcm_hw_param_last(struct snd_pcm_hw_params *params,
1473 * values < maximum. Reduce configuration space accordingly. 1319 * values < maximum. Reduce configuration space accordingly.
1474 * Return the maximum. 1320 * Return the maximum.
1475 */ 1321 */
1476static int snd_pcm_hw_param_last(struct snd_pcm_substream *pcm, 1322int snd_pcm_hw_param_last(struct snd_pcm_substream *pcm,
1477 struct snd_pcm_hw_params *params, 1323 struct snd_pcm_hw_params *params,
1478 snd_pcm_hw_param_t var, int *dir) 1324 snd_pcm_hw_param_t var, int *dir)
1479{ 1325{
1480 int changed = _snd_pcm_hw_param_last(params, var); 1326 int changed = _snd_pcm_hw_param_last(params, var);
1481 if (changed < 0) 1327 if (changed < 0)
1482 return changed; 1328 return changed;
1483 if (params->rmask) { 1329 if (params->rmask) {
1484 int err = snd_pcm_hw_refine(pcm, params); 1330 int err = snd_pcm_hw_refine(pcm, params);
1485 assert(err >= 0); 1331 snd_assert(err >= 0, return err);
1486 } 1332 }
1487 return snd_pcm_hw_param_value(params, var, dir); 1333 return snd_pcm_hw_param_value(params, var, dir);
1488} 1334}
1489 1335
1490int _snd_pcm_hw_param_min(struct snd_pcm_hw_params *params, 1336EXPORT_SYMBOL(snd_pcm_hw_param_last);
1491 snd_pcm_hw_param_t var, unsigned int val, int dir)
1492{
1493 int changed;
1494 int open = 0;
1495 if (dir) {
1496 if (dir > 0) {
1497 open = 1;
1498 } else if (dir < 0) {
1499 if (val > 0) {
1500 open = 1;
1501 val--;
1502 }
1503 }
1504 }
1505 if (hw_is_mask(var))
1506 changed = snd_mask_refine_min(hw_param_mask(params, var), val + !!open);
1507 else if (hw_is_interval(var))
1508 changed = snd_interval_refine_min(hw_param_interval(params, var), val, open);
1509 else {
1510 assert(0);
1511 return -EINVAL;
1512 }
1513 if (changed) {
1514 params->cmask |= 1 << var;
1515 params->rmask |= 1 << var;
1516 }
1517 return changed;
1518}
1519
1520/**
1521 * snd_pcm_hw_param_min
1522 * @pcm: PCM instance
1523 * @params: the hw_params instance
1524 * @var: parameter to retrieve
1525 * @val: minimal value
1526 * @dir: pointer to the direction (-1,0,1) or NULL
1527 *
1528 * Inside configuration space defined by PARAMS remove from PAR all
1529 * values < VAL. Reduce configuration space accordingly.
1530 * Return new minimum or -EINVAL if the configuration space is empty
1531 */
1532static int snd_pcm_hw_param_min(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params,
1533 snd_pcm_hw_param_t var, unsigned int val,
1534 int *dir)
1535{
1536 int changed = _snd_pcm_hw_param_min(params, var, val, dir ? *dir : 0);
1537 if (changed < 0)
1538 return changed;
1539 if (params->rmask) {
1540 int err = snd_pcm_hw_refine(pcm, params);
1541 if (err < 0)
1542 return err;
1543 }
1544 return snd_pcm_hw_param_value_min(params, var, dir);
1545}
1546
1547static int _snd_pcm_hw_param_max(struct snd_pcm_hw_params *params,
1548 snd_pcm_hw_param_t var, unsigned int val,
1549 int dir)
1550{
1551 int changed;
1552 int open = 0;
1553 if (dir) {
1554 if (dir < 0) {
1555 open = 1;
1556 } else if (dir > 0) {
1557 open = 1;
1558 val++;
1559 }
1560 }
1561 if (hw_is_mask(var)) {
1562 if (val == 0 && open) {
1563 snd_mask_none(hw_param_mask(params, var));
1564 changed = -EINVAL;
1565 } else
1566 changed = snd_mask_refine_max(hw_param_mask(params, var), val - !!open);
1567 } else if (hw_is_interval(var))
1568 changed = snd_interval_refine_max(hw_param_interval(params, var), val, open);
1569 else {
1570 assert(0);
1571 return -EINVAL;
1572 }
1573 if (changed) {
1574 params->cmask |= 1 << var;
1575 params->rmask |= 1 << var;
1576 }
1577 return changed;
1578}
1579
1580/**
1581 * snd_pcm_hw_param_max
1582 * @pcm: PCM instance
1583 * @params: the hw_params instance
1584 * @var: parameter to retrieve
1585 * @val: maximal value
1586 * @dir: pointer to the direction (-1,0,1) or NULL
1587 *
1588 * Inside configuration space defined by PARAMS remove from PAR all
1589 * values >= VAL + 1. Reduce configuration space accordingly.
1590 * Return new maximum or -EINVAL if the configuration space is empty
1591 */
1592static int snd_pcm_hw_param_max(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params,
1593 snd_pcm_hw_param_t var, unsigned int val,
1594 int *dir)
1595{
1596 int changed = _snd_pcm_hw_param_max(params, var, val, dir ? *dir : 0);
1597 if (changed < 0)
1598 return changed;
1599 if (params->rmask) {
1600 int err = snd_pcm_hw_refine(pcm, params);
1601 if (err < 0)
1602 return err;
1603 }
1604 return snd_pcm_hw_param_value_max(params, var, dir);
1605}
1606
1607int _snd_pcm_hw_param_set(struct snd_pcm_hw_params *params,
1608 snd_pcm_hw_param_t var, unsigned int val, int dir)
1609{
1610 int changed;
1611 if (hw_is_mask(var)) {
1612 struct snd_mask *m = hw_param_mask(params, var);
1613 if (val == 0 && dir < 0) {
1614 changed = -EINVAL;
1615 snd_mask_none(m);
1616 } else {
1617 if (dir > 0)
1618 val++;
1619 else if (dir < 0)
1620 val--;
1621 changed = snd_mask_refine_set(hw_param_mask(params, var), val);
1622 }
1623 } else if (hw_is_interval(var)) {
1624 struct snd_interval *i = hw_param_interval(params, var);
1625 if (val == 0 && dir < 0) {
1626 changed = -EINVAL;
1627 snd_interval_none(i);
1628 } else if (dir == 0)
1629 changed = snd_interval_refine_set(i, val);
1630 else {
1631 struct snd_interval t;
1632 t.openmin = 1;
1633 t.openmax = 1;
1634 t.empty = 0;
1635 t.integer = 0;
1636 if (dir < 0) {
1637 t.min = val - 1;
1638 t.max = val;
1639 } else {
1640 t.min = val;
1641 t.max = val+1;
1642 }
1643 changed = snd_interval_refine(i, &t);
1644 }
1645 } else {
1646 assert(0);
1647 return -EINVAL;
1648 }
1649 if (changed) {
1650 params->cmask |= 1 << var;
1651 params->rmask |= 1 << var;
1652 }
1653 return changed;
1654}
1655
1656/**
1657 * snd_pcm_hw_param_set
1658 * @pcm: PCM instance
1659 * @params: the hw_params instance
1660 * @var: parameter to retrieve
1661 * @val: value to set
1662 * @dir: pointer to the direction (-1,0,1) or NULL
1663 *
1664 * Inside configuration space defined by PARAMS remove from PAR all
1665 * values != VAL. Reduce configuration space accordingly.
1666 * Return VAL or -EINVAL if the configuration space is empty
1667 */
1668int snd_pcm_hw_param_set(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params,
1669 snd_pcm_hw_param_t var, unsigned int val, int dir)
1670{
1671 int changed = _snd_pcm_hw_param_set(params, var, val, dir);
1672 if (changed < 0)
1673 return changed;
1674 if (params->rmask) {
1675 int err = snd_pcm_hw_refine(pcm, params);
1676 if (err < 0)
1677 return err;
1678 }
1679 return snd_pcm_hw_param_value(params, var, NULL);
1680}
1681
1682static int _snd_pcm_hw_param_mask(struct snd_pcm_hw_params *params,
1683 snd_pcm_hw_param_t var, const struct snd_mask *val)
1684{
1685 int changed;
1686 assert(hw_is_mask(var));
1687 changed = snd_mask_refine(hw_param_mask(params, var), val);
1688 if (changed) {
1689 params->cmask |= 1 << var;
1690 params->rmask |= 1 << var;
1691 }
1692 return changed;
1693}
1694
1695/**
1696 * snd_pcm_hw_param_mask
1697 * @pcm: PCM instance
1698 * @params: the hw_params instance
1699 * @var: parameter to retrieve
1700 * @val: mask to apply
1701 *
1702 * Inside configuration space defined by PARAMS remove from PAR all values
1703 * not contained in MASK. Reduce configuration space accordingly.
1704 * This function can be called only for SNDRV_PCM_HW_PARAM_ACCESS,
1705 * SNDRV_PCM_HW_PARAM_FORMAT, SNDRV_PCM_HW_PARAM_SUBFORMAT.
1706 * Return 0 on success or -EINVAL
1707 * if the configuration space is empty
1708 */
1709int snd_pcm_hw_param_mask(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params,
1710 snd_pcm_hw_param_t var, const struct snd_mask *val)
1711{
1712 int changed = _snd_pcm_hw_param_mask(params, var, val);
1713 if (changed < 0)
1714 return changed;
1715 if (params->rmask) {
1716 int err = snd_pcm_hw_refine(pcm, params);
1717 if (err < 0)
1718 return err;
1719 }
1720 return 0;
1721}
1722
1723static int boundary_sub(int a, int adir,
1724 int b, int bdir,
1725 int *c, int *cdir)
1726{
1727 adir = adir < 0 ? -1 : (adir > 0 ? 1 : 0);
1728 bdir = bdir < 0 ? -1 : (bdir > 0 ? 1 : 0);
1729 *c = a - b;
1730 *cdir = adir - bdir;
1731 if (*cdir == -2) {
1732 assert(*c > INT_MIN);
1733 (*c)--;
1734 } else if (*cdir == 2) {
1735 assert(*c < INT_MAX);
1736 (*c)++;
1737 }
1738 return 0;
1739}
1740
1741static int boundary_lt(unsigned int a, int adir,
1742 unsigned int b, int bdir)
1743{
1744 assert(a > 0 || adir >= 0);
1745 assert(b > 0 || bdir >= 0);
1746 if (adir < 0) {
1747 a--;
1748 adir = 1;
1749 } else if (adir > 0)
1750 adir = 1;
1751 if (bdir < 0) {
1752 b--;
1753 bdir = 1;
1754 } else if (bdir > 0)
1755 bdir = 1;
1756 return a < b || (a == b && adir < bdir);
1757}
1758
1759/* Return 1 if min is nearer to best than max */
1760static int boundary_nearer(int min, int mindir,
1761 int best, int bestdir,
1762 int max, int maxdir)
1763{
1764 int dmin, dmindir;
1765 int dmax, dmaxdir;
1766 boundary_sub(best, bestdir, min, mindir, &dmin, &dmindir);
1767 boundary_sub(max, maxdir, best, bestdir, &dmax, &dmaxdir);
1768 return boundary_lt(dmin, dmindir, dmax, dmaxdir);
1769}
1770
1771/**
1772 * snd_pcm_hw_param_near
1773 * @pcm: PCM instance
1774 * @params: the hw_params instance
1775 * @var: parameter to retrieve
1776 * @best: value to set
1777 * @dir: pointer to the direction (-1,0,1) or NULL
1778 *
1779 * Inside configuration space defined by PARAMS set PAR to the available value
1780 * nearest to VAL. Reduce configuration space accordingly.
1781 * This function cannot be called for SNDRV_PCM_HW_PARAM_ACCESS,
1782 * SNDRV_PCM_HW_PARAM_FORMAT, SNDRV_PCM_HW_PARAM_SUBFORMAT.
1783 * Return the value found.
1784 */
1785int snd_pcm_hw_param_near(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params,
1786 snd_pcm_hw_param_t var, unsigned int best, int *dir)
1787{
1788 struct snd_pcm_hw_params *save = NULL;
1789 int v;
1790 unsigned int saved_min;
1791 int last = 0;
1792 int min, max;
1793 int mindir, maxdir;
1794 int valdir = dir ? *dir : 0;
1795 /* FIXME */
1796 if (best > INT_MAX)
1797 best = INT_MAX;
1798 min = max = best;
1799 mindir = maxdir = valdir;
1800 if (maxdir > 0)
1801 maxdir = 0;
1802 else if (maxdir == 0)
1803 maxdir = -1;
1804 else {
1805 maxdir = 1;
1806 max--;
1807 }
1808 save = kmalloc(sizeof(*save), GFP_KERNEL);
1809 if (save == NULL)
1810 return -ENOMEM;
1811 *save = *params;
1812 saved_min = min;
1813 min = snd_pcm_hw_param_min(pcm, params, var, min, &mindir);
1814 if (min >= 0) {
1815 struct snd_pcm_hw_params *params1;
1816 if (max < 0)
1817 goto _end;
1818 if ((unsigned int)min == saved_min && mindir == valdir)
1819 goto _end;
1820 params1 = kmalloc(sizeof(*params1), GFP_KERNEL);
1821 if (params1 == NULL) {
1822 kfree(save);
1823 return -ENOMEM;
1824 }
1825 *params1 = *save;
1826 max = snd_pcm_hw_param_max(pcm, params1, var, max, &maxdir);
1827 if (max < 0) {
1828 kfree(params1);
1829 goto _end;
1830 }
1831 if (boundary_nearer(max, maxdir, best, valdir, min, mindir)) {
1832 *params = *params1;
1833 last = 1;
1834 }
1835 kfree(params1);
1836 } else {
1837 *params = *save;
1838 max = snd_pcm_hw_param_max(pcm, params, var, max, &maxdir);
1839 assert(max >= 0);
1840 last = 1;
1841 }
1842 _end:
1843 kfree(save);
1844 if (last)
1845 v = snd_pcm_hw_param_last(pcm, params, var, dir);
1846 else
1847 v = snd_pcm_hw_param_first(pcm, params, var, dir);
1848 assert(v >= 0);
1849 return v;
1850}
1851 1337
1852/** 1338/**
1853 * snd_pcm_hw_param_choose 1339 * snd_pcm_hw_param_choose
@@ -1859,39 +1345,32 @@ int snd_pcm_hw_param_near(struct snd_pcm_substream *pcm, struct snd_pcm_hw_param
1859 * first access, first format, first subformat, min channels, 1345 * first access, first format, first subformat, min channels,
1860 * min rate, min period time, max buffer size, min tick time 1346 * min rate, min period time, max buffer size, min tick time
1861 */ 1347 */
1862int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params) 1348int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm,
1863{ 1349 struct snd_pcm_hw_params *params)
1864 int err; 1350{
1865 1351 static int vars[] = {
1866 err = snd_pcm_hw_param_first(pcm, params, SNDRV_PCM_HW_PARAM_ACCESS, NULL); 1352 SNDRV_PCM_HW_PARAM_ACCESS,
1867 assert(err >= 0); 1353 SNDRV_PCM_HW_PARAM_FORMAT,
1868 1354 SNDRV_PCM_HW_PARAM_SUBFORMAT,
1869 err = snd_pcm_hw_param_first(pcm, params, SNDRV_PCM_HW_PARAM_FORMAT, NULL); 1355 SNDRV_PCM_HW_PARAM_CHANNELS,
1870 assert(err >= 0); 1356 SNDRV_PCM_HW_PARAM_RATE,
1871 1357 SNDRV_PCM_HW_PARAM_PERIOD_TIME,
1872 err = snd_pcm_hw_param_first(pcm, params, SNDRV_PCM_HW_PARAM_SUBFORMAT, NULL); 1358 SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
1873 assert(err >= 0); 1359 SNDRV_PCM_HW_PARAM_TICK_TIME,
1874 1360 -1
1875 err = snd_pcm_hw_param_first(pcm, params, SNDRV_PCM_HW_PARAM_CHANNELS, NULL); 1361 };
1876 assert(err >= 0); 1362 int err, *v;
1877
1878 err = snd_pcm_hw_param_first(pcm, params, SNDRV_PCM_HW_PARAM_RATE, NULL);
1879 assert(err >= 0);
1880
1881 err = snd_pcm_hw_param_first(pcm, params, SNDRV_PCM_HW_PARAM_PERIOD_TIME, NULL);
1882 assert(err >= 0);
1883
1884 err = snd_pcm_hw_param_last(pcm, params, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, NULL);
1885 assert(err >= 0);
1886
1887 err = snd_pcm_hw_param_first(pcm, params, SNDRV_PCM_HW_PARAM_TICK_TIME, NULL);
1888 assert(err >= 0);
1889 1363
1364 for (v = vars; *v != -1; v++) {
1365 if (*v != SNDRV_PCM_HW_PARAM_BUFFER_SIZE)
1366 err = snd_pcm_hw_param_first(pcm, params, *v, NULL);
1367 else
1368 err = snd_pcm_hw_param_last(pcm, params, *v, NULL);
1369 snd_assert(err >= 0, return err);
1370 }
1890 return 0; 1371 return 0;
1891} 1372}
1892 1373
1893#undef assert
1894
1895static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream, 1374static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream,
1896 void *arg) 1375 void *arg)
1897{ 1376{
@@ -1967,6 +1446,8 @@ int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream,
1967 return -ENXIO; 1446 return -ENXIO;
1968} 1447}
1969 1448
1449EXPORT_SYMBOL(snd_pcm_lib_ioctl);
1450
1970/* 1451/*
1971 * Conditions 1452 * Conditions
1972 */ 1453 */
@@ -2101,6 +1582,8 @@ void snd_pcm_period_elapsed(struct snd_pcm_substream *substream)
2101 kill_fasync(&runtime->fasync, SIGIO, POLL_IN); 1582 kill_fasync(&runtime->fasync, SIGIO, POLL_IN);
2102} 1583}
2103 1584
1585EXPORT_SYMBOL(snd_pcm_period_elapsed);
1586
2104static int snd_pcm_lib_write_transfer(struct snd_pcm_substream *substream, 1587static int snd_pcm_lib_write_transfer(struct snd_pcm_substream *substream,
2105 unsigned int hwoff, 1588 unsigned int hwoff,
2106 unsigned long data, unsigned int off, 1589 unsigned long data, unsigned int off,
@@ -2299,7 +1782,7 @@ snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream, const v
2299 if (runtime->status->state == SNDRV_PCM_STATE_OPEN) 1782 if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
2300 return -EBADFD; 1783 return -EBADFD;
2301 1784
2302 nonblock = !!(substream->ffile->f_flags & O_NONBLOCK); 1785 nonblock = !!(substream->f_flags & O_NONBLOCK);
2303 1786
2304 if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED && 1787 if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED &&
2305 runtime->channels > 1) 1788 runtime->channels > 1)
@@ -2308,6 +1791,8 @@ snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream, const v
2308 snd_pcm_lib_write_transfer); 1791 snd_pcm_lib_write_transfer);
2309} 1792}
2310 1793
1794EXPORT_SYMBOL(snd_pcm_lib_write);
1795
2311static int snd_pcm_lib_writev_transfer(struct snd_pcm_substream *substream, 1796static int snd_pcm_lib_writev_transfer(struct snd_pcm_substream *substream,
2312 unsigned int hwoff, 1797 unsigned int hwoff,
2313 unsigned long data, unsigned int off, 1798 unsigned long data, unsigned int off,
@@ -2362,7 +1847,7 @@ snd_pcm_sframes_t snd_pcm_lib_writev(struct snd_pcm_substream *substream,
2362 if (runtime->status->state == SNDRV_PCM_STATE_OPEN) 1847 if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
2363 return -EBADFD; 1848 return -EBADFD;
2364 1849
2365 nonblock = !!(substream->ffile->f_flags & O_NONBLOCK); 1850 nonblock = !!(substream->f_flags & O_NONBLOCK);
2366 1851
2367 if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) 1852 if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
2368 return -EINVAL; 1853 return -EINVAL;
@@ -2370,6 +1855,8 @@ snd_pcm_sframes_t snd_pcm_lib_writev(struct snd_pcm_substream *substream,
2370 nonblock, snd_pcm_lib_writev_transfer); 1855 nonblock, snd_pcm_lib_writev_transfer);
2371} 1856}
2372 1857
1858EXPORT_SYMBOL(snd_pcm_lib_writev);
1859
2373static int snd_pcm_lib_read_transfer(struct snd_pcm_substream *substream, 1860static int snd_pcm_lib_read_transfer(struct snd_pcm_substream *substream,
2374 unsigned int hwoff, 1861 unsigned int hwoff,
2375 unsigned long data, unsigned int off, 1862 unsigned long data, unsigned int off,
@@ -2572,12 +2059,14 @@ snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream, void __u
2572 if (runtime->status->state == SNDRV_PCM_STATE_OPEN) 2059 if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
2573 return -EBADFD; 2060 return -EBADFD;
2574 2061
2575 nonblock = !!(substream->ffile->f_flags & O_NONBLOCK); 2062 nonblock = !!(substream->f_flags & O_NONBLOCK);
2576 if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED) 2063 if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED)
2577 return -EINVAL; 2064 return -EINVAL;
2578 return snd_pcm_lib_read1(substream, (unsigned long)buf, size, nonblock, snd_pcm_lib_read_transfer); 2065 return snd_pcm_lib_read1(substream, (unsigned long)buf, size, nonblock, snd_pcm_lib_read_transfer);
2579} 2066}
2580 2067
2068EXPORT_SYMBOL(snd_pcm_lib_read);
2069
2581static int snd_pcm_lib_readv_transfer(struct snd_pcm_substream *substream, 2070static int snd_pcm_lib_readv_transfer(struct snd_pcm_substream *substream,
2582 unsigned int hwoff, 2071 unsigned int hwoff,
2583 unsigned long data, unsigned int off, 2072 unsigned long data, unsigned int off,
@@ -2629,58 +2118,10 @@ snd_pcm_sframes_t snd_pcm_lib_readv(struct snd_pcm_substream *substream,
2629 if (runtime->status->state == SNDRV_PCM_STATE_OPEN) 2118 if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
2630 return -EBADFD; 2119 return -EBADFD;
2631 2120
2632 nonblock = !!(substream->ffile->f_flags & O_NONBLOCK); 2121 nonblock = !!(substream->f_flags & O_NONBLOCK);
2633 if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) 2122 if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
2634 return -EINVAL; 2123 return -EINVAL;
2635 return snd_pcm_lib_read1(substream, (unsigned long)bufs, frames, nonblock, snd_pcm_lib_readv_transfer); 2124 return snd_pcm_lib_read1(substream, (unsigned long)bufs, frames, nonblock, snd_pcm_lib_readv_transfer);
2636} 2125}
2637 2126
2638/*
2639 * Exported symbols
2640 */
2641
2642EXPORT_SYMBOL(snd_interval_refine);
2643EXPORT_SYMBOL(snd_interval_list);
2644EXPORT_SYMBOL(snd_interval_ratnum);
2645EXPORT_SYMBOL(_snd_pcm_hw_params_any);
2646EXPORT_SYMBOL(_snd_pcm_hw_param_min);
2647EXPORT_SYMBOL(_snd_pcm_hw_param_set);
2648EXPORT_SYMBOL(_snd_pcm_hw_param_setempty);
2649EXPORT_SYMBOL(_snd_pcm_hw_param_setinteger);
2650EXPORT_SYMBOL(snd_pcm_hw_param_value_min);
2651EXPORT_SYMBOL(snd_pcm_hw_param_value_max);
2652EXPORT_SYMBOL(snd_pcm_hw_param_mask);
2653EXPORT_SYMBOL(snd_pcm_hw_param_first);
2654EXPORT_SYMBOL(snd_pcm_hw_param_last);
2655EXPORT_SYMBOL(snd_pcm_hw_param_near);
2656EXPORT_SYMBOL(snd_pcm_hw_param_set);
2657EXPORT_SYMBOL(snd_pcm_hw_refine);
2658EXPORT_SYMBOL(snd_pcm_hw_constraints_init);
2659EXPORT_SYMBOL(snd_pcm_hw_constraints_complete);
2660EXPORT_SYMBOL(snd_pcm_hw_constraint_list);
2661EXPORT_SYMBOL(snd_pcm_hw_constraint_step);
2662EXPORT_SYMBOL(snd_pcm_hw_constraint_ratnums);
2663EXPORT_SYMBOL(snd_pcm_hw_constraint_ratdens);
2664EXPORT_SYMBOL(snd_pcm_hw_constraint_msbits);
2665EXPORT_SYMBOL(snd_pcm_hw_constraint_minmax);
2666EXPORT_SYMBOL(snd_pcm_hw_constraint_integer);
2667EXPORT_SYMBOL(snd_pcm_hw_constraint_pow2);
2668EXPORT_SYMBOL(snd_pcm_hw_rule_add);
2669EXPORT_SYMBOL(snd_pcm_set_ops);
2670EXPORT_SYMBOL(snd_pcm_set_sync);
2671EXPORT_SYMBOL(snd_pcm_lib_ioctl);
2672EXPORT_SYMBOL(snd_pcm_stop);
2673EXPORT_SYMBOL(snd_pcm_period_elapsed);
2674EXPORT_SYMBOL(snd_pcm_lib_write);
2675EXPORT_SYMBOL(snd_pcm_lib_read);
2676EXPORT_SYMBOL(snd_pcm_lib_writev);
2677EXPORT_SYMBOL(snd_pcm_lib_readv); 2127EXPORT_SYMBOL(snd_pcm_lib_readv);
2678EXPORT_SYMBOL(snd_pcm_lib_buffer_bytes);
2679EXPORT_SYMBOL(snd_pcm_lib_period_bytes);
2680/* pcm_memory.c */
2681EXPORT_SYMBOL(snd_pcm_lib_preallocate_free_for_all);
2682EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages);
2683EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages_for_all);
2684EXPORT_SYMBOL(snd_pcm_sgbuf_ops_page);
2685EXPORT_SYMBOL(snd_pcm_lib_malloc_pages);
2686EXPORT_SYMBOL(snd_pcm_lib_free_pages);
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
index 428f8c169ee1..067d2056db9a 100644
--- a/sound/core/pcm_memory.c
+++ b/sound/core/pcm_memory.c
@@ -126,6 +126,8 @@ int snd_pcm_lib_preallocate_free_for_all(struct snd_pcm *pcm)
126 return 0; 126 return 0;
127} 127}
128 128
129EXPORT_SYMBOL(snd_pcm_lib_preallocate_free_for_all);
130
129#ifdef CONFIG_SND_VERBOSE_PROCFS 131#ifdef CONFIG_SND_VERBOSE_PROCFS
130/* 132/*
131 * read callback for prealloc proc file 133 * read callback for prealloc proc file
@@ -191,9 +193,7 @@ static inline void preallocate_info_init(struct snd_pcm_substream *substream)
191 struct snd_info_entry *entry; 193 struct snd_info_entry *entry;
192 194
193 if ((entry = snd_info_create_card_entry(substream->pcm->card, "prealloc", substream->proc_root)) != NULL) { 195 if ((entry = snd_info_create_card_entry(substream->pcm->card, "prealloc", substream->proc_root)) != NULL) {
194 entry->c.text.read_size = 64;
195 entry->c.text.read = snd_pcm_lib_preallocate_proc_read; 196 entry->c.text.read = snd_pcm_lib_preallocate_proc_read;
196 entry->c.text.write_size = 64;
197 entry->c.text.write = snd_pcm_lib_preallocate_proc_write; 197 entry->c.text.write = snd_pcm_lib_preallocate_proc_write;
198 entry->mode |= S_IWUSR; 198 entry->mode |= S_IWUSR;
199 entry->private_data = substream; 199 entry->private_data = substream;
@@ -253,6 +253,8 @@ int snd_pcm_lib_preallocate_pages(struct snd_pcm_substream *substream,
253 return snd_pcm_lib_preallocate_pages1(substream, size, max); 253 return snd_pcm_lib_preallocate_pages1(substream, size, max);
254} 254}
255 255
256EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages);
257
256/** 258/**
257 * snd_pcm_lib_preallocate_pages_for_all - pre-allocation for continous memory type (all substreams) 259 * snd_pcm_lib_preallocate_pages_for_all - pre-allocation for continous memory type (all substreams)
258 * @pcm: the pcm instance 260 * @pcm: the pcm instance
@@ -280,6 +282,8 @@ int snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm,
280 return 0; 282 return 0;
281} 283}
282 284
285EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages_for_all);
286
283/** 287/**
284 * snd_pcm_sgbuf_ops_page - get the page struct at the given offset 288 * snd_pcm_sgbuf_ops_page - get the page struct at the given offset
285 * @substream: the pcm substream instance 289 * @substream: the pcm substream instance
@@ -298,6 +302,8 @@ struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, unsigne
298 return sgbuf->page_table[idx]; 302 return sgbuf->page_table[idx];
299} 303}
300 304
305EXPORT_SYMBOL(snd_pcm_sgbuf_ops_page);
306
301/** 307/**
302 * snd_pcm_lib_malloc_pages - allocate the DMA buffer 308 * snd_pcm_lib_malloc_pages - allocate the DMA buffer
303 * @substream: the substream to allocate the DMA buffer to 309 * @substream: the substream to allocate the DMA buffer to
@@ -349,6 +355,8 @@ int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size)
349 return 1; /* area was changed */ 355 return 1; /* area was changed */
350} 356}
351 357
358EXPORT_SYMBOL(snd_pcm_lib_malloc_pages);
359
352/** 360/**
353 * snd_pcm_lib_free_pages - release the allocated DMA buffer. 361 * snd_pcm_lib_free_pages - release the allocated DMA buffer.
354 * @substream: the substream to release the DMA buffer 362 * @substream: the substream to release the DMA buffer
@@ -374,3 +382,5 @@ int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream)
374 snd_pcm_set_runtime_buffer(substream, NULL); 382 snd_pcm_set_runtime_buffer(substream, NULL);
375 return 0; 383 return 0;
376} 384}
385
386EXPORT_SYMBOL(snd_pcm_lib_free_pages);
diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c
index 593c77f4d181..0019c59a779d 100644
--- a/sound/core/pcm_misc.c
+++ b/sound/core/pcm_misc.c
@@ -207,6 +207,8 @@ int snd_pcm_format_signed(snd_pcm_format_t format)
207 return val; 207 return val;
208} 208}
209 209
210EXPORT_SYMBOL(snd_pcm_format_signed);
211
210/** 212/**
211 * snd_pcm_format_unsigned - Check the PCM format is unsigned linear 213 * snd_pcm_format_unsigned - Check the PCM format is unsigned linear
212 * @format: the format to check 214 * @format: the format to check
@@ -224,6 +226,8 @@ int snd_pcm_format_unsigned(snd_pcm_format_t format)
224 return !val; 226 return !val;
225} 227}
226 228
229EXPORT_SYMBOL(snd_pcm_format_unsigned);
230
227/** 231/**
228 * snd_pcm_format_linear - Check the PCM format is linear 232 * snd_pcm_format_linear - Check the PCM format is linear
229 * @format: the format to check 233 * @format: the format to check
@@ -235,6 +239,8 @@ int snd_pcm_format_linear(snd_pcm_format_t format)
235 return snd_pcm_format_signed(format) >= 0; 239 return snd_pcm_format_signed(format) >= 0;
236} 240}
237 241
242EXPORT_SYMBOL(snd_pcm_format_linear);
243
238/** 244/**
239 * snd_pcm_format_little_endian - Check the PCM format is little-endian 245 * snd_pcm_format_little_endian - Check the PCM format is little-endian
240 * @format: the format to check 246 * @format: the format to check
@@ -252,6 +258,8 @@ int snd_pcm_format_little_endian(snd_pcm_format_t format)
252 return val; 258 return val;
253} 259}
254 260
261EXPORT_SYMBOL(snd_pcm_format_little_endian);
262
255/** 263/**
256 * snd_pcm_format_big_endian - Check the PCM format is big-endian 264 * snd_pcm_format_big_endian - Check the PCM format is big-endian
257 * @format: the format to check 265 * @format: the format to check
@@ -269,6 +277,8 @@ int snd_pcm_format_big_endian(snd_pcm_format_t format)
269 return !val; 277 return !val;
270} 278}
271 279
280EXPORT_SYMBOL(snd_pcm_format_big_endian);
281
272/** 282/**
273 * snd_pcm_format_width - return the bit-width of the format 283 * snd_pcm_format_width - return the bit-width of the format
274 * @format: the format to check 284 * @format: the format to check
@@ -286,6 +296,8 @@ int snd_pcm_format_width(snd_pcm_format_t format)
286 return val; 296 return val;
287} 297}
288 298
299EXPORT_SYMBOL(snd_pcm_format_width);
300
289/** 301/**
290 * snd_pcm_format_physical_width - return the physical bit-width of the format 302 * snd_pcm_format_physical_width - return the physical bit-width of the format
291 * @format: the format to check 303 * @format: the format to check
@@ -303,6 +315,8 @@ int snd_pcm_format_physical_width(snd_pcm_format_t format)
303 return val; 315 return val;
304} 316}
305 317
318EXPORT_SYMBOL(snd_pcm_format_physical_width);
319
306/** 320/**
307 * snd_pcm_format_size - return the byte size of samples on the given format 321 * snd_pcm_format_size - return the byte size of samples on the given format
308 * @format: the format to check 322 * @format: the format to check
@@ -318,6 +332,8 @@ ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples)
318 return samples * phys_width / 8; 332 return samples * phys_width / 8;
319} 333}
320 334
335EXPORT_SYMBOL(snd_pcm_format_size);
336
321/** 337/**
322 * snd_pcm_format_silence_64 - return the silent data in 8 bytes array 338 * snd_pcm_format_silence_64 - return the silent data in 8 bytes array
323 * @format: the format to check 339 * @format: the format to check
@@ -333,6 +349,8 @@ const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format)
333 return pcm_formats[format].silence; 349 return pcm_formats[format].silence;
334} 350}
335 351
352EXPORT_SYMBOL(snd_pcm_format_silence_64);
353
336/** 354/**
337 * snd_pcm_format_set_silence - set the silence data on the buffer 355 * snd_pcm_format_set_silence - set the silence data on the buffer
338 * @format: the PCM format 356 * @format: the PCM format
@@ -402,6 +420,8 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int
402 return 0; 420 return 0;
403} 421}
404 422
423EXPORT_SYMBOL(snd_pcm_format_set_silence);
424
405/* [width][unsigned][bigendian] */ 425/* [width][unsigned][bigendian] */
406static int linear_formats[4][2][2] = { 426static int linear_formats[4][2][2] = {
407 {{ SNDRV_PCM_FORMAT_S8, SNDRV_PCM_FORMAT_S8}, 427 {{ SNDRV_PCM_FORMAT_S8, SNDRV_PCM_FORMAT_S8},
@@ -432,6 +452,8 @@ snd_pcm_format_t snd_pcm_build_linear_format(int width, int unsignd, int big_end
432 return linear_formats[width][!!unsignd][!!big_endian]; 452 return linear_formats[width][!!unsignd][!!big_endian];
433} 453}
434 454
455EXPORT_SYMBOL(snd_pcm_build_linear_format);
456
435/** 457/**
436 * snd_pcm_limit_hw_rates - determine rate_min/rate_max fields 458 * snd_pcm_limit_hw_rates - determine rate_min/rate_max fields
437 * @runtime: the runtime instance 459 * @runtime: the runtime instance
@@ -463,3 +485,5 @@ int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime)
463 } 485 }
464 return 0; 486 return 0;
465} 487}
488
489EXPORT_SYMBOL(snd_pcm_limit_hw_rates);
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 0860c5a84502..439f047929e1 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -71,8 +71,9 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream);
71 */ 71 */
72 72
73DEFINE_RWLOCK(snd_pcm_link_rwlock); 73DEFINE_RWLOCK(snd_pcm_link_rwlock);
74static DECLARE_RWSEM(snd_pcm_link_rwsem); 74EXPORT_SYMBOL(snd_pcm_link_rwlock);
75 75
76static DECLARE_RWSEM(snd_pcm_link_rwsem);
76 77
77static inline mm_segment_t snd_enter_user(void) 78static inline mm_segment_t snd_enter_user(void)
78{ 79{
@@ -319,6 +320,8 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
319 return 0; 320 return 0;
320} 321}
321 322
323EXPORT_SYMBOL(snd_pcm_hw_refine);
324
322static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream, 325static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream,
323 struct snd_pcm_hw_params __user * _params) 326 struct snd_pcm_hw_params __user * _params)
324{ 327{
@@ -369,7 +372,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
369#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) 372#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
370 if (!substream->oss.oss) 373 if (!substream->oss.oss)
371#endif 374#endif
372 if (atomic_read(&runtime->mmap_count)) 375 if (atomic_read(&substream->mmap_count))
373 return -EBADFD; 376 return -EBADFD;
374 377
375 params->rmask = ~0U; 378 params->rmask = ~0U;
@@ -482,7 +485,7 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream)
482 return -EBADFD; 485 return -EBADFD;
483 } 486 }
484 snd_pcm_stream_unlock_irq(substream); 487 snd_pcm_stream_unlock_irq(substream);
485 if (atomic_read(&runtime->mmap_count)) 488 if (atomic_read(&substream->mmap_count))
486 return -EBADFD; 489 return -EBADFD;
487 if (substream->ops->hw_free) 490 if (substream->ops->hw_free)
488 result = substream->ops->hw_free(substream); 491 result = substream->ops->hw_free(substream);
@@ -936,6 +939,8 @@ int snd_pcm_stop(struct snd_pcm_substream *substream, int state)
936 return snd_pcm_action(&snd_pcm_action_stop, substream, state); 939 return snd_pcm_action(&snd_pcm_action_stop, substream, state);
937} 940}
938 941
942EXPORT_SYMBOL(snd_pcm_stop);
943
939/** 944/**
940 * snd_pcm_drain_done 945 * snd_pcm_drain_done
941 * @substream: the PCM substream 946 * @substream: the PCM substream
@@ -1085,6 +1090,8 @@ int snd_pcm_suspend(struct snd_pcm_substream *substream)
1085 return err; 1090 return err;
1086} 1091}
1087 1092
1093EXPORT_SYMBOL(snd_pcm_suspend);
1094
1088/** 1095/**
1089 * snd_pcm_suspend_all 1096 * snd_pcm_suspend_all
1090 * @pcm: the PCM instance 1097 * @pcm: the PCM instance
@@ -1114,6 +1121,8 @@ int snd_pcm_suspend_all(struct snd_pcm *pcm)
1114 return 0; 1121 return 0;
1115} 1122}
1116 1123
1124EXPORT_SYMBOL(snd_pcm_suspend_all);
1125
1117/* resume */ 1126/* resume */
1118 1127
1119static int snd_pcm_pre_resume(struct snd_pcm_substream *substream, int state) 1128static int snd_pcm_pre_resume(struct snd_pcm_substream *substream, int state)
@@ -1275,13 +1284,16 @@ static int snd_pcm_reset(struct snd_pcm_substream *substream)
1275/* 1284/*
1276 * prepare ioctl 1285 * prepare ioctl
1277 */ 1286 */
1278static int snd_pcm_pre_prepare(struct snd_pcm_substream *substream, int state) 1287/* we use the second argument for updating f_flags */
1288static int snd_pcm_pre_prepare(struct snd_pcm_substream *substream,
1289 int f_flags)
1279{ 1290{
1280 struct snd_pcm_runtime *runtime = substream->runtime; 1291 struct snd_pcm_runtime *runtime = substream->runtime;
1281 if (runtime->status->state == SNDRV_PCM_STATE_OPEN) 1292 if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
1282 return -EBADFD; 1293 return -EBADFD;
1283 if (snd_pcm_running(substream)) 1294 if (snd_pcm_running(substream))
1284 return -EBUSY; 1295 return -EBUSY;
1296 substream->f_flags = f_flags;
1285 return 0; 1297 return 0;
1286} 1298}
1287 1299
@@ -1310,17 +1322,26 @@ static struct action_ops snd_pcm_action_prepare = {
1310/** 1322/**
1311 * snd_pcm_prepare 1323 * snd_pcm_prepare
1312 * @substream: the PCM substream instance 1324 * @substream: the PCM substream instance
1325 * @file: file to refer f_flags
1313 * 1326 *
1314 * Prepare the PCM substream to be triggerable. 1327 * Prepare the PCM substream to be triggerable.
1315 */ 1328 */
1316static int snd_pcm_prepare(struct snd_pcm_substream *substream) 1329static int snd_pcm_prepare(struct snd_pcm_substream *substream,
1330 struct file *file)
1317{ 1331{
1318 int res; 1332 int res;
1319 struct snd_card *card = substream->pcm->card; 1333 struct snd_card *card = substream->pcm->card;
1334 int f_flags;
1335
1336 if (file)
1337 f_flags = file->f_flags;
1338 else
1339 f_flags = substream->f_flags;
1320 1340
1321 snd_power_lock(card); 1341 snd_power_lock(card);
1322 if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0) 1342 if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0)
1323 res = snd_pcm_action_nonatomic(&snd_pcm_action_prepare, substream, 0); 1343 res = snd_pcm_action_nonatomic(&snd_pcm_action_prepare,
1344 substream, f_flags);
1324 snd_power_unlock(card); 1345 snd_power_unlock(card);
1325 return res; 1346 return res;
1326} 1347}
@@ -1331,7 +1352,7 @@ static int snd_pcm_prepare(struct snd_pcm_substream *substream)
1331 1352
1332static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, int state) 1353static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, int state)
1333{ 1354{
1334 if (substream->ffile->f_flags & O_NONBLOCK) 1355 if (substream->f_flags & O_NONBLOCK)
1335 return -EAGAIN; 1356 return -EAGAIN;
1336 substream->runtime->trigger_master = substream; 1357 substream->runtime->trigger_master = substream;
1337 return 0; 1358 return 0;
@@ -1448,8 +1469,6 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream)
1448 } 1469 }
1449 } 1470 }
1450 up_read(&snd_pcm_link_rwsem); 1471 up_read(&snd_pcm_link_rwsem);
1451 if (! num_drecs)
1452 goto _error;
1453 1472
1454 snd_pcm_stream_lock_irq(substream); 1473 snd_pcm_stream_lock_irq(substream);
1455 /* resume pause */ 1474 /* resume pause */
@@ -2006,6 +2025,10 @@ static void pcm_release_private(struct snd_pcm_substream *substream)
2006 2025
2007void snd_pcm_release_substream(struct snd_pcm_substream *substream) 2026void snd_pcm_release_substream(struct snd_pcm_substream *substream)
2008{ 2027{
2028 substream->ref_count--;
2029 if (substream->ref_count > 0)
2030 return;
2031
2009 snd_pcm_drop(substream); 2032 snd_pcm_drop(substream);
2010 if (substream->hw_opened) { 2033 if (substream->hw_opened) {
2011 if (substream->ops->hw_free != NULL) 2034 if (substream->ops->hw_free != NULL)
@@ -2020,6 +2043,8 @@ void snd_pcm_release_substream(struct snd_pcm_substream *substream)
2020 snd_pcm_detach_substream(substream); 2043 snd_pcm_detach_substream(substream);
2021} 2044}
2022 2045
2046EXPORT_SYMBOL(snd_pcm_release_substream);
2047
2023int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, 2048int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
2024 struct file *file, 2049 struct file *file,
2025 struct snd_pcm_substream **rsubstream) 2050 struct snd_pcm_substream **rsubstream)
@@ -2030,6 +2055,11 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
2030 err = snd_pcm_attach_substream(pcm, stream, file, &substream); 2055 err = snd_pcm_attach_substream(pcm, stream, file, &substream);
2031 if (err < 0) 2056 if (err < 0)
2032 return err; 2057 return err;
2058 if (substream->ref_count > 1) {
2059 *rsubstream = substream;
2060 return 0;
2061 }
2062
2033 substream->no_mmap_ctrl = 0; 2063 substream->no_mmap_ctrl = 0;
2034 err = snd_pcm_hw_constraints_init(substream); 2064 err = snd_pcm_hw_constraints_init(substream);
2035 if (err < 0) { 2065 if (err < 0) {
@@ -2056,6 +2086,8 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
2056 return err; 2086 return err;
2057} 2087}
2058 2088
2089EXPORT_SYMBOL(snd_pcm_open_substream);
2090
2059static int snd_pcm_open_file(struct file *file, 2091static int snd_pcm_open_file(struct file *file,
2060 struct snd_pcm *pcm, 2092 struct snd_pcm *pcm,
2061 int stream, 2093 int stream,
@@ -2073,17 +2105,20 @@ static int snd_pcm_open_file(struct file *file,
2073 if (err < 0) 2105 if (err < 0)
2074 return err; 2106 return err;
2075 2107
2076 pcm_file = kzalloc(sizeof(*pcm_file), GFP_KERNEL); 2108 if (substream->ref_count > 1)
2077 if (pcm_file == NULL) { 2109 pcm_file = substream->file;
2078 snd_pcm_release_substream(substream); 2110 else {
2079 return -ENOMEM; 2111 pcm_file = kzalloc(sizeof(*pcm_file), GFP_KERNEL);
2112 if (pcm_file == NULL) {
2113 snd_pcm_release_substream(substream);
2114 return -ENOMEM;
2115 }
2116 str = substream->pstr;
2117 substream->file = pcm_file;
2118 substream->pcm_release = pcm_release_private;
2119 pcm_file->substream = substream;
2120 snd_pcm_add_file(str, pcm_file);
2080 } 2121 }
2081 str = substream->pstr;
2082 substream->file = pcm_file;
2083 substream->pcm_release = pcm_release_private;
2084 pcm_file->substream = substream;
2085 snd_pcm_add_file(str, pcm_file);
2086
2087 file->private_data = pcm_file; 2122 file->private_data = pcm_file;
2088 *rpcm_file = pcm_file; 2123 *rpcm_file = pcm_file;
2089 return 0; 2124 return 0;
@@ -2170,7 +2205,6 @@ static int snd_pcm_release(struct inode *inode, struct file *file)
2170 pcm_file = file->private_data; 2205 pcm_file = file->private_data;
2171 substream = pcm_file->substream; 2206 substream = pcm_file->substream;
2172 snd_assert(substream != NULL, return -ENXIO); 2207 snd_assert(substream != NULL, return -ENXIO);
2173 snd_assert(!atomic_read(&substream->runtime->mmap_count), );
2174 pcm = substream->pcm; 2208 pcm = substream->pcm;
2175 fasync_helper(-1, file, 0, &substream->runtime->fasync); 2209 fasync_helper(-1, file, 0, &substream->runtime->fasync);
2176 mutex_lock(&pcm->open_mutex); 2210 mutex_lock(&pcm->open_mutex);
@@ -2493,7 +2527,8 @@ static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream,
2493 return 0; 2527 return 0;
2494} 2528}
2495 2529
2496static int snd_pcm_common_ioctl1(struct snd_pcm_substream *substream, 2530static int snd_pcm_common_ioctl1(struct file *file,
2531 struct snd_pcm_substream *substream,
2497 unsigned int cmd, void __user *arg) 2532 unsigned int cmd, void __user *arg)
2498{ 2533{
2499 snd_assert(substream != NULL, return -ENXIO); 2534 snd_assert(substream != NULL, return -ENXIO);
@@ -2518,7 +2553,7 @@ static int snd_pcm_common_ioctl1(struct snd_pcm_substream *substream,
2518 case SNDRV_PCM_IOCTL_CHANNEL_INFO: 2553 case SNDRV_PCM_IOCTL_CHANNEL_INFO:
2519 return snd_pcm_channel_info_user(substream, arg); 2554 return snd_pcm_channel_info_user(substream, arg);
2520 case SNDRV_PCM_IOCTL_PREPARE: 2555 case SNDRV_PCM_IOCTL_PREPARE:
2521 return snd_pcm_prepare(substream); 2556 return snd_pcm_prepare(substream, file);
2522 case SNDRV_PCM_IOCTL_RESET: 2557 case SNDRV_PCM_IOCTL_RESET:
2523 return snd_pcm_reset(substream); 2558 return snd_pcm_reset(substream);
2524 case SNDRV_PCM_IOCTL_START: 2559 case SNDRV_PCM_IOCTL_START:
@@ -2560,7 +2595,8 @@ static int snd_pcm_common_ioctl1(struct snd_pcm_substream *substream,
2560 return -ENOTTY; 2595 return -ENOTTY;
2561} 2596}
2562 2597
2563static int snd_pcm_playback_ioctl1(struct snd_pcm_substream *substream, 2598static int snd_pcm_playback_ioctl1(struct file *file,
2599 struct snd_pcm_substream *substream,
2564 unsigned int cmd, void __user *arg) 2600 unsigned int cmd, void __user *arg)
2565{ 2601{
2566 snd_assert(substream != NULL, return -ENXIO); 2602 snd_assert(substream != NULL, return -ENXIO);
@@ -2636,10 +2672,11 @@ static int snd_pcm_playback_ioctl1(struct snd_pcm_substream *substream,
2636 return result < 0 ? result : 0; 2672 return result < 0 ? result : 0;
2637 } 2673 }
2638 } 2674 }
2639 return snd_pcm_common_ioctl1(substream, cmd, arg); 2675 return snd_pcm_common_ioctl1(file, substream, cmd, arg);
2640} 2676}
2641 2677
2642static int snd_pcm_capture_ioctl1(struct snd_pcm_substream *substream, 2678static int snd_pcm_capture_ioctl1(struct file *file,
2679 struct snd_pcm_substream *substream,
2643 unsigned int cmd, void __user *arg) 2680 unsigned int cmd, void __user *arg)
2644{ 2681{
2645 snd_assert(substream != NULL, return -ENXIO); 2682 snd_assert(substream != NULL, return -ENXIO);
@@ -2715,7 +2752,7 @@ static int snd_pcm_capture_ioctl1(struct snd_pcm_substream *substream,
2715 return result < 0 ? result : 0; 2752 return result < 0 ? result : 0;
2716 } 2753 }
2717 } 2754 }
2718 return snd_pcm_common_ioctl1(substream, cmd, arg); 2755 return snd_pcm_common_ioctl1(file, substream, cmd, arg);
2719} 2756}
2720 2757
2721static long snd_pcm_playback_ioctl(struct file *file, unsigned int cmd, 2758static long snd_pcm_playback_ioctl(struct file *file, unsigned int cmd,
@@ -2728,7 +2765,8 @@ static long snd_pcm_playback_ioctl(struct file *file, unsigned int cmd,
2728 if (((cmd >> 8) & 0xff) != 'A') 2765 if (((cmd >> 8) & 0xff) != 'A')
2729 return -ENOTTY; 2766 return -ENOTTY;
2730 2767
2731 return snd_pcm_playback_ioctl1(pcm_file->substream, cmd, (void __user *)arg); 2768 return snd_pcm_playback_ioctl1(file, pcm_file->substream, cmd,
2769 (void __user *)arg);
2732} 2770}
2733 2771
2734static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd, 2772static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd,
@@ -2741,7 +2779,8 @@ static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd,
2741 if (((cmd >> 8) & 0xff) != 'A') 2779 if (((cmd >> 8) & 0xff) != 'A')
2742 return -ENOTTY; 2780 return -ENOTTY;
2743 2781
2744 return snd_pcm_capture_ioctl1(pcm_file->substream, cmd, (void __user *)arg); 2782 return snd_pcm_capture_ioctl1(file, pcm_file->substream, cmd,
2783 (void __user *)arg);
2745} 2784}
2746 2785
2747int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, 2786int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream,
@@ -2753,12 +2792,12 @@ int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream,
2753 fs = snd_enter_user(); 2792 fs = snd_enter_user();
2754 switch (substream->stream) { 2793 switch (substream->stream) {
2755 case SNDRV_PCM_STREAM_PLAYBACK: 2794 case SNDRV_PCM_STREAM_PLAYBACK:
2756 result = snd_pcm_playback_ioctl1(substream, 2795 result = snd_pcm_playback_ioctl1(NULL, substream, cmd,
2757 cmd, (void __user *)arg); 2796 (void __user *)arg);
2758 break; 2797 break;
2759 case SNDRV_PCM_STREAM_CAPTURE: 2798 case SNDRV_PCM_STREAM_CAPTURE:
2760 result = snd_pcm_capture_ioctl1(substream, 2799 result = snd_pcm_capture_ioctl1(NULL, substream, cmd,
2761 cmd, (void __user *)arg); 2800 (void __user *)arg);
2762 break; 2801 break;
2763 default: 2802 default:
2764 result = -EINVAL; 2803 result = -EINVAL;
@@ -2768,6 +2807,8 @@ int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream,
2768 return result; 2807 return result;
2769} 2808}
2770 2809
2810EXPORT_SYMBOL(snd_pcm_kernel_ioctl);
2811
2771static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count, 2812static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count,
2772 loff_t * offset) 2813 loff_t * offset)
2773{ 2814{
@@ -3134,7 +3175,7 @@ static int snd_pcm_default_mmap(struct snd_pcm_substream *substream,
3134 area->vm_ops = &snd_pcm_vm_ops_data; 3175 area->vm_ops = &snd_pcm_vm_ops_data;
3135 area->vm_private_data = substream; 3176 area->vm_private_data = substream;
3136 area->vm_flags |= VM_RESERVED; 3177 area->vm_flags |= VM_RESERVED;
3137 atomic_inc(&substream->runtime->mmap_count); 3178 atomic_inc(&substream->mmap_count);
3138 return 0; 3179 return 0;
3139} 3180}
3140 3181
@@ -3166,9 +3207,11 @@ int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream,
3166 (substream->runtime->dma_addr + offset) >> PAGE_SHIFT, 3207 (substream->runtime->dma_addr + offset) >> PAGE_SHIFT,
3167 size, area->vm_page_prot)) 3208 size, area->vm_page_prot))
3168 return -EAGAIN; 3209 return -EAGAIN;
3169 atomic_inc(&substream->runtime->mmap_count); 3210 atomic_inc(&substream->mmap_count);
3170 return 0; 3211 return 0;
3171} 3212}
3213
3214EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem);
3172#endif /* SNDRV_PCM_INFO_MMAP */ 3215#endif /* SNDRV_PCM_INFO_MMAP */
3173 3216
3174/* 3217/*
@@ -3212,6 +3255,8 @@ int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file,
3212 return snd_pcm_default_mmap(substream, area); 3255 return snd_pcm_default_mmap(substream, area);
3213} 3256}
3214 3257
3258EXPORT_SYMBOL(snd_pcm_mmap_data);
3259
3215static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area) 3260static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area)
3216{ 3261{
3217 struct snd_pcm_file * pcm_file; 3262 struct snd_pcm_file * pcm_file;
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 87b47c9564f7..8c15c66eb4aa 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -43,7 +43,7 @@ MODULE_DESCRIPTION("Midlevel RawMidi code for ALSA.");
43MODULE_LICENSE("GPL"); 43MODULE_LICENSE("GPL");
44 44
45#ifdef CONFIG_SND_OSSEMUL 45#ifdef CONFIG_SND_OSSEMUL
46static int midi_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 0}; 46static int midi_map[SNDRV_CARDS];
47static int amidi_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1}; 47static int amidi_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1};
48module_param_array(midi_map, int, NULL, 0444); 48module_param_array(midi_map, int, NULL, 0444);
49MODULE_PARM_DESC(midi_map, "Raw MIDI device number assigned to 1st OSS device."); 49MODULE_PARM_DESC(midi_map, "Raw MIDI device number assigned to 1st OSS device.");
@@ -1561,7 +1561,6 @@ static int snd_rawmidi_dev_register(struct snd_device *device)
1561 entry = snd_info_create_card_entry(rmidi->card, name, rmidi->card->proc_root); 1561 entry = snd_info_create_card_entry(rmidi->card, name, rmidi->card->proc_root);
1562 if (entry) { 1562 if (entry) {
1563 entry->private_data = rmidi; 1563 entry->private_data = rmidi;
1564 entry->c.text.read_size = 1024;
1565 entry->c.text.read = snd_rawmidi_proc_info_read; 1564 entry->c.text.read = snd_rawmidi_proc_info_read;
1566 if (snd_info_register(entry) < 0) { 1565 if (snd_info_register(entry) < 0) {
1567 snd_info_free_entry(entry); 1566 snd_info_free_entry(entry);
diff --git a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c
index b9919785180b..e7234135641c 100644
--- a/sound/core/seq/oss/seq_oss.c
+++ b/sound/core/seq/oss/seq_oss.c
@@ -291,7 +291,6 @@ register_proc(void)
291 291
292 entry->content = SNDRV_INFO_CONTENT_TEXT; 292 entry->content = SNDRV_INFO_CONTENT_TEXT;
293 entry->private_data = NULL; 293 entry->private_data = NULL;
294 entry->c.text.read_size = 1024;
295 entry->c.text.read = info_read; 294 entry->c.text.read = info_read;
296 if (snd_info_register(entry) < 0) { 295 if (snd_info_register(entry) < 0) {
297 snd_info_free_entry(entry); 296 snd_info_free_entry(entry);
diff --git a/sound/core/seq/seq.c b/sound/core/seq/seq.c
index 20f954bc7aa0..2f0d8773ac6b 100644
--- a/sound/core/seq/seq.c
+++ b/sound/core/seq/seq.c
@@ -129,25 +129,3 @@ static void __exit alsa_seq_exit(void)
129 129
130module_init(alsa_seq_init) 130module_init(alsa_seq_init)
131module_exit(alsa_seq_exit) 131module_exit(alsa_seq_exit)
132
133 /* seq_clientmgr.c */
134EXPORT_SYMBOL(snd_seq_create_kernel_client);
135EXPORT_SYMBOL(snd_seq_delete_kernel_client);
136EXPORT_SYMBOL(snd_seq_kernel_client_enqueue);
137EXPORT_SYMBOL(snd_seq_kernel_client_enqueue_blocking);
138EXPORT_SYMBOL(snd_seq_kernel_client_dispatch);
139EXPORT_SYMBOL(snd_seq_kernel_client_ctl);
140EXPORT_SYMBOL(snd_seq_kernel_client_write_poll);
141EXPORT_SYMBOL(snd_seq_set_queue_tempo);
142 /* seq_memory.c */
143EXPORT_SYMBOL(snd_seq_expand_var_event);
144EXPORT_SYMBOL(snd_seq_dump_var_event);
145 /* seq_ports.c */
146EXPORT_SYMBOL(snd_seq_event_port_attach);
147EXPORT_SYMBOL(snd_seq_event_port_detach);
148 /* seq_lock.c */
149#if defined(CONFIG_SMP) || defined(CONFIG_SND_DEBUG)
150/*EXPORT_SYMBOL(snd_seq_sleep_in_lock);*/
151/*EXPORT_SYMBOL(snd_seq_sleep_timeout_in_lock);*/
152EXPORT_SYMBOL(snd_use_lock_sync_helper);
153#endif
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index bb15d9ee8842..532a660df51d 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -1714,6 +1714,8 @@ int snd_seq_set_queue_tempo(int client, struct snd_seq_queue_tempo *tempo)
1714 return snd_seq_queue_timer_set_tempo(tempo->queue, client, tempo); 1714 return snd_seq_queue_timer_set_tempo(tempo->queue, client, tempo);
1715} 1715}
1716 1716
1717EXPORT_SYMBOL(snd_seq_set_queue_tempo);
1718
1717static int snd_seq_ioctl_set_queue_tempo(struct snd_seq_client *client, 1719static int snd_seq_ioctl_set_queue_tempo(struct snd_seq_client *client,
1718 void __user *arg) 1720 void __user *arg)
1719{ 1721{
@@ -2264,6 +2266,8 @@ int snd_seq_create_kernel_client(struct snd_card *card, int client_index,
2264 return client->number; 2266 return client->number;
2265} 2267}
2266 2268
2269EXPORT_SYMBOL(snd_seq_create_kernel_client);
2270
2267/* exported to kernel modules */ 2271/* exported to kernel modules */
2268int snd_seq_delete_kernel_client(int client) 2272int snd_seq_delete_kernel_client(int client)
2269{ 2273{
@@ -2280,6 +2284,7 @@ int snd_seq_delete_kernel_client(int client)
2280 return 0; 2284 return 0;
2281} 2285}
2282 2286
2287EXPORT_SYMBOL(snd_seq_delete_kernel_client);
2283 2288
2284/* skeleton to enqueue event, called from snd_seq_kernel_client_enqueue 2289/* skeleton to enqueue event, called from snd_seq_kernel_client_enqueue
2285 * and snd_seq_kernel_client_enqueue_blocking 2290 * and snd_seq_kernel_client_enqueue_blocking
@@ -2328,6 +2333,8 @@ int snd_seq_kernel_client_enqueue(int client, struct snd_seq_event * ev,
2328 return kernel_client_enqueue(client, ev, NULL, 0, atomic, hop); 2333 return kernel_client_enqueue(client, ev, NULL, 0, atomic, hop);
2329} 2334}
2330 2335
2336EXPORT_SYMBOL(snd_seq_kernel_client_enqueue);
2337
2331/* 2338/*
2332 * exported, called by kernel clients to enqueue events (with blocking) 2339 * exported, called by kernel clients to enqueue events (with blocking)
2333 * 2340 *
@@ -2340,6 +2347,7 @@ int snd_seq_kernel_client_enqueue_blocking(int client, struct snd_seq_event * ev
2340 return kernel_client_enqueue(client, ev, file, 1, atomic, hop); 2347 return kernel_client_enqueue(client, ev, file, 1, atomic, hop);
2341} 2348}
2342 2349
2350EXPORT_SYMBOL(snd_seq_kernel_client_enqueue_blocking);
2343 2351
2344/* 2352/*
2345 * exported, called by kernel clients to dispatch events directly to other 2353 * exported, called by kernel clients to dispatch events directly to other
@@ -2376,6 +2384,7 @@ int snd_seq_kernel_client_dispatch(int client, struct snd_seq_event * ev,
2376 return result; 2384 return result;
2377} 2385}
2378 2386
2387EXPORT_SYMBOL(snd_seq_kernel_client_dispatch);
2379 2388
2380/* 2389/*
2381 * exported, called by kernel clients to perform same functions as with 2390 * exported, called by kernel clients to perform same functions as with
@@ -2396,6 +2405,7 @@ int snd_seq_kernel_client_ctl(int clientid, unsigned int cmd, void *arg)
2396 return result; 2405 return result;
2397} 2406}
2398 2407
2408EXPORT_SYMBOL(snd_seq_kernel_client_ctl);
2399 2409
2400/* exported (for OSS emulator) */ 2410/* exported (for OSS emulator) */
2401int snd_seq_kernel_client_write_poll(int clientid, struct file *file, poll_table *wait) 2411int snd_seq_kernel_client_write_poll(int clientid, struct file *file, poll_table *wait)
@@ -2413,6 +2423,8 @@ int snd_seq_kernel_client_write_poll(int clientid, struct file *file, poll_table
2413 return 0; 2423 return 0;
2414} 2424}
2415 2425
2426EXPORT_SYMBOL(snd_seq_kernel_client_write_poll);
2427
2416/*---------------------------------------------------------------------------*/ 2428/*---------------------------------------------------------------------------*/
2417 2429
2418#ifdef CONFIG_PROC_FS 2430#ifdef CONFIG_PROC_FS
diff --git a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c
index d9a3e5a18d6a..d812dc886360 100644
--- a/sound/core/seq/seq_device.c
+++ b/sound/core/seq/seq_device.c
@@ -80,7 +80,7 @@ static LIST_HEAD(opslist);
80static int num_ops; 80static int num_ops;
81static DEFINE_MUTEX(ops_mutex); 81static DEFINE_MUTEX(ops_mutex);
82#ifdef CONFIG_PROC_FS 82#ifdef CONFIG_PROC_FS
83static struct snd_info_entry *info_entry = NULL; 83static struct snd_info_entry *info_entry;
84#endif 84#endif
85 85
86/* 86/*
@@ -555,7 +555,6 @@ static int __init alsa_seq_device_init(void)
555 if (info_entry == NULL) 555 if (info_entry == NULL)
556 return -ENOMEM; 556 return -ENOMEM;
557 info_entry->content = SNDRV_INFO_CONTENT_TEXT; 557 info_entry->content = SNDRV_INFO_CONTENT_TEXT;
558 info_entry->c.text.read_size = 2048;
559 info_entry->c.text.read = snd_seq_device_info; 558 info_entry->c.text.read = snd_seq_device_info;
560 if (snd_info_register(info_entry) < 0) { 559 if (snd_info_register(info_entry) < 0) {
561 snd_info_free_entry(info_entry); 560 snd_info_free_entry(info_entry);
diff --git a/sound/core/seq/seq_dummy.c b/sound/core/seq/seq_dummy.c
index 2a283a59ea4d..e55488d1237c 100644
--- a/sound/core/seq/seq_dummy.c
+++ b/sound/core/seq/seq_dummy.c
@@ -66,7 +66,7 @@ MODULE_LICENSE("GPL");
66MODULE_ALIAS("snd-seq-client-" __stringify(SNDRV_SEQ_CLIENT_DUMMY)); 66MODULE_ALIAS("snd-seq-client-" __stringify(SNDRV_SEQ_CLIENT_DUMMY));
67 67
68static int ports = 1; 68static int ports = 1;
69static int duplex = 0; 69static int duplex;
70 70
71module_param(ports, int, 0444); 71module_param(ports, int, 0444);
72MODULE_PARM_DESC(ports, "number of ports to be created"); 72MODULE_PARM_DESC(ports, "number of ports to be created");
@@ -171,7 +171,9 @@ create_port(int idx, int type)
171 pinfo.capability |= SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE; 171 pinfo.capability |= SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE;
172 if (duplex) 172 if (duplex)
173 pinfo.capability |= SNDRV_SEQ_PORT_CAP_DUPLEX; 173 pinfo.capability |= SNDRV_SEQ_PORT_CAP_DUPLEX;
174 pinfo.type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC; 174 pinfo.type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC
175 | SNDRV_SEQ_PORT_TYPE_SOFTWARE
176 | SNDRV_SEQ_PORT_TYPE_PORT;
175 memset(&pcb, 0, sizeof(pcb)); 177 memset(&pcb, 0, sizeof(pcb));
176 pcb.owner = THIS_MODULE; 178 pcb.owner = THIS_MODULE;
177 pcb.unuse = dummy_unuse; 179 pcb.unuse = dummy_unuse;
diff --git a/sound/core/seq/seq_info.c b/sound/core/seq/seq_info.c
index acce21afdaa4..142e9e6882c9 100644
--- a/sound/core/seq/seq_info.c
+++ b/sound/core/seq/seq_info.c
@@ -34,8 +34,8 @@ static struct snd_info_entry *timer_entry;
34 34
35 35
36static struct snd_info_entry * __init 36static struct snd_info_entry * __init
37create_info_entry(char *name, int size, void (*read)(struct snd_info_entry *, 37create_info_entry(char *name, void (*read)(struct snd_info_entry *,
38 struct snd_info_buffer *)) 38 struct snd_info_buffer *))
39{ 39{
40 struct snd_info_entry *entry; 40 struct snd_info_entry *entry;
41 41
@@ -43,7 +43,6 @@ create_info_entry(char *name, int size, void (*read)(struct snd_info_entry *,
43 if (entry == NULL) 43 if (entry == NULL)
44 return NULL; 44 return NULL;
45 entry->content = SNDRV_INFO_CONTENT_TEXT; 45 entry->content = SNDRV_INFO_CONTENT_TEXT;
46 entry->c.text.read_size = size;
47 entry->c.text.read = read; 46 entry->c.text.read = read;
48 if (snd_info_register(entry) < 0) { 47 if (snd_info_register(entry) < 0) {
49 snd_info_free_entry(entry); 48 snd_info_free_entry(entry);
@@ -55,11 +54,11 @@ create_info_entry(char *name, int size, void (*read)(struct snd_info_entry *,
55/* create all our /proc entries */ 54/* create all our /proc entries */
56int __init snd_seq_info_init(void) 55int __init snd_seq_info_init(void)
57{ 56{
58 queues_entry = create_info_entry("queues", 512 + (256 * SNDRV_SEQ_MAX_QUEUES), 57 queues_entry = create_info_entry("queues",
59 snd_seq_info_queues_read); 58 snd_seq_info_queues_read);
60 clients_entry = create_info_entry("clients", 512 + (256 * SNDRV_SEQ_MAX_CLIENTS), 59 clients_entry = create_info_entry("clients",
61 snd_seq_info_clients_read); 60 snd_seq_info_clients_read);
62 timer_entry = create_info_entry("timer", 1024, snd_seq_info_timer_read); 61 timer_entry = create_info_entry("timer", snd_seq_info_timer_read);
63 return 0; 62 return 0;
64} 63}
65 64
diff --git a/sound/core/seq/seq_lock.c b/sound/core/seq/seq_lock.c
index a837a94b2d2a..1a34941d4217 100644
--- a/sound/core/seq/seq_lock.c
+++ b/sound/core/seq/seq_lock.c
@@ -44,4 +44,6 @@ void snd_use_lock_sync_helper(snd_use_lock_t *lockp, const char *file, int line)
44 } 44 }
45} 45}
46 46
47EXPORT_SYMBOL(snd_use_lock_sync_helper);
48
47#endif 49#endif
diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c
index 40b4f679c80e..4bffe509f719 100644
--- a/sound/core/seq/seq_memory.c
+++ b/sound/core/seq/seq_memory.c
@@ -118,6 +118,8 @@ int snd_seq_dump_var_event(const struct snd_seq_event *event,
118 return 0; 118 return 0;
119} 119}
120 120
121EXPORT_SYMBOL(snd_seq_dump_var_event);
122
121 123
122/* 124/*
123 * exported: 125 * exported:
@@ -167,6 +169,7 @@ int snd_seq_expand_var_event(const struct snd_seq_event *event, int count, char
167 return err < 0 ? err : newlen; 169 return err < 0 ? err : newlen;
168} 170}
169 171
172EXPORT_SYMBOL(snd_seq_expand_var_event);
170 173
171/* 174/*
172 * release this cell, free extended data if available 175 * release this cell, free extended data if available
diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c
index 9caa1372bece..1daa5b069c79 100644
--- a/sound/core/seq/seq_midi.c
+++ b/sound/core/seq/seq_midi.c
@@ -278,6 +278,7 @@ snd_seq_midisynth_register_port(struct snd_seq_device *dev)
278 struct seq_midisynth *msynth, *ms; 278 struct seq_midisynth *msynth, *ms;
279 struct snd_seq_port_info *port; 279 struct snd_seq_port_info *port;
280 struct snd_rawmidi_info *info; 280 struct snd_rawmidi_info *info;
281 struct snd_rawmidi *rmidi = dev->private_data;
281 int newclient = 0; 282 int newclient = 0;
282 unsigned int p, ports; 283 unsigned int p, ports;
283 struct snd_seq_port_callback pcallbacks; 284 struct snd_seq_port_callback pcallbacks;
@@ -320,8 +321,8 @@ snd_seq_midisynth_register_port(struct snd_seq_device *dev)
320 } 321 }
321 client->seq_client = 322 client->seq_client =
322 snd_seq_create_kernel_client( 323 snd_seq_create_kernel_client(
323 card, 0, "%s", info->name[0] ? 324 card, 0, "%s", card->shortname[0] ?
324 (const char *)info->name : "External MIDI"); 325 (const char *)card->shortname : "External MIDI");
325 if (client->seq_client < 0) { 326 if (client->seq_client < 0) {
326 kfree(client); 327 kfree(client);
327 mutex_unlock(&register_mutex); 328 mutex_unlock(&register_mutex);
@@ -376,7 +377,9 @@ snd_seq_midisynth_register_port(struct snd_seq_device *dev)
376 if ((port->capability & (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_READ)) == (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_READ) && 377 if ((port->capability & (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_READ)) == (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_READ) &&
377 info->flags & SNDRV_RAWMIDI_INFO_DUPLEX) 378 info->flags & SNDRV_RAWMIDI_INFO_DUPLEX)
378 port->capability |= SNDRV_SEQ_PORT_CAP_DUPLEX; 379 port->capability |= SNDRV_SEQ_PORT_CAP_DUPLEX;
379 port->type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC; 380 port->type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC
381 | SNDRV_SEQ_PORT_TYPE_HARDWARE
382 | SNDRV_SEQ_PORT_TYPE_PORT;
380 port->midi_channels = 16; 383 port->midi_channels = 16;
381 memset(&pcallbacks, 0, sizeof(pcallbacks)); 384 memset(&pcallbacks, 0, sizeof(pcallbacks));
382 pcallbacks.owner = THIS_MODULE; 385 pcallbacks.owner = THIS_MODULE;
@@ -387,6 +390,8 @@ snd_seq_midisynth_register_port(struct snd_seq_device *dev)
387 pcallbacks.unuse = midisynth_unuse; 390 pcallbacks.unuse = midisynth_unuse;
388 pcallbacks.event_input = event_process_midi; 391 pcallbacks.event_input = event_process_midi;
389 port->kernel = &pcallbacks; 392 port->kernel = &pcallbacks;
393 if (rmidi->ops && rmidi->ops->get_port_info)
394 rmidi->ops->get_port_info(rmidi, p, port);
390 if (snd_seq_kernel_client_ctl(client->seq_client, SNDRV_SEQ_IOCTL_CREATE_PORT, port)<0) 395 if (snd_seq_kernel_client_ctl(client->seq_client, SNDRV_SEQ_IOCTL_CREATE_PORT, port)<0)
391 goto __nomem; 396 goto __nomem;
392 ms->seq_client = client->seq_client; 397 ms->seq_client = client->seq_client;
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c
index 41e078c938cd..334579a9f268 100644
--- a/sound/core/seq/seq_ports.c
+++ b/sound/core/seq/seq_ports.c
@@ -221,7 +221,6 @@ static void clear_subscriber_list(struct snd_seq_client *client,
221{ 221{
222 struct list_head *p, *n; 222 struct list_head *p, *n;
223 223
224 down_write(&grp->list_mutex);
225 list_for_each_safe(p, n, &grp->list_head) { 224 list_for_each_safe(p, n, &grp->list_head) {
226 struct snd_seq_subscribers *subs; 225 struct snd_seq_subscribers *subs;
227 struct snd_seq_client *c; 226 struct snd_seq_client *c;
@@ -259,7 +258,6 @@ static void clear_subscriber_list(struct snd_seq_client *client,
259 snd_seq_client_unlock(c); 258 snd_seq_client_unlock(c);
260 } 259 }
261 } 260 }
262 up_write(&grp->list_mutex);
263} 261}
264 262
265/* delete port data */ 263/* delete port data */
@@ -677,6 +675,7 @@ int snd_seq_event_port_attach(int client,
677 return ret; 675 return ret;
678} 676}
679 677
678EXPORT_SYMBOL(snd_seq_event_port_attach);
680 679
681/* 680/*
682 * Detach the driver from a port. 681 * Detach the driver from a port.
@@ -696,3 +695,5 @@ int snd_seq_event_port_detach(int client, int port)
696 695
697 return err; 696 return err;
698} 697}
698
699EXPORT_SYMBOL(snd_seq_event_port_detach);
diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c
index f4edec603b8f..0cfa06c6b81f 100644
--- a/sound/core/seq/seq_virmidi.c
+++ b/sound/core/seq/seq_virmidi.c
@@ -390,7 +390,9 @@ static int snd_virmidi_dev_attach_seq(struct snd_virmidi_dev *rdev)
390 pinfo->capability |= SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SYNC_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE; 390 pinfo->capability |= SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SYNC_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE;
391 pinfo->capability |= SNDRV_SEQ_PORT_CAP_READ | SNDRV_SEQ_PORT_CAP_SYNC_READ | SNDRV_SEQ_PORT_CAP_SUBS_READ; 391 pinfo->capability |= SNDRV_SEQ_PORT_CAP_READ | SNDRV_SEQ_PORT_CAP_SYNC_READ | SNDRV_SEQ_PORT_CAP_SUBS_READ;
392 pinfo->capability |= SNDRV_SEQ_PORT_CAP_DUPLEX; 392 pinfo->capability |= SNDRV_SEQ_PORT_CAP_DUPLEX;
393 pinfo->type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC; 393 pinfo->type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC
394 | SNDRV_SEQ_PORT_TYPE_SOFTWARE
395 | SNDRV_SEQ_PORT_TYPE_PORT;
394 pinfo->midi_channels = 16; 396 pinfo->midi_channels = 16;
395 memset(&pcallbacks, 0, sizeof(pcallbacks)); 397 memset(&pcallbacks, 0, sizeof(pcallbacks));
396 pcallbacks.owner = THIS_MODULE; 398 pcallbacks.owner = THIS_MODULE;
diff --git a/sound/core/sound.c b/sound/core/sound.c
index 108e430b5036..cd862728346c 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -39,6 +39,8 @@
39 39
40static int major = CONFIG_SND_MAJOR; 40static int major = CONFIG_SND_MAJOR;
41int snd_major; 41int snd_major;
42EXPORT_SYMBOL(snd_major);
43
42static int cards_limit = 1; 44static int cards_limit = 1;
43static int device_mode = S_IFCHR | S_IRUGO | S_IWUGO; 45static int device_mode = S_IFCHR | S_IRUGO | S_IWUGO;
44 46
@@ -60,6 +62,7 @@ MODULE_ALIAS_CHARDEV_MAJOR(CONFIG_SND_MAJOR);
60 * modules are loaded manually, this limit number increases, too. 62 * modules are loaded manually, this limit number increases, too.
61 */ 63 */
62int snd_ecards_limit; 64int snd_ecards_limit;
65EXPORT_SYMBOL(snd_ecards_limit);
63 66
64static struct snd_minor *snd_minors[SNDRV_OS_MINORS]; 67static struct snd_minor *snd_minors[SNDRV_OS_MINORS];
65static DEFINE_MUTEX(sound_mutex); 68static DEFINE_MUTEX(sound_mutex);
@@ -78,20 +81,17 @@ extern struct class *sound_class;
78 */ 81 */
79void snd_request_card(int card) 82void snd_request_card(int card)
80{ 83{
81 int locked;
82
83 if (! current->fs->root) 84 if (! current->fs->root)
84 return; 85 return;
85 read_lock(&snd_card_rwlock); 86 if (snd_card_locked(card))
86 locked = snd_cards_lock & (1 << card);
87 read_unlock(&snd_card_rwlock);
88 if (locked)
89 return; 87 return;
90 if (card < 0 || card >= cards_limit) 88 if (card < 0 || card >= cards_limit)
91 return; 89 return;
92 request_module("snd-card-%i", card); 90 request_module("snd-card-%i", card);
93} 91}
94 92
93EXPORT_SYMBOL(snd_request_card);
94
95static void snd_request_other(int minor) 95static void snd_request_other(int minor)
96{ 96{
97 char *str; 97 char *str;
@@ -133,6 +133,8 @@ void *snd_lookup_minor_data(unsigned int minor, int type)
133 return private_data; 133 return private_data;
134} 134}
135 135
136EXPORT_SYMBOL(snd_lookup_minor_data);
137
136static int snd_open(struct inode *inode, struct file *file) 138static int snd_open(struct inode *inode, struct file *file)
137{ 139{
138 unsigned int minor = iminor(inode); 140 unsigned int minor = iminor(inode);
@@ -281,6 +283,8 @@ int snd_register_device(int type, struct snd_card *card, int dev,
281 return 0; 283 return 0;
282} 284}
283 285
286EXPORT_SYMBOL(snd_register_device);
287
284/** 288/**
285 * snd_unregister_device - unregister the device on the given card 289 * snd_unregister_device - unregister the device on the given card
286 * @type: the device type, SNDRV_DEVICE_TYPE_XXX 290 * @type: the device type, SNDRV_DEVICE_TYPE_XXX
@@ -321,12 +325,14 @@ int snd_unregister_device(int type, struct snd_card *card, int dev)
321 return 0; 325 return 0;
322} 326}
323 327
328EXPORT_SYMBOL(snd_unregister_device);
329
324#ifdef CONFIG_PROC_FS 330#ifdef CONFIG_PROC_FS
325/* 331/*
326 * INFO PART 332 * INFO PART
327 */ 333 */
328 334
329static struct snd_info_entry *snd_minor_info_entry = NULL; 335static struct snd_info_entry *snd_minor_info_entry;
330 336
331static const char *snd_device_type_name(int type) 337static const char *snd_device_type_name(int type)
332{ 338{
@@ -381,7 +387,6 @@ int __init snd_minor_info_init(void)
381 387
382 entry = snd_info_create_module_entry(THIS_MODULE, "devices", NULL); 388 entry = snd_info_create_module_entry(THIS_MODULE, "devices", NULL);
383 if (entry) { 389 if (entry) {
384 entry->c.text.read_size = PAGE_SIZE;
385 entry->c.text.read = snd_minor_info_read; 390 entry->c.text.read = snd_minor_info_read;
386 if (snd_info_register(entry) < 0) { 391 if (snd_info_register(entry) < 0) {
387 snd_info_free_entry(entry); 392 snd_info_free_entry(entry);
@@ -446,91 +451,3 @@ static void __exit alsa_sound_exit(void)
446 451
447module_init(alsa_sound_init) 452module_init(alsa_sound_init)
448module_exit(alsa_sound_exit) 453module_exit(alsa_sound_exit)
449
450 /* sound.c */
451EXPORT_SYMBOL(snd_major);
452EXPORT_SYMBOL(snd_ecards_limit);
453#if defined(CONFIG_KMOD)
454EXPORT_SYMBOL(snd_request_card);
455#endif
456EXPORT_SYMBOL(snd_register_device);
457EXPORT_SYMBOL(snd_unregister_device);
458EXPORT_SYMBOL(snd_lookup_minor_data);
459#if defined(CONFIG_SND_OSSEMUL)
460EXPORT_SYMBOL(snd_register_oss_device);
461EXPORT_SYMBOL(snd_unregister_oss_device);
462EXPORT_SYMBOL(snd_lookup_oss_minor_data);
463#endif
464 /* memory.c */
465EXPORT_SYMBOL(copy_to_user_fromio);
466EXPORT_SYMBOL(copy_from_user_toio);
467 /* init.c */
468EXPORT_SYMBOL(snd_cards);
469#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
470EXPORT_SYMBOL(snd_mixer_oss_notify_callback);
471#endif
472EXPORT_SYMBOL(snd_card_new);
473EXPORT_SYMBOL(snd_card_disconnect);
474EXPORT_SYMBOL(snd_card_free);
475EXPORT_SYMBOL(snd_card_free_in_thread);
476EXPORT_SYMBOL(snd_card_register);
477EXPORT_SYMBOL(snd_component_add);
478EXPORT_SYMBOL(snd_card_file_add);
479EXPORT_SYMBOL(snd_card_file_remove);
480#ifdef CONFIG_PM
481EXPORT_SYMBOL(snd_power_wait);
482#endif
483 /* device.c */
484EXPORT_SYMBOL(snd_device_new);
485EXPORT_SYMBOL(snd_device_register);
486EXPORT_SYMBOL(snd_device_free);
487 /* isadma.c */
488#ifdef CONFIG_ISA_DMA_API
489EXPORT_SYMBOL(snd_dma_program);
490EXPORT_SYMBOL(snd_dma_disable);
491EXPORT_SYMBOL(snd_dma_pointer);
492#endif
493 /* info.c */
494#ifdef CONFIG_PROC_FS
495EXPORT_SYMBOL(snd_seq_root);
496EXPORT_SYMBOL(snd_iprintf);
497EXPORT_SYMBOL(snd_info_get_line);
498EXPORT_SYMBOL(snd_info_get_str);
499EXPORT_SYMBOL(snd_info_create_module_entry);
500EXPORT_SYMBOL(snd_info_create_card_entry);
501EXPORT_SYMBOL(snd_info_free_entry);
502EXPORT_SYMBOL(snd_info_register);
503EXPORT_SYMBOL(snd_info_unregister);
504EXPORT_SYMBOL(snd_card_proc_new);
505#endif
506 /* info_oss.c */
507#if defined(CONFIG_SND_OSSEMUL) && defined(CONFIG_PROC_FS)
508EXPORT_SYMBOL(snd_oss_info_register);
509#endif
510 /* control.c */
511EXPORT_SYMBOL(snd_ctl_new);
512EXPORT_SYMBOL(snd_ctl_new1);
513EXPORT_SYMBOL(snd_ctl_free_one);
514EXPORT_SYMBOL(snd_ctl_add);
515EXPORT_SYMBOL(snd_ctl_remove);
516EXPORT_SYMBOL(snd_ctl_remove_id);
517EXPORT_SYMBOL(snd_ctl_rename_id);
518EXPORT_SYMBOL(snd_ctl_find_numid);
519EXPORT_SYMBOL(snd_ctl_find_id);
520EXPORT_SYMBOL(snd_ctl_notify);
521EXPORT_SYMBOL(snd_ctl_register_ioctl);
522EXPORT_SYMBOL(snd_ctl_unregister_ioctl);
523#ifdef CONFIG_COMPAT
524EXPORT_SYMBOL(snd_ctl_register_ioctl_compat);
525EXPORT_SYMBOL(snd_ctl_unregister_ioctl_compat);
526#endif
527EXPORT_SYMBOL(snd_ctl_elem_read);
528EXPORT_SYMBOL(snd_ctl_elem_write);
529 /* misc.c */
530EXPORT_SYMBOL(release_and_free_resource);
531#ifdef CONFIG_SND_VERBOSE_PRINTK
532EXPORT_SYMBOL(snd_verbose_printk);
533#endif
534#if defined(CONFIG_SND_DEBUG) && defined(CONFIG_SND_VERBOSE_PRINTK)
535EXPORT_SYMBOL(snd_verbose_printd);
536#endif
diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c
index 9055c6de9587..74f0fe5a1ba0 100644
--- a/sound/core/sound_oss.c
+++ b/sound/core/sound_oss.c
@@ -58,6 +58,8 @@ void *snd_lookup_oss_minor_data(unsigned int minor, int type)
58 return private_data; 58 return private_data;
59} 59}
60 60
61EXPORT_SYMBOL(snd_lookup_oss_minor_data);
62
61static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev) 63static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev)
62{ 64{
63 int minor; 65 int minor;
@@ -158,6 +160,8 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev,
158 return -EBUSY; 160 return -EBUSY;
159} 161}
160 162
163EXPORT_SYMBOL(snd_register_oss_device);
164
161int snd_unregister_oss_device(int type, struct snd_card *card, int dev) 165int snd_unregister_oss_device(int type, struct snd_card *card, int dev)
162{ 166{
163 int minor = snd_oss_kernel_minor(type, card, dev); 167 int minor = snd_oss_kernel_minor(type, card, dev);
@@ -197,13 +201,15 @@ int snd_unregister_oss_device(int type, struct snd_card *card, int dev)
197 return 0; 201 return 0;
198} 202}
199 203
204EXPORT_SYMBOL(snd_unregister_oss_device);
205
200/* 206/*
201 * INFO PART 207 * INFO PART
202 */ 208 */
203 209
204#ifdef CONFIG_PROC_FS 210#ifdef CONFIG_PROC_FS
205 211
206static struct snd_info_entry *snd_minor_info_oss_entry = NULL; 212static struct snd_info_entry *snd_minor_info_oss_entry;
207 213
208static const char *snd_oss_device_type_name(int type) 214static const char *snd_oss_device_type_name(int type)
209{ 215{
@@ -252,7 +258,6 @@ int __init snd_minor_info_oss_init(void)
252 258
253 entry = snd_info_create_module_entry(THIS_MODULE, "devices", snd_oss_root); 259 entry = snd_info_create_module_entry(THIS_MODULE, "devices", snd_oss_root);
254 if (entry) { 260 if (entry) {
255 entry->c.text.read_size = PAGE_SIZE;
256 entry->c.text.read = snd_minor_info_oss_read; 261 entry->c.text.read = snd_minor_info_oss_read;
257 if (snd_info_register(entry) < 0) { 262 if (snd_info_register(entry) < 0) {
258 snd_info_free_entry(entry); 263 snd_info_free_entry(entry);
diff --git a/sound/core/timer.c b/sound/core/timer.c
index cdeeb639b675..78199f58b93a 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -1061,7 +1061,6 @@ static int snd_timer_register_system(void)
1061static void snd_timer_proc_read(struct snd_info_entry *entry, 1061static void snd_timer_proc_read(struct snd_info_entry *entry,
1062 struct snd_info_buffer *buffer) 1062 struct snd_info_buffer *buffer)
1063{ 1063{
1064 unsigned long flags;
1065 struct snd_timer *timer; 1064 struct snd_timer *timer;
1066 struct snd_timer_instance *ti; 1065 struct snd_timer_instance *ti;
1067 struct list_head *p, *q; 1066 struct list_head *p, *q;
@@ -1095,7 +1094,6 @@ static void snd_timer_proc_read(struct snd_info_entry *entry,
1095 if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE) 1094 if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE)
1096 snd_iprintf(buffer, " SLAVE"); 1095 snd_iprintf(buffer, " SLAVE");
1097 snd_iprintf(buffer, "\n"); 1096 snd_iprintf(buffer, "\n");
1098 spin_lock_irqsave(&timer->lock, flags);
1099 list_for_each(q, &timer->open_list_head) { 1097 list_for_each(q, &timer->open_list_head) {
1100 ti = list_entry(q, struct snd_timer_instance, open_list); 1098 ti = list_entry(q, struct snd_timer_instance, open_list);
1101 snd_iprintf(buffer, " Client %s : %s\n", 1099 snd_iprintf(buffer, " Client %s : %s\n",
@@ -1104,12 +1102,11 @@ static void snd_timer_proc_read(struct snd_info_entry *entry,
1104 SNDRV_TIMER_IFLG_RUNNING) 1102 SNDRV_TIMER_IFLG_RUNNING)
1105 ? "running" : "stopped"); 1103 ? "running" : "stopped");
1106 } 1104 }
1107 spin_unlock_irqrestore(&timer->lock, flags);
1108 } 1105 }
1109 mutex_unlock(&register_mutex); 1106 mutex_unlock(&register_mutex);
1110} 1107}
1111 1108
1112static struct snd_info_entry *snd_timer_proc_entry = NULL; 1109static struct snd_info_entry *snd_timer_proc_entry;
1113 1110
1114static void __init snd_timer_proc_init(void) 1111static void __init snd_timer_proc_init(void)
1115{ 1112{
@@ -1117,7 +1114,6 @@ static void __init snd_timer_proc_init(void)
1117 1114
1118 entry = snd_info_create_module_entry(THIS_MODULE, "timers", NULL); 1115 entry = snd_info_create_module_entry(THIS_MODULE, "timers", NULL);
1119 if (entry != NULL) { 1116 if (entry != NULL) {
1120 entry->c.text.read_size = SNDRV_TIMER_DEVICES * 128;
1121 entry->c.text.read = snd_timer_proc_read; 1117 entry->c.text.read = snd_timer_proc_read;
1122 if (snd_info_register(entry) < 0) { 1118 if (snd_info_register(entry) < 0) {
1123 snd_info_free_entry(entry); 1119 snd_info_free_entry(entry);
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index ae0df549fac7..ffeafaf2ecca 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -677,6 +677,10 @@ static int __init alsa_card_dummy_init(void)
677 i, NULL, 0); 677 i, NULL, 0);
678 if (IS_ERR(device)) 678 if (IS_ERR(device))
679 continue; 679 continue;
680 if (!platform_get_drvdata(device)) {
681 platform_device_unregister(device);
682 continue;
683 }
680 devices[i] = device; 684 devices[i] = device;
681 cards++; 685 cards++;
682 } 686 }
diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c
index 77b06009735d..d3cbbb047582 100644
--- a/sound/drivers/mpu401/mpu401.c
+++ b/sound/drivers/mpu401/mpu401.c
@@ -253,6 +253,10 @@ static int __init alsa_card_mpu401_init(void)
253 i, NULL, 0); 253 i, NULL, 0);
254 if (IS_ERR(device)) 254 if (IS_ERR(device))
255 continue; 255 continue;
256 if (!platform_get_drvdata(device)) {
257 platform_device_unregister(device);
258 continue;
259 }
256 platform_devices[i] = device; 260 platform_devices[i] = device;
257 snd_mpu401_devices++; 261 snd_mpu401_devices++;
258 } 262 }
diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c
index b49a45cbf67a..4bf07ca9b17d 100644
--- a/sound/drivers/mpu401/mpu401_uart.c
+++ b/sound/drivers/mpu401/mpu401_uart.c
@@ -58,22 +58,26 @@ static void snd_mpu401_uart_output_write(struct snd_mpu401 * mpu);
58#define MPU401_ACK 0xfe 58#define MPU401_ACK 0xfe
59 59
60/* Build in lowlevel io */ 60/* Build in lowlevel io */
61static void mpu401_write_port(struct snd_mpu401 *mpu, unsigned char data, unsigned long addr) 61static void mpu401_write_port(struct snd_mpu401 *mpu, unsigned char data,
62 unsigned long addr)
62{ 63{
63 outb(data, addr); 64 outb(data, addr);
64} 65}
65 66
66static unsigned char mpu401_read_port(struct snd_mpu401 *mpu, unsigned long addr) 67static unsigned char mpu401_read_port(struct snd_mpu401 *mpu,
68 unsigned long addr)
67{ 69{
68 return inb(addr); 70 return inb(addr);
69} 71}
70 72
71static void mpu401_write_mmio(struct snd_mpu401 *mpu, unsigned char data, unsigned long addr) 73static void mpu401_write_mmio(struct snd_mpu401 *mpu, unsigned char data,
74 unsigned long addr)
72{ 75{
73 writeb(data, (void __iomem *)addr); 76 writeb(data, (void __iomem *)addr);
74} 77}
75 78
76static unsigned char mpu401_read_mmio(struct snd_mpu401 *mpu, unsigned long addr) 79static unsigned char mpu401_read_mmio(struct snd_mpu401 *mpu,
80 unsigned long addr)
77{ 81{
78 return readb((void __iomem *)addr); 82 return readb((void __iomem *)addr);
79} 83}
@@ -86,20 +90,13 @@ static void snd_mpu401_uart_clear_rx(struct snd_mpu401 *mpu)
86 mpu->read(mpu, MPU401D(mpu)); 90 mpu->read(mpu, MPU401D(mpu));
87#ifdef CONFIG_SND_DEBUG 91#ifdef CONFIG_SND_DEBUG
88 if (timeout <= 0) 92 if (timeout <= 0)
89 snd_printk("cmd: clear rx timeout (status = 0x%x)\n", mpu->read(mpu, MPU401C(mpu))); 93 snd_printk(KERN_ERR "cmd: clear rx timeout (status = 0x%x)\n",
94 mpu->read(mpu, MPU401C(mpu)));
90#endif 95#endif
91} 96}
92 97
93static void _snd_mpu401_uart_interrupt(struct snd_mpu401 *mpu) 98static void uart_interrupt_tx(struct snd_mpu401 *mpu)
94{ 99{
95 spin_lock(&mpu->input_lock);
96 if (test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) {
97 snd_mpu401_uart_input_read(mpu);
98 } else {
99 snd_mpu401_uart_clear_rx(mpu);
100 }
101 spin_unlock(&mpu->input_lock);
102 /* ok. for better Tx performance try do some output when input is done */
103 if (test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode) && 100 if (test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode) &&
104 test_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode)) { 101 test_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode)) {
105 spin_lock(&mpu->output_lock); 102 spin_lock(&mpu->output_lock);
@@ -108,6 +105,22 @@ static void _snd_mpu401_uart_interrupt(struct snd_mpu401 *mpu)
108 } 105 }
109} 106}
110 107
108static void _snd_mpu401_uart_interrupt(struct snd_mpu401 *mpu)
109{
110 if (mpu->info_flags & MPU401_INFO_INPUT) {
111 spin_lock(&mpu->input_lock);
112 if (test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode))
113 snd_mpu401_uart_input_read(mpu);
114 else
115 snd_mpu401_uart_clear_rx(mpu);
116 spin_unlock(&mpu->input_lock);
117 }
118 if (! (mpu->info_flags & MPU401_INFO_TX_IRQ))
119 /* ok. for better Tx performance try do some output
120 when input is done */
121 uart_interrupt_tx(mpu);
122}
123
111/** 124/**
112 * snd_mpu401_uart_interrupt - generic MPU401-UART interrupt handler 125 * snd_mpu401_uart_interrupt - generic MPU401-UART interrupt handler
113 * @irq: the irq number 126 * @irq: the irq number
@@ -116,7 +129,8 @@ static void _snd_mpu401_uart_interrupt(struct snd_mpu401 *mpu)
116 * 129 *
117 * Processes the interrupt for MPU401-UART i/o. 130 * Processes the interrupt for MPU401-UART i/o.
118 */ 131 */
119irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id, struct pt_regs *regs) 132irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id,
133 struct pt_regs *regs)
120{ 134{
121 struct snd_mpu401 *mpu = dev_id; 135 struct snd_mpu401 *mpu = dev_id;
122 136
@@ -126,6 +140,29 @@ irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id, struct pt_regs *reg
126 return IRQ_HANDLED; 140 return IRQ_HANDLED;
127} 141}
128 142
143EXPORT_SYMBOL(snd_mpu401_uart_interrupt);
144
145/**
146 * snd_mpu401_uart_interrupt_tx - generic MPU401-UART transmit irq handler
147 * @irq: the irq number
148 * @dev_id: mpu401 instance
149 * @regs: the reigster
150 *
151 * Processes the interrupt for MPU401-UART output.
152 */
153irqreturn_t snd_mpu401_uart_interrupt_tx(int irq, void *dev_id,
154 struct pt_regs *regs)
155{
156 struct snd_mpu401 *mpu = dev_id;
157
158 if (mpu == NULL)
159 return IRQ_NONE;
160 uart_interrupt_tx(mpu);
161 return IRQ_HANDLED;
162}
163
164EXPORT_SYMBOL(snd_mpu401_uart_interrupt_tx);
165
129/* 166/*
130 * timer callback 167 * timer callback
131 * reprogram the timer and call the interrupt job 168 * reprogram the timer and call the interrupt job
@@ -159,7 +196,8 @@ static void snd_mpu401_uart_add_timer (struct snd_mpu401 *mpu, int input)
159 mpu->timer.expires = 1 + jiffies; 196 mpu->timer.expires = 1 + jiffies;
160 add_timer(&mpu->timer); 197 add_timer(&mpu->timer);
161 } 198 }
162 mpu->timer_invoked |= input ? MPU401_MODE_INPUT_TIMER : MPU401_MODE_OUTPUT_TIMER; 199 mpu->timer_invoked |= input ? MPU401_MODE_INPUT_TIMER :
200 MPU401_MODE_OUTPUT_TIMER;
163 spin_unlock_irqrestore (&mpu->timer_lock, flags); 201 spin_unlock_irqrestore (&mpu->timer_lock, flags);
164} 202}
165 203
@@ -172,7 +210,8 @@ static void snd_mpu401_uart_remove_timer (struct snd_mpu401 *mpu, int input)
172 210
173 spin_lock_irqsave (&mpu->timer_lock, flags); 211 spin_lock_irqsave (&mpu->timer_lock, flags);
174 if (mpu->timer_invoked) { 212 if (mpu->timer_invoked) {
175 mpu->timer_invoked &= input ? ~MPU401_MODE_INPUT_TIMER : ~MPU401_MODE_OUTPUT_TIMER; 213 mpu->timer_invoked &= input ? ~MPU401_MODE_INPUT_TIMER :
214 ~MPU401_MODE_OUTPUT_TIMER;
176 if (! mpu->timer_invoked) 215 if (! mpu->timer_invoked)
177 del_timer(&mpu->timer); 216 del_timer(&mpu->timer);
178 } 217 }
@@ -180,11 +219,12 @@ static void snd_mpu401_uart_remove_timer (struct snd_mpu401 *mpu, int input)
180} 219}
181 220
182/* 221/*
183 222 * send a UART command
223 * return zero if successful, non-zero for some errors
184 */ 224 */
185 225
186static int snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd, 226static int snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd,
187 int ack) 227 int ack)
188{ 228{
189 unsigned long flags; 229 unsigned long flags;
190 int timeout, ok; 230 int timeout, ok;
@@ -196,11 +236,13 @@ static int snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd,
196 } 236 }
197 /* ok. standard MPU-401 initialization */ 237 /* ok. standard MPU-401 initialization */
198 if (mpu->hardware != MPU401_HW_SB) { 238 if (mpu->hardware != MPU401_HW_SB) {
199 for (timeout = 1000; timeout > 0 && !snd_mpu401_output_ready(mpu); timeout--) 239 for (timeout = 1000; timeout > 0 &&
240 !snd_mpu401_output_ready(mpu); timeout--)
200 udelay(10); 241 udelay(10);
201#ifdef CONFIG_SND_DEBUG 242#ifdef CONFIG_SND_DEBUG
202 if (!timeout) 243 if (!timeout)
203 snd_printk("cmd: tx timeout (status = 0x%x)\n", mpu->read(mpu, MPU401C(mpu))); 244 snd_printk(KERN_ERR "cmd: tx timeout (status = 0x%x)\n",
245 mpu->read(mpu, MPU401C(mpu)));
204#endif 246#endif
205 } 247 }
206 mpu->write(mpu, cmd, MPU401C(mpu)); 248 mpu->write(mpu, cmd, MPU401C(mpu));
@@ -215,12 +257,14 @@ static int snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd,
215 } 257 }
216 if (!ok && mpu->read(mpu, MPU401D(mpu)) == MPU401_ACK) 258 if (!ok && mpu->read(mpu, MPU401D(mpu)) == MPU401_ACK)
217 ok = 1; 259 ok = 1;
218 } else { 260 } else
219 ok = 1; 261 ok = 1;
220 }
221 spin_unlock_irqrestore(&mpu->input_lock, flags); 262 spin_unlock_irqrestore(&mpu->input_lock, flags);
222 if (!ok) { 263 if (!ok) {
223 snd_printk("cmd: 0x%x failed at 0x%lx (status = 0x%x, data = 0x%x)\n", cmd, mpu->port, mpu->read(mpu, MPU401C(mpu)), mpu->read(mpu, MPU401D(mpu))); 264 snd_printk(KERN_ERR "cmd: 0x%x failed at 0x%lx "
265 "(status = 0x%x, data = 0x%x)\n", cmd, mpu->port,
266 mpu->read(mpu, MPU401C(mpu)),
267 mpu->read(mpu, MPU401D(mpu)));
224 return 1; 268 return 1;
225 } 269 }
226 return 0; 270 return 0;
@@ -314,7 +358,8 @@ static int snd_mpu401_uart_output_close(struct snd_rawmidi_substream *substream)
314/* 358/*
315 * trigger input callback 359 * trigger input callback
316 */ 360 */
317static void snd_mpu401_uart_input_trigger(struct snd_rawmidi_substream *substream, int up) 361static void
362snd_mpu401_uart_input_trigger(struct snd_rawmidi_substream *substream, int up)
318{ 363{
319 unsigned long flags; 364 unsigned long flags;
320 struct snd_mpu401 *mpu; 365 struct snd_mpu401 *mpu;
@@ -322,7 +367,8 @@ static void snd_mpu401_uart_input_trigger(struct snd_rawmidi_substream *substrea
322 367
323 mpu = substream->rmidi->private_data; 368 mpu = substream->rmidi->private_data;
324 if (up) { 369 if (up) {
325 if (! test_and_set_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode)) { 370 if (! test_and_set_bit(MPU401_MODE_BIT_INPUT_TRIGGER,
371 &mpu->mode)) {
326 /* first time - flush FIFO */ 372 /* first time - flush FIFO */
327 while (max-- > 0) 373 while (max-- > 0)
328 mpu->read(mpu, MPU401D(mpu)); 374 mpu->read(mpu, MPU401D(mpu));
@@ -352,13 +398,11 @@ static void snd_mpu401_uart_input_read(struct snd_mpu401 * mpu)
352 unsigned char byte; 398 unsigned char byte;
353 399
354 while (max-- > 0) { 400 while (max-- > 0) {
355 if (snd_mpu401_input_avail(mpu)) { 401 if (! snd_mpu401_input_avail(mpu))
356 byte = mpu->read(mpu, MPU401D(mpu));
357 if (test_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode))
358 snd_rawmidi_receive(mpu->substream_input, &byte, 1);
359 } else {
360 break; /* input not available */ 402 break; /* input not available */
361 } 403 byte = mpu->read(mpu, MPU401D(mpu));
404 if (test_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode))
405 snd_rawmidi_receive(mpu->substream_input, &byte, 1);
362 } 406 }
363} 407}
364 408
@@ -380,16 +424,16 @@ static void snd_mpu401_uart_output_write(struct snd_mpu401 * mpu)
380 int max = 256, timeout; 424 int max = 256, timeout;
381 425
382 do { 426 do {
383 if (snd_rawmidi_transmit_peek(mpu->substream_output, &byte, 1) == 1) { 427 if (snd_rawmidi_transmit_peek(mpu->substream_output,
428 &byte, 1) == 1) {
384 for (timeout = 100; timeout > 0; timeout--) { 429 for (timeout = 100; timeout > 0; timeout--) {
385 if (snd_mpu401_output_ready(mpu)) { 430 if (snd_mpu401_output_ready(mpu))
386 mpu->write(mpu, byte, MPU401D(mpu));
387 snd_rawmidi_transmit_ack(mpu->substream_output, 1);
388 break; 431 break;
389 }
390 } 432 }
391 if (timeout == 0) 433 if (timeout == 0)
392 break; /* Tx FIFO full - try again later */ 434 break; /* Tx FIFO full - try again later */
435 mpu->write(mpu, byte, MPU401D(mpu));
436 snd_rawmidi_transmit_ack(mpu->substream_output, 1);
393 } else { 437 } else {
394 snd_mpu401_uart_remove_timer (mpu, 0); 438 snd_mpu401_uart_remove_timer (mpu, 0);
395 break; /* no other data - leave the tx loop */ 439 break; /* no other data - leave the tx loop */
@@ -400,7 +444,8 @@ static void snd_mpu401_uart_output_write(struct snd_mpu401 * mpu)
400/* 444/*
401 * output trigger callback 445 * output trigger callback
402 */ 446 */
403static void snd_mpu401_uart_output_trigger(struct snd_rawmidi_substream *substream, int up) 447static void
448snd_mpu401_uart_output_trigger(struct snd_rawmidi_substream *substream, int up)
404{ 449{
405 unsigned long flags; 450 unsigned long flags;
406 struct snd_mpu401 *mpu; 451 struct snd_mpu401 *mpu;
@@ -413,14 +458,16 @@ static void snd_mpu401_uart_output_trigger(struct snd_rawmidi_substream *substre
413 * since the output timer might have been removed in 458 * since the output timer might have been removed in
414 * snd_mpu401_uart_output_write(). 459 * snd_mpu401_uart_output_write().
415 */ 460 */
416 snd_mpu401_uart_add_timer(mpu, 0); 461 if (! (mpu->info_flags & MPU401_INFO_TX_IRQ))
462 snd_mpu401_uart_add_timer(mpu, 0);
417 463
418 /* output pending data */ 464 /* output pending data */
419 spin_lock_irqsave(&mpu->output_lock, flags); 465 spin_lock_irqsave(&mpu->output_lock, flags);
420 snd_mpu401_uart_output_write(mpu); 466 snd_mpu401_uart_output_write(mpu);
421 spin_unlock_irqrestore(&mpu->output_lock, flags); 467 spin_unlock_irqrestore(&mpu->output_lock, flags);
422 } else { 468 } else {
423 snd_mpu401_uart_remove_timer(mpu, 0); 469 if (! (mpu->info_flags & MPU401_INFO_TX_IRQ))
470 snd_mpu401_uart_remove_timer(mpu, 0);
424 clear_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode); 471 clear_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode);
425 } 472 }
426} 473}
@@ -458,7 +505,7 @@ static void snd_mpu401_uart_free(struct snd_rawmidi *rmidi)
458 * @device: the device index, zero-based 505 * @device: the device index, zero-based
459 * @hardware: the hardware type, MPU401_HW_XXXX 506 * @hardware: the hardware type, MPU401_HW_XXXX
460 * @port: the base address of MPU401 port 507 * @port: the base address of MPU401 port
461 * @integrated: non-zero if the port was already reserved by the chip 508 * @info_flags: bitflags MPU401_INFO_XXX
462 * @irq: the irq number, -1 if no interrupt for mpu 509 * @irq: the irq number, -1 if no interrupt for mpu
463 * @irq_flags: the irq request flags (SA_XXX), 0 if irq was already reserved. 510 * @irq_flags: the irq request flags (SA_XXX), 0 if irq was already reserved.
464 * @rrawmidi: the pointer to store the new rawmidi instance 511 * @rrawmidi: the pointer to store the new rawmidi instance
@@ -473,17 +520,24 @@ static void snd_mpu401_uart_free(struct snd_rawmidi *rmidi)
473 */ 520 */
474int snd_mpu401_uart_new(struct snd_card *card, int device, 521int snd_mpu401_uart_new(struct snd_card *card, int device,
475 unsigned short hardware, 522 unsigned short hardware,
476 unsigned long port, int integrated, 523 unsigned long port,
524 unsigned int info_flags,
477 int irq, int irq_flags, 525 int irq, int irq_flags,
478 struct snd_rawmidi ** rrawmidi) 526 struct snd_rawmidi ** rrawmidi)
479{ 527{
480 struct snd_mpu401 *mpu; 528 struct snd_mpu401 *mpu;
481 struct snd_rawmidi *rmidi; 529 struct snd_rawmidi *rmidi;
530 int in_enable, out_enable;
482 int err; 531 int err;
483 532
484 if (rrawmidi) 533 if (rrawmidi)
485 *rrawmidi = NULL; 534 *rrawmidi = NULL;
486 if ((err = snd_rawmidi_new(card, "MPU-401U", device, 1, 1, &rmidi)) < 0) 535 if (! (info_flags & (MPU401_INFO_INPUT | MPU401_INFO_OUTPUT)))
536 info_flags |= MPU401_INFO_INPUT | MPU401_INFO_OUTPUT;
537 in_enable = (info_flags & MPU401_INFO_INPUT) ? 1 : 0;
538 out_enable = (info_flags & MPU401_INFO_OUTPUT) ? 1 : 0;
539 if ((err = snd_rawmidi_new(card, "MPU-401U", device,
540 out_enable, in_enable, &rmidi)) < 0)
487 return err; 541 return err;
488 mpu = kzalloc(sizeof(*mpu), GFP_KERNEL); 542 mpu = kzalloc(sizeof(*mpu), GFP_KERNEL);
489 if (mpu == NULL) { 543 if (mpu == NULL) {
@@ -497,23 +551,23 @@ int snd_mpu401_uart_new(struct snd_card *card, int device,
497 spin_lock_init(&mpu->output_lock); 551 spin_lock_init(&mpu->output_lock);
498 spin_lock_init(&mpu->timer_lock); 552 spin_lock_init(&mpu->timer_lock);
499 mpu->hardware = hardware; 553 mpu->hardware = hardware;
500 if (!integrated) { 554 if (! (info_flags & MPU401_INFO_INTEGRATED)) {
501 int res_size = hardware == MPU401_HW_PC98II ? 4 : 2; 555 int res_size = hardware == MPU401_HW_PC98II ? 4 : 2;
502 if ((mpu->res = request_region(port, res_size, "MPU401 UART")) == NULL) { 556 mpu->res = request_region(port, res_size, "MPU401 UART");
503 snd_printk(KERN_ERR "mpu401_uart: unable to grab port 0x%lx size %d\n", port, res_size); 557 if (mpu->res == NULL) {
558 snd_printk(KERN_ERR "mpu401_uart: "
559 "unable to grab port 0x%lx size %d\n",
560 port, res_size);
504 snd_device_free(card, rmidi); 561 snd_device_free(card, rmidi);
505 return -EBUSY; 562 return -EBUSY;
506 } 563 }
507 } 564 }
508 switch (hardware) { 565 if (info_flags & MPU401_INFO_MMIO) {
509 case MPU401_HW_AUREAL:
510 mpu->write = mpu401_write_mmio; 566 mpu->write = mpu401_write_mmio;
511 mpu->read = mpu401_read_mmio; 567 mpu->read = mpu401_read_mmio;
512 break; 568 } else {
513 default:
514 mpu->write = mpu401_write_port; 569 mpu->write = mpu401_write_port;
515 mpu->read = mpu401_read_port; 570 mpu->read = mpu401_read_port;
516 break;
517 } 571 }
518 mpu->port = port; 572 mpu->port = port;
519 if (hardware == MPU401_HW_PC98II) 573 if (hardware == MPU401_HW_PC98II)
@@ -521,30 +575,40 @@ int snd_mpu401_uart_new(struct snd_card *card, int device,
521 else 575 else
522 mpu->cport = port + 1; 576 mpu->cport = port + 1;
523 if (irq >= 0 && irq_flags) { 577 if (irq >= 0 && irq_flags) {
524 if (request_irq(irq, snd_mpu401_uart_interrupt, irq_flags, "MPU401 UART", (void *) mpu)) { 578 if (request_irq(irq, snd_mpu401_uart_interrupt, irq_flags,
525 snd_printk(KERN_ERR "mpu401_uart: unable to grab IRQ %d\n", irq); 579 "MPU401 UART", (void *) mpu)) {
580 snd_printk(KERN_ERR "mpu401_uart: "
581 "unable to grab IRQ %d\n", irq);
526 snd_device_free(card, rmidi); 582 snd_device_free(card, rmidi);
527 return -EBUSY; 583 return -EBUSY;
528 } 584 }
529 } 585 }
586 mpu->info_flags = info_flags;
530 mpu->irq = irq; 587 mpu->irq = irq;
531 mpu->irq_flags = irq_flags; 588 mpu->irq_flags = irq_flags;
532 if (card->shortname[0]) 589 if (card->shortname[0])
533 snprintf(rmidi->name, sizeof(rmidi->name), "%s MIDI", card->shortname); 590 snprintf(rmidi->name, sizeof(rmidi->name), "%s MIDI",
591 card->shortname);
534 else 592 else
535 sprintf(rmidi->name, "MPU-401 MIDI %d-%d", card->number, device); 593 sprintf(rmidi->name, "MPU-401 MIDI %d-%d",card->number, device);
536 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_mpu401_uart_output); 594 if (out_enable) {
537 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_mpu401_uart_input); 595 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
538 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | 596 &snd_mpu401_uart_output);
539 SNDRV_RAWMIDI_INFO_INPUT | 597 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
540 SNDRV_RAWMIDI_INFO_DUPLEX; 598 }
599 if (in_enable) {
600 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
601 &snd_mpu401_uart_input);
602 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
603 if (out_enable)
604 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;
605 }
541 mpu->rmidi = rmidi; 606 mpu->rmidi = rmidi;
542 if (rrawmidi) 607 if (rrawmidi)
543 *rrawmidi = rmidi; 608 *rrawmidi = rmidi;
544 return 0; 609 return 0;
545} 610}
546 611
547EXPORT_SYMBOL(snd_mpu401_uart_interrupt);
548EXPORT_SYMBOL(snd_mpu401_uart_new); 612EXPORT_SYMBOL(snd_mpu401_uart_new);
549 613
550/* 614/*
diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c
index b7a0b42813e1..474eed06e70f 100644
--- a/sound/drivers/mtpav.c
+++ b/sound/drivers/mtpav.c
@@ -770,11 +770,15 @@ static int __init alsa_card_mtpav_init(void)
770 return err; 770 return err;
771 771
772 device = platform_device_register_simple(SND_MTPAV_DRIVER, -1, NULL, 0); 772 device = platform_device_register_simple(SND_MTPAV_DRIVER, -1, NULL, 0);
773 if (IS_ERR(device)) { 773 if (!IS_ERR(device)) {
774 platform_driver_unregister(&snd_mtpav_driver); 774 if (platform_get_drvdata(device))
775 return PTR_ERR(device); 775 return 0;
776 } 776 platform_device_unregister(device);
777 return 0; 777 err = -ENODEV;
778 } else
779 err = PTR_ERR(device);
780 platform_driver_unregister(&snd_mtpav_driver);
781 return err;
778} 782}
779 783
780static void __exit alsa_card_mtpav_exit(void) 784static void __exit alsa_card_mtpav_exit(void)
diff --git a/sound/drivers/opl3/opl3_lib.c b/sound/drivers/opl3/opl3_lib.c
index 4f8556976774..87fe376f38f0 100644
--- a/sound/drivers/opl3/opl3_lib.c
+++ b/sound/drivers/opl3/opl3_lib.c
@@ -316,6 +316,8 @@ void snd_opl3_interrupt(struct snd_hwdep * hw)
316 } 316 }
317} 317}
318 318
319EXPORT_SYMBOL(snd_opl3_interrupt);
320
319/* 321/*
320 322
321 */ 323 */
@@ -369,6 +371,8 @@ int snd_opl3_new(struct snd_card *card,
369 return 0; 371 return 0;
370} 372}
371 373
374EXPORT_SYMBOL(snd_opl3_new);
375
372int snd_opl3_init(struct snd_opl3 *opl3) 376int snd_opl3_init(struct snd_opl3 *opl3)
373{ 377{
374 if (! opl3->command) { 378 if (! opl3->command) {
@@ -393,6 +397,8 @@ int snd_opl3_init(struct snd_opl3 *opl3)
393 return 0; 397 return 0;
394} 398}
395 399
400EXPORT_SYMBOL(snd_opl3_init);
401
396int snd_opl3_create(struct snd_card *card, 402int snd_opl3_create(struct snd_card *card,
397 unsigned long l_port, 403 unsigned long l_port,
398 unsigned long r_port, 404 unsigned long r_port,
@@ -451,6 +457,8 @@ int snd_opl3_create(struct snd_card *card,
451 return 0; 457 return 0;
452} 458}
453 459
460EXPORT_SYMBOL(snd_opl3_create);
461
454int snd_opl3_timer_new(struct snd_opl3 * opl3, int timer1_dev, int timer2_dev) 462int snd_opl3_timer_new(struct snd_opl3 * opl3, int timer1_dev, int timer2_dev)
455{ 463{
456 int err; 464 int err;
@@ -468,6 +476,8 @@ int snd_opl3_timer_new(struct snd_opl3 * opl3, int timer1_dev, int timer2_dev)
468 return 0; 476 return 0;
469} 477}
470 478
479EXPORT_SYMBOL(snd_opl3_timer_new);
480
471int snd_opl3_hwdep_new(struct snd_opl3 * opl3, 481int snd_opl3_hwdep_new(struct snd_opl3 * opl3,
472 int device, int seq_device, 482 int device, int seq_device,
473 struct snd_hwdep ** rhwdep) 483 struct snd_hwdep ** rhwdep)
@@ -526,17 +536,8 @@ int snd_opl3_hwdep_new(struct snd_opl3 * opl3,
526 return 0; 536 return 0;
527} 537}
528 538
529EXPORT_SYMBOL(snd_opl3_interrupt);
530EXPORT_SYMBOL(snd_opl3_new);
531EXPORT_SYMBOL(snd_opl3_init);
532EXPORT_SYMBOL(snd_opl3_create);
533EXPORT_SYMBOL(snd_opl3_timer_new);
534EXPORT_SYMBOL(snd_opl3_hwdep_new); 539EXPORT_SYMBOL(snd_opl3_hwdep_new);
535 540
536/* opl3_synth.c */
537EXPORT_SYMBOL(snd_opl3_regmap);
538EXPORT_SYMBOL(snd_opl3_reset);
539
540/* 541/*
541 * INIT part 542 * INIT part
542 */ 543 */
diff --git a/sound/drivers/opl3/opl3_oss.c b/sound/drivers/opl3/opl3_oss.c
index fccf019a6d85..5fd3a4c95626 100644
--- a/sound/drivers/opl3/opl3_oss.c
+++ b/sound/drivers/opl3/opl3_oss.c
@@ -100,7 +100,8 @@ static int snd_opl3_oss_create_port(struct snd_opl3 * opl3)
100 SNDRV_SEQ_PORT_CAP_WRITE, 100 SNDRV_SEQ_PORT_CAP_WRITE,
101 SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | 101 SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC |
102 SNDRV_SEQ_PORT_TYPE_MIDI_GM | 102 SNDRV_SEQ_PORT_TYPE_MIDI_GM |
103 SNDRV_SEQ_PORT_TYPE_SYNTH, 103 SNDRV_SEQ_PORT_TYPE_HARDWARE |
104 SNDRV_SEQ_PORT_TYPE_SYNTHESIZER,
104 voices, voices, 105 voices, voices,
105 name); 106 name);
106 if (opl3->oss_chset->port < 0) { 107 if (opl3->oss_chset->port < 0) {
diff --git a/sound/drivers/opl3/opl3_seq.c b/sound/drivers/opl3/opl3_seq.c
index 57becf34f43e..96762c9d4855 100644
--- a/sound/drivers/opl3/opl3_seq.c
+++ b/sound/drivers/opl3/opl3_seq.c
@@ -203,7 +203,9 @@ static int snd_opl3_synth_create_port(struct snd_opl3 * opl3)
203 SNDRV_SEQ_PORT_CAP_SUBS_WRITE, 203 SNDRV_SEQ_PORT_CAP_SUBS_WRITE,
204 SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | 204 SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC |
205 SNDRV_SEQ_PORT_TYPE_MIDI_GM | 205 SNDRV_SEQ_PORT_TYPE_MIDI_GM |
206 SNDRV_SEQ_PORT_TYPE_SYNTH, 206 SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE |
207 SNDRV_SEQ_PORT_TYPE_HARDWARE |
208 SNDRV_SEQ_PORT_TYPE_SYNTHESIZER,
207 16, voices, 209 16, voices,
208 name); 210 name);
209 if (opl3->chset->port < 0) { 211 if (opl3->chset->port < 0) {
diff --git a/sound/drivers/opl3/opl3_synth.c b/sound/drivers/opl3/opl3_synth.c
index 6db503f025b3..a4b3543a7118 100644
--- a/sound/drivers/opl3/opl3_synth.c
+++ b/sound/drivers/opl3/opl3_synth.c
@@ -58,6 +58,8 @@ char snd_opl3_regmap[MAX_OPL2_VOICES][4] =
58 { 0x12, 0x15, 0x00, 0x00 } /* is selected (only left reg block) */ 58 { 0x12, 0x15, 0x00, 0x00 } /* is selected (only left reg block) */
59}; 59};
60 60
61EXPORT_SYMBOL(snd_opl3_regmap);
62
61/* 63/*
62 * prototypes 64 * prototypes
63 */ 65 */
@@ -228,6 +230,7 @@ void snd_opl3_reset(struct snd_opl3 * opl3)
228 opl3->rhythm = 0; 230 opl3->rhythm = 0;
229} 231}
230 232
233EXPORT_SYMBOL(snd_opl3_reset);
231 234
232static int snd_opl3_play_note(struct snd_opl3 * opl3, struct snd_dm_fm_note * note) 235static int snd_opl3_play_note(struct snd_opl3 * opl3, struct snd_dm_fm_note * note)
233{ 236{
@@ -445,3 +448,4 @@ static int snd_opl3_set_connection(struct snd_opl3 * opl3, int connection)
445 448
446 return 0; 449 return 0;
447} 450}
451
diff --git a/sound/drivers/opl4/opl4_lib.c b/sound/drivers/opl4/opl4_lib.c
index 4bc860ae02de..01997f24c895 100644
--- a/sound/drivers/opl4/opl4_lib.c
+++ b/sound/drivers/opl4/opl4_lib.c
@@ -43,6 +43,8 @@ void snd_opl4_write(struct snd_opl4 *opl4, u8 reg, u8 value)
43 outb(value, opl4->pcm_port + 1); 43 outb(value, opl4->pcm_port + 1);
44} 44}
45 45
46EXPORT_SYMBOL(snd_opl4_write);
47
46u8 snd_opl4_read(struct snd_opl4 *opl4, u8 reg) 48u8 snd_opl4_read(struct snd_opl4 *opl4, u8 reg)
47{ 49{
48 snd_opl4_wait(opl4); 50 snd_opl4_wait(opl4);
@@ -52,6 +54,8 @@ u8 snd_opl4_read(struct snd_opl4 *opl4, u8 reg)
52 return inb(opl4->pcm_port + 1); 54 return inb(opl4->pcm_port + 1);
53} 55}
54 56
57EXPORT_SYMBOL(snd_opl4_read);
58
55void snd_opl4_read_memory(struct snd_opl4 *opl4, char *buf, int offset, int size) 59void snd_opl4_read_memory(struct snd_opl4 *opl4, char *buf, int offset, int size)
56{ 60{
57 unsigned long flags; 61 unsigned long flags;
@@ -76,6 +80,8 @@ void snd_opl4_read_memory(struct snd_opl4 *opl4, char *buf, int offset, int size
76 spin_unlock_irqrestore(&opl4->reg_lock, flags); 80 spin_unlock_irqrestore(&opl4->reg_lock, flags);
77} 81}
78 82
83EXPORT_SYMBOL(snd_opl4_read_memory);
84
79void snd_opl4_write_memory(struct snd_opl4 *opl4, const char *buf, int offset, int size) 85void snd_opl4_write_memory(struct snd_opl4 *opl4, const char *buf, int offset, int size)
80{ 86{
81 unsigned long flags; 87 unsigned long flags;
@@ -100,6 +106,8 @@ void snd_opl4_write_memory(struct snd_opl4 *opl4, const char *buf, int offset, i
100 spin_unlock_irqrestore(&opl4->reg_lock, flags); 106 spin_unlock_irqrestore(&opl4->reg_lock, flags);
101} 107}
102 108
109EXPORT_SYMBOL(snd_opl4_write_memory);
110
103static void snd_opl4_enable_opl4(struct snd_opl4 *opl4) 111static void snd_opl4_enable_opl4(struct snd_opl4 *opl4)
104{ 112{
105 outb(OPL3_REG_MODE, opl4->fm_port + 2); 113 outb(OPL3_REG_MODE, opl4->fm_port + 2);
@@ -256,10 +264,6 @@ int snd_opl4_create(struct snd_card *card,
256 return 0; 264 return 0;
257} 265}
258 266
259EXPORT_SYMBOL(snd_opl4_write);
260EXPORT_SYMBOL(snd_opl4_read);
261EXPORT_SYMBOL(snd_opl4_write_memory);
262EXPORT_SYMBOL(snd_opl4_read_memory);
263EXPORT_SYMBOL(snd_opl4_create); 267EXPORT_SYMBOL(snd_opl4_create);
264 268
265static int __init alsa_opl4_init(void) 269static int __init alsa_opl4_init(void)
diff --git a/sound/drivers/opl4/opl4_seq.c b/sound/drivers/opl4/opl4_seq.c
index dc0dcdc6c313..43d8a2bdd280 100644
--- a/sound/drivers/opl4/opl4_seq.c
+++ b/sound/drivers/opl4/opl4_seq.c
@@ -164,7 +164,9 @@ static int snd_opl4_seq_new_device(struct snd_seq_device *dev)
164 SNDRV_SEQ_PORT_CAP_WRITE | 164 SNDRV_SEQ_PORT_CAP_WRITE |
165 SNDRV_SEQ_PORT_CAP_SUBS_WRITE, 165 SNDRV_SEQ_PORT_CAP_SUBS_WRITE,
166 SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | 166 SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC |
167 SNDRV_SEQ_PORT_TYPE_MIDI_GM, 167 SNDRV_SEQ_PORT_TYPE_MIDI_GM |
168 SNDRV_SEQ_PORT_TYPE_HARDWARE |
169 SNDRV_SEQ_PORT_TYPE_SYNTHESIZER,
168 16, 24, 170 16, 24,
169 "OPL4 Wavetable Port"); 171 "OPL4 Wavetable Port");
170 if (opl4->chset->port < 0) { 172 if (opl4->chset->port < 0) {
diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c
index c01b4c5118b9..2330fec505da 100644
--- a/sound/drivers/serial-u16550.c
+++ b/sound/drivers/serial-u16550.c
@@ -998,6 +998,10 @@ static int __init alsa_card_serial_init(void)
998 i, NULL, 0); 998 i, NULL, 0);
999 if (IS_ERR(device)) 999 if (IS_ERR(device))
1000 continue; 1000 continue;
1001 if (!platform_get_drvdata(device)) {
1002 platform_device_unregister(device);
1003 continue;
1004 }
1001 devices[i] = device; 1005 devices[i] = device;
1002 cards++; 1006 cards++;
1003 } 1007 }
diff --git a/sound/drivers/virmidi.c b/sound/drivers/virmidi.c
index 26eb2499d442..59171f8200df 100644
--- a/sound/drivers/virmidi.c
+++ b/sound/drivers/virmidi.c
@@ -171,6 +171,10 @@ static int __init alsa_card_virmidi_init(void)
171 i, NULL, 0); 171 i, NULL, 0);
172 if (IS_ERR(device)) 172 if (IS_ERR(device))
173 continue; 173 continue;
174 if (!platform_get_drvdata(device)) {
175 platform_device_unregister(device);
176 continue;
177 }
174 devices[i] = device; 178 devices[i] = device;
175 cards++; 179 cards++;
176 } 180 }
diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c
index fa4a2b5c2d8d..a60168268ddd 100644
--- a/sound/drivers/vx/vx_core.c
+++ b/sound/drivers/vx/vx_core.c
@@ -70,6 +70,8 @@ int snd_vx_check_reg_bit(struct vx_core *chip, int reg, int mask, int bit, int t
70 return -EIO; 70 return -EIO;
71} 71}
72 72
73EXPORT_SYMBOL(snd_vx_check_reg_bit);
74
73/* 75/*
74 * vx_send_irq_dsp - set command irq bit 76 * vx_send_irq_dsp - set command irq bit
75 * @num: the requested IRQ type, IRQ_XXX 77 * @num: the requested IRQ type, IRQ_XXX
@@ -465,6 +467,8 @@ int snd_vx_load_boot_image(struct vx_core *chip, const struct firmware *boot)
465 return 0; 467 return 0;
466} 468}
467 469
470EXPORT_SYMBOL(snd_vx_load_boot_image);
471
468/* 472/*
469 * vx_test_irq_src - query the source of interrupts 473 * vx_test_irq_src - query the source of interrupts
470 * 474 *
@@ -545,6 +549,7 @@ irqreturn_t snd_vx_irq_handler(int irq, void *dev, struct pt_regs *regs)
545 return IRQ_HANDLED; 549 return IRQ_HANDLED;
546} 550}
547 551
552EXPORT_SYMBOL(snd_vx_irq_handler);
548 553
549/* 554/*
550 */ 555 */
@@ -635,7 +640,7 @@ static void vx_proc_init(struct vx_core *chip)
635 struct snd_info_entry *entry; 640 struct snd_info_entry *entry;
636 641
637 if (! snd_card_proc_new(chip->card, "vx-status", &entry)) 642 if (! snd_card_proc_new(chip->card, "vx-status", &entry))
638 snd_info_set_text_ops(entry, chip, 1024, vx_proc_read); 643 snd_info_set_text_ops(entry, chip, vx_proc_read);
639} 644}
640 645
641 646
@@ -657,6 +662,8 @@ int snd_vx_dsp_boot(struct vx_core *chip, const struct firmware *boot)
657 return 0; 662 return 0;
658} 663}
659 664
665EXPORT_SYMBOL(snd_vx_dsp_boot);
666
660/** 667/**
661 * snd_vx_dsp_load - load the DSP image 668 * snd_vx_dsp_load - load the DSP image
662 */ 669 */
@@ -705,6 +712,8 @@ int snd_vx_dsp_load(struct vx_core *chip, const struct firmware *dsp)
705 return 0; 712 return 0;
706} 713}
707 714
715EXPORT_SYMBOL(snd_vx_dsp_load);
716
708#ifdef CONFIG_PM 717#ifdef CONFIG_PM
709/* 718/*
710 * suspend 719 * suspend
@@ -721,6 +730,8 @@ int snd_vx_suspend(struct vx_core *chip, pm_message_t state)
721 return 0; 730 return 0;
722} 731}
723 732
733EXPORT_SYMBOL(snd_vx_suspend);
734
724/* 735/*
725 * resume 736 * resume
726 */ 737 */
@@ -747,6 +758,7 @@ int snd_vx_resume(struct vx_core *chip)
747 return 0; 758 return 0;
748} 759}
749 760
761EXPORT_SYMBOL(snd_vx_resume);
750#endif 762#endif
751 763
752/** 764/**
@@ -790,6 +802,8 @@ struct vx_core *snd_vx_create(struct snd_card *card, struct snd_vx_hardware *hw,
790 return chip; 802 return chip;
791} 803}
792 804
805EXPORT_SYMBOL(snd_vx_create);
806
793/* 807/*
794 * module entries 808 * module entries
795 */ 809 */
@@ -804,19 +818,3 @@ static void __exit alsa_vx_core_exit(void)
804 818
805module_init(alsa_vx_core_init) 819module_init(alsa_vx_core_init)
806module_exit(alsa_vx_core_exit) 820module_exit(alsa_vx_core_exit)
807
808/*
809 * exports
810 */
811EXPORT_SYMBOL(snd_vx_check_reg_bit);
812EXPORT_SYMBOL(snd_vx_create);
813EXPORT_SYMBOL(snd_vx_setup_firmware);
814EXPORT_SYMBOL(snd_vx_free_firmware);
815EXPORT_SYMBOL(snd_vx_irq_handler);
816EXPORT_SYMBOL(snd_vx_dsp_boot);
817EXPORT_SYMBOL(snd_vx_dsp_load);
818EXPORT_SYMBOL(snd_vx_load_boot_image);
819#ifdef CONFIG_PM
820EXPORT_SYMBOL(snd_vx_suspend);
821EXPORT_SYMBOL(snd_vx_resume);
822#endif
diff --git a/sound/drivers/vx/vx_hwdep.c b/sound/drivers/vx/vx_hwdep.c
index d837783fb538..e1920af4501d 100644
--- a/sound/drivers/vx/vx_hwdep.c
+++ b/sound/drivers/vx/vx_hwdep.c
@@ -250,3 +250,6 @@ void snd_vx_free_firmware(struct vx_core *chip)
250} 250}
251 251
252#endif /* SND_VX_FW_LOADER */ 252#endif /* SND_VX_FW_LOADER */
253
254EXPORT_SYMBOL(snd_vx_setup_firmware);
255EXPORT_SYMBOL(snd_vx_free_firmware);
diff --git a/sound/i2c/i2c.c b/sound/i2c/i2c.c
index edfe76fb0074..b60fb1892828 100644
--- a/sound/i2c/i2c.c
+++ b/sound/i2c/i2c.c
@@ -106,6 +106,8 @@ int snd_i2c_bus_create(struct snd_card *card, const char *name,
106 return 0; 106 return 0;
107} 107}
108 108
109EXPORT_SYMBOL(snd_i2c_bus_create);
110
109int snd_i2c_device_create(struct snd_i2c_bus *bus, const char *name, 111int snd_i2c_device_create(struct snd_i2c_bus *bus, const char *name,
110 unsigned char addr, struct snd_i2c_device **rdevice) 112 unsigned char addr, struct snd_i2c_device **rdevice)
111{ 113{
@@ -124,6 +126,8 @@ int snd_i2c_device_create(struct snd_i2c_bus *bus, const char *name,
124 return 0; 126 return 0;
125} 127}
126 128
129EXPORT_SYMBOL(snd_i2c_device_create);
130
127int snd_i2c_device_free(struct snd_i2c_device *device) 131int snd_i2c_device_free(struct snd_i2c_device *device)
128{ 132{
129 if (device->bus) 133 if (device->bus)
@@ -134,22 +138,29 @@ int snd_i2c_device_free(struct snd_i2c_device *device)
134 return 0; 138 return 0;
135} 139}
136 140
141EXPORT_SYMBOL(snd_i2c_device_free);
142
137int snd_i2c_sendbytes(struct snd_i2c_device *device, unsigned char *bytes, int count) 143int snd_i2c_sendbytes(struct snd_i2c_device *device, unsigned char *bytes, int count)
138{ 144{
139 return device->bus->ops->sendbytes(device, bytes, count); 145 return device->bus->ops->sendbytes(device, bytes, count);
140} 146}
141 147
148EXPORT_SYMBOL(snd_i2c_sendbytes);
142 149
143int snd_i2c_readbytes(struct snd_i2c_device *device, unsigned char *bytes, int count) 150int snd_i2c_readbytes(struct snd_i2c_device *device, unsigned char *bytes, int count)
144{ 151{
145 return device->bus->ops->readbytes(device, bytes, count); 152 return device->bus->ops->readbytes(device, bytes, count);
146} 153}
147 154
155EXPORT_SYMBOL(snd_i2c_readbytes);
156
148int snd_i2c_probeaddr(struct snd_i2c_bus *bus, unsigned short addr) 157int snd_i2c_probeaddr(struct snd_i2c_bus *bus, unsigned short addr)
149{ 158{
150 return bus->ops->probeaddr(bus, addr); 159 return bus->ops->probeaddr(bus, addr);
151} 160}
152 161
162EXPORT_SYMBOL(snd_i2c_probeaddr);
163
153/* 164/*
154 * bit-operations 165 * bit-operations
155 */ 166 */
@@ -320,12 +331,6 @@ static int snd_i2c_bit_probeaddr(struct snd_i2c_bus *bus, unsigned short addr)
320 return err; 331 return err;
321} 332}
322 333
323EXPORT_SYMBOL(snd_i2c_bus_create);
324EXPORT_SYMBOL(snd_i2c_device_create);
325EXPORT_SYMBOL(snd_i2c_device_free);
326EXPORT_SYMBOL(snd_i2c_sendbytes);
327EXPORT_SYMBOL(snd_i2c_readbytes);
328EXPORT_SYMBOL(snd_i2c_probeaddr);
329 334
330static int __init alsa_i2c_init(void) 335static int __init alsa_i2c_init(void)
331{ 336{
diff --git a/sound/i2c/l3/uda1341.c b/sound/i2c/l3/uda1341.c
index 746500e06950..b074fdddea55 100644
--- a/sound/i2c/l3/uda1341.c
+++ b/sound/i2c/l3/uda1341.c
@@ -517,9 +517,9 @@ static void __devinit snd_uda1341_proc_init(struct snd_card *card, struct l3_cli
517 struct snd_info_entry *entry; 517 struct snd_info_entry *entry;
518 518
519 if (! snd_card_proc_new(card, "uda1341", &entry)) 519 if (! snd_card_proc_new(card, "uda1341", &entry))
520 snd_info_set_text_ops(entry, clnt, 1024, snd_uda1341_proc_read); 520 snd_info_set_text_ops(entry, clnt, snd_uda1341_proc_read);
521 if (! snd_card_proc_new(card, "uda1341-regs", &entry)) 521 if (! snd_card_proc_new(card, "uda1341-regs", &entry))
522 snd_info_set_text_ops(entry, clnt, 1024, snd_uda1341_proc_regs_read); 522 snd_info_set_text_ops(entry, clnt, snd_uda1341_proc_regs_read);
523} 523}
524 524
525/* }}} */ 525/* }}} */
diff --git a/sound/isa/gus/gus_irq.c b/sound/isa/gus/gus_irq.c
index c19ba2910b72..42db37552efb 100644
--- a/sound/isa/gus/gus_irq.c
+++ b/sound/isa/gus/gus_irq.c
@@ -136,7 +136,7 @@ void snd_gus_irq_profile_init(struct snd_gus_card *gus)
136 struct snd_info_entry *entry; 136 struct snd_info_entry *entry;
137 137
138 if (! snd_card_proc_new(gus->card, "gusirq", &entry)) 138 if (! snd_card_proc_new(gus->card, "gusirq", &entry))
139 snd_info_set_text_ops(entry, gus, 1024, snd_gus_irq_info_read); 139 snd_info_set_text_ops(entry, gus, snd_gus_irq_info_read);
140} 140}
141 141
142#endif 142#endif
diff --git a/sound/isa/gus/gus_mem.c b/sound/isa/gus/gus_mem.c
index 3c0d27aa08b3..f50c276caee8 100644
--- a/sound/isa/gus/gus_mem.c
+++ b/sound/isa/gus/gus_mem.c
@@ -264,10 +264,8 @@ int snd_gf1_mem_init(struct snd_gus_card * gus)
264 if (snd_gf1_mem_xalloc(alloc, &block) == NULL) 264 if (snd_gf1_mem_xalloc(alloc, &block) == NULL)
265 return -ENOMEM; 265 return -ENOMEM;
266#ifdef CONFIG_SND_DEBUG 266#ifdef CONFIG_SND_DEBUG
267 if (! snd_card_proc_new(gus->card, "gusmem", &entry)) { 267 if (! snd_card_proc_new(gus->card, "gusmem", &entry))
268 snd_info_set_text_ops(entry, gus, 1024, snd_gf1_mem_info_read); 268 snd_info_set_text_ops(entry, gus, snd_gf1_mem_info_read);
269 entry->c.text.read_size = 256 * 1024;
270 }
271#endif 269#endif
272 return 0; 270 return 0;
273} 271}
diff --git a/sound/isa/gus/gus_synth.c b/sound/isa/gus/gus_synth.c
index 2767cc187ae3..3e4d4d6edd8b 100644
--- a/sound/isa/gus/gus_synth.c
+++ b/sound/isa/gus/gus_synth.c
@@ -194,7 +194,9 @@ static int snd_gus_synth_create_port(struct snd_gus_card * gus, int idx)
194 &callbacks, 194 &callbacks,
195 SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE, 195 SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE,
196 SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE | 196 SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE |
197 SNDRV_SEQ_PORT_TYPE_SYNTH, 197 SNDRV_SEQ_PORT_TYPE_SYNTH |
198 SNDRV_SEQ_PORT_TYPE_HARDWARE |
199 SNDRV_SEQ_PORT_TYPE_SYNTHESIZER,
198 16, 0, 200 16, 0,
199 name); 201 name);
200 if (p->chset->port < 0) { 202 if (p->chset->port < 0) {
diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c
index 4298d339e786..866300f2acbb 100644
--- a/sound/isa/gus/interwave.c
+++ b/sound/isa/gus/interwave.c
@@ -70,9 +70,9 @@ static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */
70static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ 70static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */
71static int joystick_dac[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 29}; 71static int joystick_dac[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 29};
72 /* 0 to 31, (0.59V-4.52V or 0.389V-2.98V) */ 72 /* 0 to 31, (0.59V-4.52V or 0.389V-2.98V) */
73static int midi[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; 73static int midi[SNDRV_CARDS];
74static int pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; 74static int pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};
75static int effect[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; 75static int effect[SNDRV_CARDS];
76 76
77#ifdef SNDRV_STB 77#ifdef SNDRV_STB
78#define PFX "interwave-stb: " 78#define PFX "interwave-stb: "
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
index 6d889052c32c..647a996791e9 100644
--- a/sound/isa/opl3sa2.c
+++ b/sound/isa/opl3sa2.c
@@ -59,7 +59,7 @@ static long midi_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;/* 0x330,0x300 */
59static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 0,1,3,5,9,11,12,15 */ 59static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 0,1,3,5,9,11,12,15 */
60static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 1,3,5,6,7 */ 60static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 1,3,5,6,7 */
61static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 1,3,5,6,7 */ 61static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 1,3,5,6,7 */
62static int opl3sa3_ymode[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0 }; /* 0,1,2,3 */ /*SL Added*/ 62static int opl3sa3_ymode[SNDRV_CARDS]; /* 0,1,2,3 */ /*SL Added*/
63 63
64module_param_array(index, int, NULL, 0444); 64module_param_array(index, int, NULL, 0444);
65MODULE_PARM_DESC(index, "Index value for OPL3-SA soundcard."); 65MODULE_PARM_DESC(index, "Index value for OPL3-SA soundcard.");
@@ -221,7 +221,7 @@ static void snd_opl3sa2_write(struct snd_opl3sa2 *chip, unsigned char reg, unsig
221 spin_unlock_irqrestore(&chip->reg_lock, flags); 221 spin_unlock_irqrestore(&chip->reg_lock, flags);
222} 222}
223 223
224static int __init snd_opl3sa2_detect(struct snd_opl3sa2 *chip) 224static int __devinit snd_opl3sa2_detect(struct snd_opl3sa2 *chip)
225{ 225{
226 struct snd_card *card; 226 struct snd_card *card;
227 unsigned long port; 227 unsigned long port;
@@ -489,7 +489,7 @@ static void snd_opl3sa2_master_free(struct snd_kcontrol *kcontrol)
489 chip->master_volume = NULL; 489 chip->master_volume = NULL;
490} 490}
491 491
492static int __init snd_opl3sa2_mixer(struct snd_opl3sa2 *chip) 492static int __devinit snd_opl3sa2_mixer(struct snd_opl3sa2 *chip)
493{ 493{
494 struct snd_card *card = chip->card; 494 struct snd_card *card = chip->card;
495 struct snd_ctl_elem_id id1, id2; 495 struct snd_ctl_elem_id id1, id2;
@@ -583,8 +583,8 @@ static int snd_opl3sa2_resume(struct snd_card *card)
583#endif /* CONFIG_PM */ 583#endif /* CONFIG_PM */
584 584
585#ifdef CONFIG_PNP 585#ifdef CONFIG_PNP
586static int __init snd_opl3sa2_pnp(int dev, struct snd_opl3sa2 *chip, 586static int __devinit snd_opl3sa2_pnp(int dev, struct snd_opl3sa2 *chip,
587 struct pnp_dev *pdev) 587 struct pnp_dev *pdev)
588{ 588{
589 struct pnp_resource_table * cfg; 589 struct pnp_resource_table * cfg;
590 int err; 590 int err;
@@ -862,7 +862,7 @@ static struct pnp_card_driver opl3sa2_pnpc_driver = {
862}; 862};
863#endif /* CONFIG_PNP */ 863#endif /* CONFIG_PNP */
864 864
865static int __init snd_opl3sa2_nonpnp_probe(struct platform_device *pdev) 865static int __devinit snd_opl3sa2_nonpnp_probe(struct platform_device *pdev)
866{ 866{
867 struct snd_card *card; 867 struct snd_card *card;
868 int err; 868 int err;
diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c
index e6bfcf74c1c1..283817f2de75 100644
--- a/sound/isa/opti9xx/miro.c
+++ b/sound/isa/opti9xx/miro.c
@@ -967,7 +967,7 @@ static void __init snd_miro_proc_init(struct snd_miro * miro)
967 struct snd_info_entry *entry; 967 struct snd_info_entry *entry;
968 968
969 if (! snd_card_proc_new(miro->card, "miro", &entry)) 969 if (! snd_card_proc_new(miro->card, "miro", &entry))
970 snd_info_set_text_ops(entry, miro, 1024, snd_miro_proc_read); 970 snd_info_set_text_ops(entry, miro, snd_miro_proc_read);
971} 971}
972 972
973/* 973/*
diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c
index c0b8d61b75e7..658179e86142 100644
--- a/sound/isa/sb/emu8000.c
+++ b/sound/isa/sb/emu8000.c
@@ -131,7 +131,7 @@ snd_emu8000_dma_chan(struct snd_emu8000 *emu, int ch, int mode)
131 131
132/* 132/*
133 */ 133 */
134static void __init 134static void __devinit
135snd_emu8000_read_wait(struct snd_emu8000 *emu) 135snd_emu8000_read_wait(struct snd_emu8000 *emu)
136{ 136{
137 while ((EMU8000_SMALR_READ(emu) & 0x80000000) != 0) { 137 while ((EMU8000_SMALR_READ(emu) & 0x80000000) != 0) {
@@ -143,7 +143,7 @@ snd_emu8000_read_wait(struct snd_emu8000 *emu)
143 143
144/* 144/*
145 */ 145 */
146static void __init 146static void __devinit
147snd_emu8000_write_wait(struct snd_emu8000 *emu) 147snd_emu8000_write_wait(struct snd_emu8000 *emu)
148{ 148{
149 while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) { 149 while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) {
@@ -156,7 +156,7 @@ snd_emu8000_write_wait(struct snd_emu8000 *emu)
156/* 156/*
157 * detect a card at the given port 157 * detect a card at the given port
158 */ 158 */
159static int __init 159static int __devinit
160snd_emu8000_detect(struct snd_emu8000 *emu) 160snd_emu8000_detect(struct snd_emu8000 *emu)
161{ 161{
162 /* Initialise */ 162 /* Initialise */
@@ -182,7 +182,7 @@ snd_emu8000_detect(struct snd_emu8000 *emu)
182/* 182/*
183 * intiailize audio channels 183 * intiailize audio channels
184 */ 184 */
185static void __init 185static void __devinit
186init_audio(struct snd_emu8000 *emu) 186init_audio(struct snd_emu8000 *emu)
187{ 187{
188 int ch; 188 int ch;
@@ -223,7 +223,7 @@ init_audio(struct snd_emu8000 *emu)
223/* 223/*
224 * initialize DMA address 224 * initialize DMA address
225 */ 225 */
226static void __init 226static void __devinit
227init_dma(struct snd_emu8000 *emu) 227init_dma(struct snd_emu8000 *emu)
228{ 228{
229 EMU8000_SMALR_WRITE(emu, 0); 229 EMU8000_SMALR_WRITE(emu, 0);
@@ -327,7 +327,7 @@ static unsigned short init4[128] /*__devinitdata*/ = {
327 * Taken from the oss driver, not obvious from the doc how this 327 * Taken from the oss driver, not obvious from the doc how this
328 * is meant to work 328 * is meant to work
329 */ 329 */
330static void __init 330static void __devinit
331send_array(struct snd_emu8000 *emu, unsigned short *data, int size) 331send_array(struct snd_emu8000 *emu, unsigned short *data, int size)
332{ 332{
333 int i; 333 int i;
@@ -349,7 +349,7 @@ send_array(struct snd_emu8000 *emu, unsigned short *data, int size)
349 * Send initialization arrays to start up, this just follows the 349 * Send initialization arrays to start up, this just follows the
350 * initialisation sequence in the adip. 350 * initialisation sequence in the adip.
351 */ 351 */
352static void __init 352static void __devinit
353init_arrays(struct snd_emu8000 *emu) 353init_arrays(struct snd_emu8000 *emu)
354{ 354{
355 send_array(emu, init1, ARRAY_SIZE(init1)/4); 355 send_array(emu, init1, ARRAY_SIZE(init1)/4);
@@ -375,7 +375,7 @@ init_arrays(struct snd_emu8000 *emu)
375 * seems that the only way to do this is to use the one channel and keep 375 * seems that the only way to do this is to use the one channel and keep
376 * reallocating between read and write. 376 * reallocating between read and write.
377 */ 377 */
378static void __init 378static void __devinit
379size_dram(struct snd_emu8000 *emu) 379size_dram(struct snd_emu8000 *emu)
380{ 380{
381 int i, size; 381 int i, size;
@@ -500,7 +500,7 @@ snd_emu8000_init_fm(struct snd_emu8000 *emu)
500/* 500/*
501 * The main initialization routine. 501 * The main initialization routine.
502 */ 502 */
503static void __init 503static void __devinit
504snd_emu8000_init_hw(struct snd_emu8000 *emu) 504snd_emu8000_init_hw(struct snd_emu8000 *emu)
505{ 505{
506 int i; 506 int i;
@@ -1019,7 +1019,7 @@ static struct snd_kcontrol_new *mixer_defs[EMU8000_NUM_CONTROLS] = {
1019/* 1019/*
1020 * create and attach mixer elements for WaveTable treble/bass controls 1020 * create and attach mixer elements for WaveTable treble/bass controls
1021 */ 1021 */
1022static int __init 1022static int __devinit
1023snd_emu8000_create_mixer(struct snd_card *card, struct snd_emu8000 *emu) 1023snd_emu8000_create_mixer(struct snd_card *card, struct snd_emu8000 *emu)
1024{ 1024{
1025 int i, err = 0; 1025 int i, err = 0;
@@ -1069,7 +1069,7 @@ static int snd_emu8000_dev_free(struct snd_device *device)
1069/* 1069/*
1070 * initialize and register emu8000 synth device. 1070 * initialize and register emu8000 synth device.
1071 */ 1071 */
1072int __init 1072int __devinit
1073snd_emu8000_new(struct snd_card *card, int index, long port, int seq_ports, 1073snd_emu8000_new(struct snd_card *card, int index, long port, int seq_ports,
1074 struct snd_seq_device **awe_ret) 1074 struct snd_seq_device **awe_ret)
1075{ 1075{
diff --git a/sound/isa/sb/emu8000_patch.c b/sound/isa/sb/emu8000_patch.c
index 80b1cf84a1ae..1be16c9700f0 100644
--- a/sound/isa/sb/emu8000_patch.c
+++ b/sound/isa/sb/emu8000_patch.c
@@ -23,7 +23,7 @@
23#include <asm/uaccess.h> 23#include <asm/uaccess.h>
24#include <linux/moduleparam.h> 24#include <linux/moduleparam.h>
25 25
26static int emu8000_reset_addr = 0; 26static int emu8000_reset_addr;
27module_param(emu8000_reset_addr, int, 0444); 27module_param(emu8000_reset_addr, int, 0444);
28MODULE_PARM_DESC(emu8000_reset_addr, "reset write address at each time (makes slowdown)"); 28MODULE_PARM_DESC(emu8000_reset_addr, "reset write address at each time (makes slowdown)");
29 29
diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c
index 6333f900eaee..7f7f05fa518a 100644
--- a/sound/isa/sb/sb16.c
+++ b/sound/isa/sb/sb16.c
@@ -85,7 +85,7 @@ static int dma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3 */
85static int dma16[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 5,6,7 */ 85static int dma16[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 5,6,7 */
86static int mic_agc[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; 86static int mic_agc[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
87#ifdef CONFIG_SND_SB16_CSP 87#ifdef CONFIG_SND_SB16_CSP
88static int csp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; 88static int csp[SNDRV_CARDS];
89#endif 89#endif
90#ifdef SNDRV_SBAWE_EMU8000 90#ifdef SNDRV_SBAWE_EMU8000
91static int seq_ports[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4}; 91static int seq_ports[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4};
diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c
index 9703c68e4e08..fcd638090a9e 100644
--- a/sound/isa/sb/sb16_csp.c
+++ b/sound/isa/sb/sb16_csp.c
@@ -1101,7 +1101,7 @@ static int init_proc_entry(struct snd_sb_csp * p, int device)
1101 struct snd_info_entry *entry; 1101 struct snd_info_entry *entry;
1102 sprintf(name, "cspD%d", device); 1102 sprintf(name, "cspD%d", device);
1103 if (! snd_card_proc_new(p->chip->card, name, &entry)) 1103 if (! snd_card_proc_new(p->chip->card, name, &entry))
1104 snd_info_set_text_ops(entry, p, 1024, info_read); 1104 snd_info_set_text_ops(entry, p, info_read);
1105 return 0; 1105 return 0;
1106} 1106}
1107 1107
diff --git a/sound/isa/sb/sb8_midi.c b/sound/isa/sb/sb8_midi.c
index c549aceea294..0b67edd7ac6e 100644
--- a/sound/isa/sb/sb8_midi.c
+++ b/sound/isa/sb/sb8_midi.c
@@ -32,20 +32,22 @@
32#include <sound/core.h> 32#include <sound/core.h>
33#include <sound/sb.h> 33#include <sound/sb.h>
34 34
35/*
36
37 */
38 35
39irqreturn_t snd_sb8dsp_midi_interrupt(struct snd_sb * chip) 36irqreturn_t snd_sb8dsp_midi_interrupt(struct snd_sb *chip)
40{ 37{
41 struct snd_rawmidi *rmidi; 38 struct snd_rawmidi *rmidi;
42 int max = 64; 39 int max = 64;
43 char byte; 40 char byte;
44 41
45 if (chip == NULL || (rmidi = chip->rmidi) == NULL) { 42 if (!chip)
43 return IRQ_NONE;
44
45 rmidi = chip->rmidi;
46 if (!rmidi) {
46 inb(SBP(chip, DATA_AVAIL)); /* ack interrupt */ 47 inb(SBP(chip, DATA_AVAIL)); /* ack interrupt */
47 return IRQ_NONE; 48 return IRQ_NONE;
48 } 49 }
50
49 spin_lock(&chip->midi_input_lock); 51 spin_lock(&chip->midi_input_lock);
50 while (max-- > 0) { 52 while (max-- > 0) {
51 if (inb(SBP(chip, DATA_AVAIL)) & 0x80) { 53 if (inb(SBP(chip, DATA_AVAIL)) & 0x80) {
@@ -59,10 +61,6 @@ irqreturn_t snd_sb8dsp_midi_interrupt(struct snd_sb * chip)
59 return IRQ_HANDLED; 61 return IRQ_HANDLED;
60} 62}
61 63
62/*
63
64 */
65
66static int snd_sb8dsp_midi_input_open(struct snd_rawmidi_substream *substream) 64static int snd_sb8dsp_midi_input_open(struct snd_rawmidi_substream *substream)
67{ 65{
68 unsigned long flags; 66 unsigned long flags;
@@ -252,10 +250,6 @@ static void snd_sb8dsp_midi_output_trigger(struct snd_rawmidi_substream *substre
252 snd_sb8dsp_midi_output_write(substream); 250 snd_sb8dsp_midi_output_write(substream);
253} 251}
254 252
255/*
256
257 */
258
259static struct snd_rawmidi_ops snd_sb8dsp_midi_output = 253static struct snd_rawmidi_ops snd_sb8dsp_midi_output =
260{ 254{
261 .open = snd_sb8dsp_midi_output_open, 255 .open = snd_sb8dsp_midi_output_open,
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c
index d2a856f0fde2..27271c9446dc 100644
--- a/sound/isa/sscape.c
+++ b/sound/isa/sscape.c
@@ -897,10 +897,9 @@ static int __devinit create_mpu401(struct snd_card *card, int devnum, unsigned l
897 struct snd_rawmidi *rawmidi; 897 struct snd_rawmidi *rawmidi;
898 int err; 898 int err;
899 899
900#define MPU401_SHARE_HARDWARE 1
901 if ((err = snd_mpu401_uart_new(card, devnum, 900 if ((err = snd_mpu401_uart_new(card, devnum,
902 MPU401_HW_MPU401, 901 MPU401_HW_MPU401,
903 port, MPU401_SHARE_HARDWARE, 902 port, MPU401_INFO_INTEGRATED,
904 irq, SA_INTERRUPT, 903 irq, SA_INTERRUPT,
905 &rawmidi)) == 0) { 904 &rawmidi)) == 0) {
906 struct snd_mpu401 *mpu = (struct snd_mpu401 *) rawmidi->private_data; 905 struct snd_mpu401 *mpu = (struct snd_mpu401 *) rawmidi->private_data;
diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c
index 7ae86f82c3fa..9eb27082c659 100644
--- a/sound/isa/wavefront/wavefront.c
+++ b/sound/isa/wavefront/wavefront.c
@@ -50,7 +50,7 @@ static int ics2115_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 2,9,11,12,15 */
50static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ 50static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
51static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ 51static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */
52static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ 52static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */
53static int use_cs4232_midi[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; 53static int use_cs4232_midi[SNDRV_CARDS];
54 54
55module_param_array(index, int, NULL, 0444); 55module_param_array(index, int, NULL, 0444);
56MODULE_PARM_DESC(index, "Index value for WaveFront soundcard."); 56MODULE_PARM_DESC(index, "Index value for WaveFront soundcard.");
diff --git a/sound/oss/Kconfig b/sound/oss/Kconfig
index 558c6ed443be..080ab036b67a 100644
--- a/sound/oss/Kconfig
+++ b/sound/oss/Kconfig
@@ -98,8 +98,8 @@ config SOUND_HAL2
98 tristate "SGI HAL2 sound (EXPERIMENTAL)" 98 tristate "SGI HAL2 sound (EXPERIMENTAL)"
99 depends on SOUND_PRIME && SGI_IP22 && EXPERIMENTAL 99 depends on SOUND_PRIME && SGI_IP22 && EXPERIMENTAL
100 help 100 help
101 Say Y or M if you have an SGI Indy system and want to be able to 101 Say Y or M if you have an SGI Indy or Indigo2 system and want to be able to
102 use it's on-board A2 audio system. 102 use its on-board A2 audio system.
103 103
104config SOUND_IT8172 104config SOUND_IT8172
105 tristate "IT8172G Sound" 105 tristate "IT8172G Sound"
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index a2081803a827..d37346b12dc0 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -216,14 +216,19 @@ config SND_CS46XX_NEW_DSP
216 This works better than the old code, so say Y. 216 This works better than the old code, so say Y.
217 217
218config SND_CS5535AUDIO 218config SND_CS5535AUDIO
219 tristate "CS5535 Audio" 219 tristate "CS5535/CS5536 Audio"
220 depends on SND && X86 && !X86_64 220 depends on SND && X86 && !X86_64
221 select SND_PCM 221 select SND_PCM
222 select SND_AC97_CODEC 222 select SND_AC97_CODEC
223 help 223 help
224 Say Y here to include support for audio on CS5535 chips. It is 224 Say Y here to include support for audio on CS5535 chips. It is
225 referred to as NS CS5535 IO or AMD CS5535 IO companion in 225 referred to as NS CS5535 IO or AMD CS5535 IO companion in
226 various literature. 226 various literature. This driver also supports the CS5536 audio
227 device. However, for both chips, on certain boards, you may
228 need to use ac97_quirk=hp_only if your board has physically
229 mapped headphone out to master output. If that works for you,
230 send lspci -vvv output to the mailing list so that your board
231 can be identified in the quirks list.
227 232
228 To compile this driver as a module, choose M here: the module 233 To compile this driver as a module, choose M here: the module
229 will be called snd-cs5535audio. 234 will be called snd-cs5535audio.
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
index d05200741ac3..0abf2808d59f 100644
--- a/sound/pci/ac97/ac97_codec.c
+++ b/sound/pci/ac97/ac97_codec.c
@@ -253,6 +253,8 @@ void snd_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short va
253 ac97->bus->ops->write(ac97, reg, value); 253 ac97->bus->ops->write(ac97, reg, value);
254} 254}
255 255
256EXPORT_SYMBOL(snd_ac97_write);
257
256/** 258/**
257 * snd_ac97_read - read a value from the given register 259 * snd_ac97_read - read a value from the given register
258 * 260 *
@@ -281,6 +283,8 @@ static inline unsigned short snd_ac97_read_cache(struct snd_ac97 *ac97, unsigned
281 return ac97->regs[reg]; 283 return ac97->regs[reg];
282} 284}
283 285
286EXPORT_SYMBOL(snd_ac97_read);
287
284/** 288/**
285 * snd_ac97_write_cache - write a value on the given register and update the cache 289 * snd_ac97_write_cache - write a value on the given register and update the cache
286 * @ac97: the ac97 instance 290 * @ac97: the ac97 instance
@@ -302,6 +306,8 @@ void snd_ac97_write_cache(struct snd_ac97 *ac97, unsigned short reg, unsigned sh
302 mutex_unlock(&ac97->reg_mutex); 306 mutex_unlock(&ac97->reg_mutex);
303} 307}
304 308
309EXPORT_SYMBOL(snd_ac97_write_cache);
310
305/** 311/**
306 * snd_ac97_update - update the value on the given register 312 * snd_ac97_update - update the value on the given register
307 * @ac97: the ac97 instance 313 * @ac97: the ac97 instance
@@ -331,6 +337,8 @@ int snd_ac97_update(struct snd_ac97 *ac97, unsigned short reg, unsigned short va
331 return change; 337 return change;
332} 338}
333 339
340EXPORT_SYMBOL(snd_ac97_update);
341
334/** 342/**
335 * snd_ac97_update_bits - update the bits on the given register 343 * snd_ac97_update_bits - update the bits on the given register
336 * @ac97: the ac97 instance 344 * @ac97: the ac97 instance
@@ -356,6 +364,8 @@ int snd_ac97_update_bits(struct snd_ac97 *ac97, unsigned short reg, unsigned sho
356 return change; 364 return change;
357} 365}
358 366
367EXPORT_SYMBOL(snd_ac97_update_bits);
368
359/* no lock version - see snd_ac97_updat_bits() */ 369/* no lock version - see snd_ac97_updat_bits() */
360int snd_ac97_update_bits_nolock(struct snd_ac97 *ac97, unsigned short reg, 370int snd_ac97_update_bits_nolock(struct snd_ac97 *ac97, unsigned short reg,
361 unsigned short mask, unsigned short value) 371 unsigned short mask, unsigned short value)
@@ -563,7 +573,7 @@ AC97_SINGLE("PC Speaker Playback Volume", AC97_PC_BEEP, 1, 15, 1)
563}; 573};
564 574
565static const struct snd_kcontrol_new snd_ac97_controls_mic_boost = 575static const struct snd_kcontrol_new snd_ac97_controls_mic_boost =
566 AC97_SINGLE("Mic Boost (+20dB)", AC97_MIC, 6, 1, 0); 576 AC97_SINGLE("Mic Boost (+20dB) Switch", AC97_MIC, 6, 1, 0);
567 577
568 578
569static const char* std_rec_sel[] = {"Mic", "CD", "Video", "Aux", "Line", "Mix", "Mix Mono", "Phone"}; 579static const char* std_rec_sel[] = {"Mic", "CD", "Video", "Aux", "Line", "Mix", "Mix Mono", "Phone"};
@@ -605,7 +615,7 @@ AC97_SINGLE("Simulated Stereo Enhancement", AC97_GENERAL_PURPOSE, 14, 1, 0),
605AC97_SINGLE("3D Control - Switch", AC97_GENERAL_PURPOSE, 13, 1, 0), 615AC97_SINGLE("3D Control - Switch", AC97_GENERAL_PURPOSE, 13, 1, 0),
606AC97_SINGLE("Loudness (bass boost)", AC97_GENERAL_PURPOSE, 12, 1, 0), 616AC97_SINGLE("Loudness (bass boost)", AC97_GENERAL_PURPOSE, 12, 1, 0),
607AC97_ENUM("Mono Output Select", std_enum[2]), 617AC97_ENUM("Mono Output Select", std_enum[2]),
608AC97_ENUM("Mic Select", std_enum[3]), 618AC97_ENUM("Mic Select Capture Switch", std_enum[3]),
609AC97_SINGLE("ADC/DAC Loopback", AC97_GENERAL_PURPOSE, 7, 1, 0) 619AC97_SINGLE("ADC/DAC Loopback", AC97_GENERAL_PURPOSE, 7, 1, 0)
610}; 620};
611 621
@@ -1226,7 +1236,8 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97)
1226 ac97->regs[AC97_CENTER_LFE_MASTER] = 0x8080; 1236 ac97->regs[AC97_CENTER_LFE_MASTER] = 0x8080;
1227 1237
1228 /* build center controls */ 1238 /* build center controls */
1229 if (snd_ac97_try_volume_mix(ac97, AC97_CENTER_LFE_MASTER)) { 1239 if ((snd_ac97_try_volume_mix(ac97, AC97_CENTER_LFE_MASTER))
1240 && !(ac97->flags & AC97_AD_MULTI)) {
1230 if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_center[0], ac97))) < 0) 1241 if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_center[0], ac97))) < 0)
1231 return err; 1242 return err;
1232 if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_center[1], ac97))) < 0) 1243 if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_center[1], ac97))) < 0)
@@ -1238,7 +1249,8 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97)
1238 } 1249 }
1239 1250
1240 /* build LFE controls */ 1251 /* build LFE controls */
1241 if (snd_ac97_try_volume_mix(ac97, AC97_CENTER_LFE_MASTER+1)) { 1252 if ((snd_ac97_try_volume_mix(ac97, AC97_CENTER_LFE_MASTER+1))
1253 && !(ac97->flags & AC97_AD_MULTI)) {
1242 if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_lfe[0], ac97))) < 0) 1254 if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_lfe[0], ac97))) < 0)
1243 return err; 1255 return err;
1244 if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_lfe[1], ac97))) < 0) 1256 if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_lfe[1], ac97))) < 0)
@@ -1250,7 +1262,8 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97)
1250 } 1262 }
1251 1263
1252 /* build surround controls */ 1264 /* build surround controls */
1253 if (snd_ac97_try_volume_mix(ac97, AC97_SURROUND_MASTER)) { 1265 if ((snd_ac97_try_volume_mix(ac97, AC97_SURROUND_MASTER))
1266 && !(ac97->flags & AC97_AD_MULTI)) {
1254 /* Surround Master (0x38) is with stereo mutes */ 1267 /* Surround Master (0x38) is with stereo mutes */
1255 if ((err = snd_ac97_cmix_new_stereo(card, "Surround Playback", AC97_SURROUND_MASTER, 1, ac97)) < 0) 1268 if ((err = snd_ac97_cmix_new_stereo(card, "Surround Playback", AC97_SURROUND_MASTER, 1, ac97)) < 0)
1256 return err; 1269 return err;
@@ -1335,9 +1348,11 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97)
1335 } 1348 }
1336 1349
1337 /* build Aux controls */ 1350 /* build Aux controls */
1338 if (snd_ac97_try_volume_mix(ac97, AC97_AUX)) { 1351 if (!(ac97->flags & AC97_HAS_NO_AUX)) {
1339 if ((err = snd_ac97_cmix_new(card, "Aux Playback", AC97_AUX, ac97)) < 0) 1352 if (snd_ac97_try_volume_mix(ac97, AC97_AUX)) {
1340 return err; 1353 if ((err = snd_ac97_cmix_new(card, "Aux Playback", AC97_AUX, ac97)) < 0)
1354 return err;
1355 }
1341 } 1356 }
1342 1357
1343 /* build PCM controls */ 1358 /* build PCM controls */
@@ -1682,6 +1697,7 @@ const char *snd_ac97_get_short_name(struct snd_ac97 *ac97)
1682 return "unknown codec"; 1697 return "unknown codec";
1683} 1698}
1684 1699
1700EXPORT_SYMBOL(snd_ac97_get_short_name);
1685 1701
1686/* wait for a while until registers are accessible after RESET 1702/* wait for a while until registers are accessible after RESET
1687 * return 0 if ok, negative not ready 1703 * return 0 if ok, negative not ready
@@ -1774,6 +1790,8 @@ int snd_ac97_bus(struct snd_card *card, int num, struct snd_ac97_bus_ops *ops,
1774 return 0; 1790 return 0;
1775} 1791}
1776 1792
1793EXPORT_SYMBOL(snd_ac97_bus);
1794
1777/* stop no dev release warning */ 1795/* stop no dev release warning */
1778static void ac97_device_release(struct device * dev) 1796static void ac97_device_release(struct device * dev)
1779{ 1797{
@@ -2117,6 +2135,7 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template,
2117 return 0; 2135 return 0;
2118} 2136}
2119 2137
2138EXPORT_SYMBOL(snd_ac97_mixer);
2120 2139
2121/* 2140/*
2122 * Power down the chip. 2141 * Power down the chip.
@@ -2166,6 +2185,8 @@ void snd_ac97_suspend(struct snd_ac97 *ac97)
2166 snd_ac97_powerdown(ac97); 2185 snd_ac97_powerdown(ac97);
2167} 2186}
2168 2187
2188EXPORT_SYMBOL(snd_ac97_suspend);
2189
2169/* 2190/*
2170 * restore ac97 status 2191 * restore ac97 status
2171 */ 2192 */
@@ -2267,6 +2288,8 @@ __reset_ready:
2267 snd_ac97_restore_iec958(ac97); 2288 snd_ac97_restore_iec958(ac97);
2268 } 2289 }
2269} 2290}
2291
2292EXPORT_SYMBOL(snd_ac97_resume);
2270#endif 2293#endif
2271 2294
2272 2295
@@ -2590,29 +2613,7 @@ int snd_ac97_tune_hardware(struct snd_ac97 *ac97, struct ac97_quirk *quirk, cons
2590 return 0; 2613 return 0;
2591} 2614}
2592 2615
2593
2594/*
2595 * Exported symbols
2596 */
2597
2598EXPORT_SYMBOL(snd_ac97_write);
2599EXPORT_SYMBOL(snd_ac97_read);
2600EXPORT_SYMBOL(snd_ac97_write_cache);
2601EXPORT_SYMBOL(snd_ac97_update);
2602EXPORT_SYMBOL(snd_ac97_update_bits);
2603EXPORT_SYMBOL(snd_ac97_get_short_name);
2604EXPORT_SYMBOL(snd_ac97_bus);
2605EXPORT_SYMBOL(snd_ac97_mixer);
2606EXPORT_SYMBOL(snd_ac97_pcm_assign);
2607EXPORT_SYMBOL(snd_ac97_pcm_open);
2608EXPORT_SYMBOL(snd_ac97_pcm_close);
2609EXPORT_SYMBOL(snd_ac97_pcm_double_rate_rules);
2610EXPORT_SYMBOL(snd_ac97_tune_hardware); 2616EXPORT_SYMBOL(snd_ac97_tune_hardware);
2611EXPORT_SYMBOL(snd_ac97_set_rate);
2612#ifdef CONFIG_PM
2613EXPORT_SYMBOL(snd_ac97_resume);
2614EXPORT_SYMBOL(snd_ac97_suspend);
2615#endif
2616 2617
2617/* 2618/*
2618 * INIT part 2619 * INIT part
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
index 4d9cf37300f7..7f197c780816 100644
--- a/sound/pci/ac97/ac97_patch.c
+++ b/sound/pci/ac97/ac97_patch.c
@@ -464,6 +464,10 @@ int patch_wolfson05(struct snd_ac97 * ac97)
464{ 464{
465 /* WM9705, WM9710 */ 465 /* WM9705, WM9710 */
466 ac97->build_ops = &patch_wolfson_wm9705_ops; 466 ac97->build_ops = &patch_wolfson_wm9705_ops;
467#ifdef CONFIG_TOUCHSCREEN_WM9705
468 /* WM9705 touchscreen uses AUX and VIDEO for touch */
469 ac97->flags |=3D AC97_HAS_NO_VIDEO | AC97_HAS_NO_AUX;
470#endif
467 return 0; 471 return 0;
468} 472}
469 473
@@ -1367,6 +1371,13 @@ static void ad18xx_resume(struct snd_ac97 *ac97)
1367 1371
1368 snd_ac97_restore_iec958(ac97); 1372 snd_ac97_restore_iec958(ac97);
1369} 1373}
1374
1375static void ad1888_resume(struct snd_ac97 *ac97)
1376{
1377 ad18xx_resume(ac97);
1378 snd_ac97_write_cache(ac97, AC97_CODEC_CLASS_REV, 0x8080);
1379}
1380
1370#endif 1381#endif
1371 1382
1372int patch_ad1819(struct snd_ac97 * ac97) 1383int patch_ad1819(struct snd_ac97 * ac97)
@@ -1627,6 +1638,7 @@ static const struct snd_kcontrol_new snd_ac97_ad1981x_jack_sense[] = {
1627 * (SS vendor << 16 | device) 1638 * (SS vendor << 16 | device)
1628 */ 1639 */
1629static unsigned int ad1981_jacks_blacklist[] = { 1640static unsigned int ad1981_jacks_blacklist[] = {
1641 0x10140537, /* Thinkpad T41p */
1630 0x10140554, /* Thinkpad T42p/R50p */ 1642 0x10140554, /* Thinkpad T42p/R50p */
1631 0 /* end */ 1643 0 /* end */
1632}; 1644};
@@ -1839,7 +1851,7 @@ static struct snd_ac97_build_ops patch_ad1888_build_ops = {
1839 .build_post_spdif = patch_ad198x_post_spdif, 1851 .build_post_spdif = patch_ad198x_post_spdif,
1840 .build_specific = patch_ad1888_specific, 1852 .build_specific = patch_ad1888_specific,
1841#ifdef CONFIG_PM 1853#ifdef CONFIG_PM
1842 .resume = ad18xx_resume, 1854 .resume = ad1888_resume,
1843#endif 1855#endif
1844 .update_jacks = ad1888_update_jacks, 1856 .update_jacks = ad1888_update_jacks,
1845}; 1857};
@@ -2048,7 +2060,10 @@ int patch_alc650(struct snd_ac97 * ac97)
2048 /* Enable SPDIF-IN only on Rev.E and above */ 2060 /* Enable SPDIF-IN only on Rev.E and above */
2049 val = snd_ac97_read(ac97, AC97_ALC650_CLOCK); 2061 val = snd_ac97_read(ac97, AC97_ALC650_CLOCK);
2050 /* SPDIF IN with pin 47 */ 2062 /* SPDIF IN with pin 47 */
2051 if (ac97->spec.dev_flags) 2063 if (ac97->spec.dev_flags &&
2064 /* ASUS A6KM requires EAPD */
2065 ! (ac97->subsystem_vendor == 0x1043 &&
2066 ac97->subsystem_device == 0x1103))
2052 val |= 0x03; /* enable */ 2067 val |= 0x03; /* enable */
2053 else 2068 else
2054 val &= ~0x03; /* disable */ 2069 val &= ~0x03; /* disable */
diff --git a/sound/pci/ac97/ac97_pcm.c b/sound/pci/ac97/ac97_pcm.c
index 512a3583b0ce..f684aa2c0067 100644
--- a/sound/pci/ac97/ac97_pcm.c
+++ b/sound/pci/ac97/ac97_pcm.c
@@ -317,6 +317,8 @@ int snd_ac97_set_rate(struct snd_ac97 *ac97, int reg, unsigned int rate)
317 return 0; 317 return 0;
318} 318}
319 319
320EXPORT_SYMBOL(snd_ac97_set_rate);
321
320static unsigned short get_pslots(struct snd_ac97 *ac97, unsigned char *rate_table, unsigned short *spdif_slots) 322static unsigned short get_pslots(struct snd_ac97 *ac97, unsigned char *rate_table, unsigned short *spdif_slots)
321{ 323{
322 if (!ac97_is_audio(ac97)) 324 if (!ac97_is_audio(ac97))
@@ -550,6 +552,8 @@ int snd_ac97_pcm_assign(struct snd_ac97_bus *bus,
550 return 0; 552 return 0;
551} 553}
552 554
555EXPORT_SYMBOL(snd_ac97_pcm_assign);
556
553/** 557/**
554 * snd_ac97_pcm_open - opens the given AC97 pcm 558 * snd_ac97_pcm_open - opens the given AC97 pcm
555 * @pcm: the ac97 pcm instance 559 * @pcm: the ac97 pcm instance
@@ -633,6 +637,8 @@ int snd_ac97_pcm_open(struct ac97_pcm *pcm, unsigned int rate,
633 return err; 637 return err;
634} 638}
635 639
640EXPORT_SYMBOL(snd_ac97_pcm_open);
641
636/** 642/**
637 * snd_ac97_pcm_close - closes the given AC97 pcm 643 * snd_ac97_pcm_close - closes the given AC97 pcm
638 * @pcm: the ac97 pcm instance 644 * @pcm: the ac97 pcm instance
@@ -658,6 +664,8 @@ int snd_ac97_pcm_close(struct ac97_pcm *pcm)
658 return 0; 664 return 0;
659} 665}
660 666
667EXPORT_SYMBOL(snd_ac97_pcm_close);
668
661static int double_rate_hw_constraint_rate(struct snd_pcm_hw_params *params, 669static int double_rate_hw_constraint_rate(struct snd_pcm_hw_params *params,
662 struct snd_pcm_hw_rule *rule) 670 struct snd_pcm_hw_rule *rule)
663{ 671{
@@ -709,3 +717,5 @@ int snd_ac97_pcm_double_rate_rules(struct snd_pcm_runtime *runtime)
709 SNDRV_PCM_HW_PARAM_RATE, -1); 717 SNDRV_PCM_HW_PARAM_RATE, -1);
710 return err; 718 return err;
711} 719}
720
721EXPORT_SYMBOL(snd_ac97_pcm_double_rate_rules);
diff --git a/sound/pci/ac97/ac97_proc.c b/sound/pci/ac97/ac97_proc.c
index 4d523df79cc7..2118df50b9d6 100644
--- a/sound/pci/ac97/ac97_proc.c
+++ b/sound/pci/ac97/ac97_proc.c
@@ -433,7 +433,7 @@ void snd_ac97_proc_init(struct snd_ac97 * ac97)
433 prefix = ac97_is_audio(ac97) ? "ac97" : "mc97"; 433 prefix = ac97_is_audio(ac97) ? "ac97" : "mc97";
434 sprintf(name, "%s#%d-%d", prefix, ac97->addr, ac97->num); 434 sprintf(name, "%s#%d-%d", prefix, ac97->addr, ac97->num);
435 if ((entry = snd_info_create_card_entry(ac97->bus->card, name, ac97->bus->proc)) != NULL) { 435 if ((entry = snd_info_create_card_entry(ac97->bus->card, name, ac97->bus->proc)) != NULL) {
436 snd_info_set_text_ops(entry, ac97, 1024, snd_ac97_proc_read); 436 snd_info_set_text_ops(entry, ac97, snd_ac97_proc_read);
437 if (snd_info_register(entry) < 0) { 437 if (snd_info_register(entry) < 0) {
438 snd_info_free_entry(entry); 438 snd_info_free_entry(entry);
439 entry = NULL; 439 entry = NULL;
@@ -442,10 +442,9 @@ void snd_ac97_proc_init(struct snd_ac97 * ac97)
442 ac97->proc = entry; 442 ac97->proc = entry;
443 sprintf(name, "%s#%d-%d+regs", prefix, ac97->addr, ac97->num); 443 sprintf(name, "%s#%d-%d+regs", prefix, ac97->addr, ac97->num);
444 if ((entry = snd_info_create_card_entry(ac97->bus->card, name, ac97->bus->proc)) != NULL) { 444 if ((entry = snd_info_create_card_entry(ac97->bus->card, name, ac97->bus->proc)) != NULL) {
445 snd_info_set_text_ops(entry, ac97, 1024, snd_ac97_proc_regs_read); 445 snd_info_set_text_ops(entry, ac97, snd_ac97_proc_regs_read);
446#ifdef CONFIG_SND_DEBUG 446#ifdef CONFIG_SND_DEBUG
447 entry->mode |= S_IWUSR; 447 entry->mode |= S_IWUSR;
448 entry->c.text.write_size = 1024;
449 entry->c.text.write = snd_ac97_proc_regs_write; 448 entry->c.text.write = snd_ac97_proc_regs_write;
450#endif 449#endif
451 if (snd_info_register(entry) < 0) { 450 if (snd_info_register(entry) < 0) {
diff --git a/sound/pci/ac97/ak4531_codec.c b/sound/pci/ac97/ak4531_codec.c
index 0fb7b3407312..94c26ec05882 100644
--- a/sound/pci/ac97/ak4531_codec.c
+++ b/sound/pci/ac97/ak4531_codec.c
@@ -453,7 +453,7 @@ static void snd_ak4531_proc_init(struct snd_card *card, struct snd_ak4531 *ak453
453 struct snd_info_entry *entry; 453 struct snd_info_entry *entry;
454 454
455 if (! snd_card_proc_new(card, "ak4531", &entry)) 455 if (! snd_card_proc_new(card, "ak4531", &entry))
456 snd_info_set_text_ops(entry, ak4531, 1024, snd_ak4531_proc_read); 456 snd_info_set_text_ops(entry, ak4531, snd_ak4531_proc_read);
457} 457}
458#endif 458#endif
459 459
diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c
index eece1c7e55a0..d42bf4570367 100644
--- a/sound/pci/ad1889.c
+++ b/sound/pci/ad1889.c
@@ -753,7 +753,7 @@ snd_ad1889_proc_init(struct snd_ad1889 *chip)
753 struct snd_info_entry *entry; 753 struct snd_info_entry *entry;
754 754
755 if (!snd_card_proc_new(chip->card, chip->card->driver, &entry)) 755 if (!snd_card_proc_new(chip->card, chip->card->driver, &entry))
756 snd_info_set_text_ops(entry, chip, 1024, snd_ad1889_proc_read); 756 snd_info_set_text_ops(entry, chip, snd_ad1889_proc_read);
757} 757}
758 758
759static struct ac97_quirk ac97_quirks[] = { 759static struct ac97_quirk ac97_quirks[] = {
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index e2dbc2118902..5dfdbf6657f2 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -49,7 +49,7 @@ MODULE_SUPPORTED_DEVICE("{{ALI,M5451,pci},{ALI,M5451}}");
49static int index = SNDRV_DEFAULT_IDX1; /* Index */ 49static int index = SNDRV_DEFAULT_IDX1; /* Index */
50static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ 50static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */
51static int pcm_channels = 32; 51static int pcm_channels = 32;
52static int spdif = 0; 52static int spdif;
53 53
54module_param(index, int, 0444); 54module_param(index, int, 0444);
55MODULE_PARM_DESC(index, "Index value for ALI M5451 PCI Audio."); 55MODULE_PARM_DESC(index, "Index value for ALI M5451 PCI Audio.");
@@ -2173,7 +2173,7 @@ static void __devinit snd_ali_proc_init(struct snd_ali *codec)
2173{ 2173{
2174 struct snd_info_entry *entry; 2174 struct snd_info_entry *entry;
2175 if(!snd_card_proc_new(codec->card, "ali5451", &entry)) 2175 if(!snd_card_proc_new(codec->card, "ali5451", &entry))
2176 snd_info_set_text_ops(entry, codec, 1024, snd_ali_proc_read); 2176 snd_info_set_text_ops(entry, codec, snd_ali_proc_read);
2177} 2177}
2178 2178
2179static int __devinit snd_ali_resources(struct snd_ali *codec) 2179static int __devinit snd_ali_resources(struct snd_ali *codec)
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c
index 60423b1c678b..a9f08066459a 100644
--- a/sound/pci/als4000.c
+++ b/sound/pci/als4000.c
@@ -746,8 +746,8 @@ static int __devinit snd_card_als4000_probe(struct pci_dev *pci,
746 card->shortname, chip->alt_port, chip->irq); 746 card->shortname, chip->alt_port, chip->irq);
747 747
748 if ((err = snd_mpu401_uart_new( card, 0, MPU401_HW_ALS4000, 748 if ((err = snd_mpu401_uart_new( card, 0, MPU401_HW_ALS4000,
749 gcr+0x30, 1, pci->irq, 0, 749 gcr+0x30, MPU401_INFO_INTEGRATED,
750 &chip->rmidi)) < 0) { 750 pci->irq, 0, &chip->rmidi)) < 0) {
751 printk(KERN_ERR "als4000: no MPU-401 device at 0x%lx?\n", gcr+0x30); 751 printk(KERN_ERR "als4000: no MPU-401 device at 0x%lx?\n", gcr+0x30);
752 goto out_err; 752 goto out_err;
753 } 753 }
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index d0f759d86d3d..f18a8c0e4688 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -1504,7 +1504,7 @@ static void __devinit snd_atiixp_proc_init(struct atiixp *chip)
1504 struct snd_info_entry *entry; 1504 struct snd_info_entry *entry;
1505 1505
1506 if (! snd_card_proc_new(chip->card, "atiixp", &entry)) 1506 if (! snd_card_proc_new(chip->card, "atiixp", &entry))
1507 snd_info_set_text_ops(entry, chip, 1024, snd_atiixp_proc_read); 1507 snd_info_set_text_ops(entry, chip, snd_atiixp_proc_read);
1508} 1508}
1509#else /* !CONFIG_PROC_FS */ 1509#else /* !CONFIG_PROC_FS */
1510#define snd_atiixp_proc_init(chip) 1510#define snd_atiixp_proc_init(chip)
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
index 12a34c39caa7..40739057076b 100644
--- a/sound/pci/atiixp_modem.c
+++ b/sound/pci/atiixp_modem.c
@@ -1177,7 +1177,7 @@ static void __devinit snd_atiixp_proc_init(struct atiixp_modem *chip)
1177 struct snd_info_entry *entry; 1177 struct snd_info_entry *entry;
1178 1178
1179 if (! snd_card_proc_new(chip->card, "atiixp-modem", &entry)) 1179 if (! snd_card_proc_new(chip->card, "atiixp-modem", &entry))
1180 snd_info_set_text_ops(entry, chip, 1024, snd_atiixp_proc_read); 1180 snd_info_set_text_ops(entry, chip, snd_atiixp_proc_read);
1181} 1181}
1182#else 1182#else
1183#define snd_atiixp_proc_init(chip) 1183#define snd_atiixp_proc_init(chip)
diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c
index 126870ec063a..8a3b118989bf 100644
--- a/sound/pci/au88x0/au88x0.c
+++ b/sound/pci/au88x0/au88x0.c
@@ -261,6 +261,13 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
261 return err; 261 return err;
262 } 262 }
263 snd_vortex_workaround(pci, pcifix[dev]); 263 snd_vortex_workaround(pci, pcifix[dev]);
264
265 // Card details needed in snd_vortex_midi
266 strcpy(card->driver, CARD_NAME_SHORT);
267 sprintf(card->shortname, "Aureal Vortex %s", CARD_NAME_SHORT);
268 sprintf(card->longname, "%s at 0x%lx irq %i",
269 card->shortname, chip->io, chip->irq);
270
264 // (4) Alloc components. 271 // (4) Alloc components.
265 // ADB pcm. 272 // ADB pcm.
266 if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_ADB, NR_ADB)) < 0) { 273 if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_ADB, NR_ADB)) < 0) {
@@ -323,11 +330,6 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
323#endif 330#endif
324 331
325 // (5) 332 // (5)
326 strcpy(card->driver, CARD_NAME_SHORT);
327 strcpy(card->shortname, CARD_NAME_SHORT);
328 sprintf(card->longname, "%s at 0x%lx irq %i",
329 card->shortname, chip->io, chip->irq);
330
331 if ((err = pci_read_config_word(pci, PCI_DEVICE_ID, 333 if ((err = pci_read_config_word(pci, PCI_DEVICE_ID,
332 &(chip->device))) < 0) { 334 &(chip->device))) < 0) {
333 snd_card_free(card); 335 snd_card_free(card);
diff --git a/sound/pci/au88x0/au88x0_mpu401.c b/sound/pci/au88x0/au88x0_mpu401.c
index 873f486b07b8..c75d368ea087 100644
--- a/sound/pci/au88x0/au88x0_mpu401.c
+++ b/sound/pci/au88x0/au88x0_mpu401.c
@@ -47,7 +47,7 @@ static int __devinit snd_vortex_midi(vortex_t * vortex)
47 struct snd_rawmidi *rmidi; 47 struct snd_rawmidi *rmidi;
48 int temp, mode; 48 int temp, mode;
49 struct snd_mpu401 *mpu; 49 struct snd_mpu401 *mpu;
50 int port; 50 unsigned long port;
51 51
52#ifdef VORTEX_MPU401_LEGACY 52#ifdef VORTEX_MPU401_LEGACY
53 /* EnableHardCodedMPU401Port() */ 53 /* EnableHardCodedMPU401Port() */
@@ -70,9 +70,6 @@ static int __devinit snd_vortex_midi(vortex_t * vortex)
70 temp |= (MIDI_CLOCK_DIV << 8) | ((mode >> 24) & 0xff) << 4; 70 temp |= (MIDI_CLOCK_DIV << 8) | ((mode >> 24) & 0xff) << 4;
71 hwwrite(vortex->mmio, VORTEX_CTRL2, temp); 71 hwwrite(vortex->mmio, VORTEX_CTRL2, temp);
72 hwwrite(vortex->mmio, VORTEX_MIDI_CMD, MPU401_RESET); 72 hwwrite(vortex->mmio, VORTEX_MIDI_CMD, MPU401_RESET);
73 /* Set some kind of mode */
74 if (mode)
75 hwwrite(vortex->mmio, VORTEX_MIDI_CMD, MPU401_ENTER_UART);
76 73
77 /* Check if anything is OK. */ 74 /* Check if anything is OK. */
78 temp = hwread(vortex->mmio, VORTEX_MIDI_DATA); 75 temp = hwread(vortex->mmio, VORTEX_MIDI_DATA);
@@ -98,7 +95,8 @@ static int __devinit snd_vortex_midi(vortex_t * vortex)
98 port = (unsigned long)(vortex->mmio + VORTEX_MIDI_DATA); 95 port = (unsigned long)(vortex->mmio + VORTEX_MIDI_DATA);
99 if ((temp = 96 if ((temp =
100 snd_mpu401_uart_new(vortex->card, 0, MPU401_HW_AUREAL, port, 97 snd_mpu401_uart_new(vortex->card, 0, MPU401_HW_AUREAL, port,
101 1, 0, 0, &rmidi)) != 0) { 98 MPU401_INFO_INTEGRATED | MPU401_INFO_MMIO,
99 0, 0, &rmidi)) != 0) {
102 hwwrite(vortex->mmio, VORTEX_CTRL, 100 hwwrite(vortex->mmio, VORTEX_CTRL,
103 (hwread(vortex->mmio, VORTEX_CTRL) & 101 (hwread(vortex->mmio, VORTEX_CTRL) &
104 ~CTRL_MIDI_PORT) & ~CTRL_MIDI_EN); 102 ~CTRL_MIDI_PORT) & ~CTRL_MIDI_EN);
@@ -107,6 +105,9 @@ static int __devinit snd_vortex_midi(vortex_t * vortex)
107 mpu = rmidi->private_data; 105 mpu = rmidi->private_data;
108 mpu->cport = (unsigned long)(vortex->mmio + VORTEX_MIDI_CMD); 106 mpu->cport = (unsigned long)(vortex->mmio + VORTEX_MIDI_CMD);
109#endif 107#endif
108 /* Overwrite MIDI name */
109 snprintf(rmidi->name, sizeof(rmidi->name), "%s MIDI %d", CARD_NAME_SHORT , vortex->card->number);
110
110 vortex->rmidi = rmidi; 111 vortex->rmidi = rmidi;
111 return 0; 112 return 0;
112} 113}
diff --git a/sound/pci/au88x0/au88x0_xtalk.c b/sound/pci/au88x0/au88x0_xtalk.c
index 4534e1882ada..b4151e208b71 100644
--- a/sound/pci/au88x0/au88x0_xtalk.c
+++ b/sound/pci/au88x0/au88x0_xtalk.c
@@ -66,31 +66,20 @@ static xtalk_gains_t const asXtalkGainsAllChan = {
66 0 66 0
67 //0x7FFF,0x7FFF,0x7FFF,0x7FFF,0x7fff,0x7FFF,0x7FFF,0x7FFF,0x7FFF,0x7fff 67 //0x7FFF,0x7FFF,0x7FFF,0x7FFF,0x7fff,0x7FFF,0x7FFF,0x7FFF,0x7FFF,0x7fff
68}; 68};
69static xtalk_gains_t const asXtalkGainsZeros = { 69static xtalk_gains_t const asXtalkGainsZeros;
70 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
71};
72 70
73static xtalk_dline_t const alXtalkDlineZeros = { 71static xtalk_dline_t const alXtalkDlineZeros;
74 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
75 0, 0, 0,
76 0, 0, 0, 0, 0, 0, 0
77};
78static xtalk_dline_t const alXtalkDlineTest = { 72static xtalk_dline_t const alXtalkDlineTest = {
79 0xFC18, 0x03E8FFFF, 0x186A0, 0x7960FFFE, 1, 0xFFFFFFFF, 73 0xFC18, 0x03E8FFFF, 0x186A0, 0x7960FFFE, 1, 0xFFFFFFFF,
80 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
81 0, 0, 0, 0 75 0, 0, 0, 0
82}; 76};
83 77
84static xtalk_instate_t const asXtalkInStateZeros = { 0, 0, 0, 0 }; 78static xtalk_instate_t const asXtalkInStateZeros;
85static xtalk_instate_t const asXtalkInStateTest = 79static xtalk_instate_t const asXtalkInStateTest =
86 { 0xFF80, 0x0080, 0xFFFF, 0x0001 }; 80 { 0xFF80, 0x0080, 0xFFFF, 0x0001 };
87static xtalk_state_t const asXtalkOutStateZeros = { 81static xtalk_state_t const asXtalkOutStateZeros;
88 {0, 0, 0, 0}, 82
89 {0, 0, 0, 0},
90 {0, 0, 0, 0},
91 {0, 0, 0, 0},
92 {0, 0, 0, 0}
93};
94static short const sDiamondKLeftEq = 0x401d; 83static short const sDiamondKLeftEq = 0x401d;
95static short const sDiamondKRightEq = 0x401d; 84static short const sDiamondKRightEq = 0x401d;
96static short const sDiamondKLeftXt = 0xF90E; 85static short const sDiamondKLeftXt = 0xF90E;
@@ -162,13 +151,7 @@ static xtalk_coefs_t const asXtalkNarrowCoefsRightXt = {
162 {0, 0, 0, 0, 0} 151 {0, 0, 0, 0, 0}
163}; 152};
164 153
165static xtalk_coefs_t const asXtalkCoefsZeros = { 154static xtalk_coefs_t const asXtalkCoefsZeros;
166 {0, 0, 0, 0, 0},
167 {0, 0, 0, 0, 0},
168 {0, 0, 0, 0, 0},
169 {0, 0, 0, 0, 0},
170 {0, 0, 0, 0, 0}
171};
172static xtalk_coefs_t const asXtalkCoefsPipe = { 155static xtalk_coefs_t const asXtalkCoefsPipe = {
173 {0, 0, 0x0FA0, 0, 0}, 156 {0, 0, 0x0FA0, 0, 0},
174 {0, 0, 0x0FA0, 0, 0}, 157 {0, 0, 0x0FA0, 0, 0},
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index 52a364524262..6e62dafb66cd 100644
--- a/sound/pci/azt3328.c
+++ b/sound/pci/azt3328.c
@@ -33,14 +33,21 @@
33 * in the first place >:-P}), 33 * in the first place >:-P}),
34 * I was forced to base this driver on reverse engineering 34 * I was forced to base this driver on reverse engineering
35 * (3 weeks' worth of evenings filled with driver work). 35 * (3 weeks' worth of evenings filled with driver work).
36 * (and no, I did NOT go the easy way: to pick up a PCI128 for 9 Euros) 36 * (and no, I did NOT go the easy way: to pick up a SB PCI128 for 9 Euros)
37 * 37 *
38 * The AZF3328 chip (note: AZF3328, *not* AZT3328, that's just the driver name 38 * The AZF3328 chip (note: AZF3328, *not* AZT3328, that's just the driver name
39 * for compatibility reasons) has the following features: 39 * for compatibility reasons) has the following features:
40 * 40 *
41 * - builtin AC97 conformant codec (SNR over 80dB) 41 * - builtin AC97 conformant codec (SNR over 80dB)
42 * (really AC97 compliant?? I really doubt it when looking 42 * Note that "conformant" != "compliant"!! this chip's mixer register layout
43 * at the mixer register layout) 43 * *differs* from the standard AC97 layout:
44 * they chose to not implement the headphone register (which is not a
45 * problem since it's merely optional), yet when doing this, they committed
46 * the grave sin of letting other registers follow immediately instead of
47 * keeping a headphone dummy register, thereby shifting the mixer register
48 * addresses illegally. So far unfortunately it looks like the very flexible
49 * ALSA AC97 support is still not enough to easily compensate for such a
50 * grave layout violation despite all tweaks and quirks mechanisms it offers.
44 * - builtin genuine OPL3 51 * - builtin genuine OPL3
45 * - full duplex 16bit playback/record at independent sampling rate 52 * - full duplex 16bit playback/record at independent sampling rate
46 * - MPU401 (+ legacy address support) FIXME: how to enable legacy addr?? 53 * - MPU401 (+ legacy address support) FIXME: how to enable legacy addr??
@@ -90,10 +97,15 @@
90 * 97 *
91 * TODO 98 * TODO
92 * - test MPU401 MIDI playback etc. 99 * - test MPU401 MIDI playback etc.
93 * - power management. See e.g. intel8x0 or cs4281. 100 * - add some power micro-management (disable various units of the card
94 * This would be nice since the chip runs a bit hot, and it's *required* 101 * as long as they're unused). However this requires I/O ports which I
95 * anyway for proper ACPI power management. 102 * haven't figured out yet and which thus might not even exist...
103 * The standard suspend/resume functionality could probably make use of
104 * some improvement, too...
96 * - figure out what all unknown port bits are responsible for 105 * - figure out what all unknown port bits are responsible for
106 * - figure out some cleverly evil scheme to possibly make ALSA AC97 code
107 * fully accept our quite incompatible ""AC97"" mixer and thus save some
108 * code (but I'm not too optimistic that doing this is possible at all)
97 */ 109 */
98 110
99#include <sound/driver.h> 111#include <sound/driver.h>
@@ -214,6 +226,16 @@ struct snd_azf3328 {
214 226
215 struct pci_dev *pci; 227 struct pci_dev *pci;
216 int irq; 228 int irq;
229
230#ifdef CONFIG_PM
231 /* register value containers for power management
232 * Note: not always full I/O range preserved (just like Win driver!) */
233 u16 saved_regs_codec [AZF_IO_SIZE_CODEC_PM / 2];
234 u16 saved_regs_io2 [AZF_IO_SIZE_IO2_PM / 2];
235 u16 saved_regs_mpu [AZF_IO_SIZE_MPU_PM / 2];
236 u16 saved_regs_synth[AZF_IO_SIZE_SYNTH_PM / 2];
237 u16 saved_regs_mixer[AZF_IO_SIZE_MIXER_PM / 2];
238#endif
217}; 239};
218 240
219static const struct pci_device_id snd_azf3328_ids[] __devinitdata = { 241static const struct pci_device_id snd_azf3328_ids[] __devinitdata = {
@@ -317,10 +339,8 @@ snd_azf3328_mixer_write_volume_gradually(const struct snd_azf3328 *chip, int reg
317 else 339 else
318 dst_vol_left &= ~0x80; 340 dst_vol_left &= ~0x80;
319 341
320 do 342 do {
321 { 343 if (!left_done) {
322 if (!left_done)
323 {
324 if (curr_vol_left > dst_vol_left) 344 if (curr_vol_left > dst_vol_left)
325 curr_vol_left--; 345 curr_vol_left--;
326 else 346 else
@@ -330,8 +350,7 @@ snd_azf3328_mixer_write_volume_gradually(const struct snd_azf3328 *chip, int reg
330 left_done = 1; 350 left_done = 1;
331 outb(curr_vol_left, portbase + 1); 351 outb(curr_vol_left, portbase + 1);
332 } 352 }
333 if (!right_done) 353 if (!right_done) {
334 {
335 if (curr_vol_right > dst_vol_right) 354 if (curr_vol_right > dst_vol_right)
336 curr_vol_right--; 355 curr_vol_right--;
337 else 356 else
@@ -346,8 +365,7 @@ snd_azf3328_mixer_write_volume_gradually(const struct snd_azf3328 *chip, int reg
346 } 365 }
347 if (delay) 366 if (delay)
348 mdelay(delay); 367 mdelay(delay);
349 } 368 } while ((!left_done) || (!right_done));
350 while ((!left_done) || (!right_done));
351 snd_azf3328_dbgcallleave(); 369 snd_azf3328_dbgcallleave();
352} 370}
353 371
@@ -514,15 +532,18 @@ snd_azf3328_info_mixer_enum(struct snd_kcontrol *kcontrol,
514 struct snd_ctl_elem_info *uinfo) 532 struct snd_ctl_elem_info *uinfo)
515{ 533{
516 static const char * const texts1[] = { 534 static const char * const texts1[] = {
517 "ModemOut1", "ModemOut2" 535 "Mic1", "Mic2"
518 }; 536 };
519 static const char * const texts2[] = { 537 static const char * const texts2[] = {
520 "MonoSelectSource1", "MonoSelectSource2" 538 "Mix", "Mic"
521 }; 539 };
522 static const char * const texts3[] = { 540 static const char * const texts3[] = {
523 "Mic", "CD", "Video", "Aux", 541 "Mic", "CD", "Video", "Aux",
524 "Line", "Mix", "Mix Mono", "Phone" 542 "Line", "Mix", "Mix Mono", "Phone"
525 }; 543 };
544 static const char * const texts4[] = {
545 "pre 3D", "post 3D"
546 };
526 struct azf3328_mixer_reg reg; 547 struct azf3328_mixer_reg reg;
527 548
528 snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value); 549 snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value);
@@ -531,14 +552,19 @@ snd_azf3328_info_mixer_enum(struct snd_kcontrol *kcontrol,
531 uinfo->value.enumerated.items = reg.enum_c; 552 uinfo->value.enumerated.items = reg.enum_c;
532 if (uinfo->value.enumerated.item > reg.enum_c - 1U) 553 if (uinfo->value.enumerated.item > reg.enum_c - 1U)
533 uinfo->value.enumerated.item = reg.enum_c - 1U; 554 uinfo->value.enumerated.item = reg.enum_c - 1U;
534 if (reg.reg == IDX_MIXER_ADVCTL2) 555 if (reg.reg == IDX_MIXER_ADVCTL2) {
535 { 556 switch(reg.lchan_shift) {
536 if (reg.lchan_shift == 8) /* modem out sel */ 557 case 8: /* modem out sel */
537 strcpy(uinfo->value.enumerated.name, texts1[uinfo->value.enumerated.item]); 558 strcpy(uinfo->value.enumerated.name, texts1[uinfo->value.enumerated.item]);
538 else /* mono sel source */ 559 break;
560 case 9: /* mono sel source */
539 strcpy(uinfo->value.enumerated.name, texts2[uinfo->value.enumerated.item]); 561 strcpy(uinfo->value.enumerated.name, texts2[uinfo->value.enumerated.item]);
540 } 562 break;
541 else 563 case 15: /* PCM Out Path */
564 strcpy(uinfo->value.enumerated.name, texts4[uinfo->value.enumerated.item]);
565 break;
566 }
567 } else
542 strcpy(uinfo->value.enumerated.name, texts3[uinfo->value.enumerated.item] 568 strcpy(uinfo->value.enumerated.name, texts3[uinfo->value.enumerated.item]
543); 569);
544 return 0; 570 return 0;
@@ -554,12 +580,10 @@ snd_azf3328_get_mixer_enum(struct snd_kcontrol *kcontrol,
554 580
555 snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value); 581 snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value);
556 val = snd_azf3328_mixer_inw(chip, reg.reg); 582 val = snd_azf3328_mixer_inw(chip, reg.reg);
557 if (reg.reg == IDX_MIXER_REC_SELECT) 583 if (reg.reg == IDX_MIXER_REC_SELECT) {
558 {
559 ucontrol->value.enumerated.item[0] = (val >> 8) & (reg.enum_c - 1); 584 ucontrol->value.enumerated.item[0] = (val >> 8) & (reg.enum_c - 1);
560 ucontrol->value.enumerated.item[1] = (val >> 0) & (reg.enum_c - 1); 585 ucontrol->value.enumerated.item[1] = (val >> 0) & (reg.enum_c - 1);
561 } 586 } else
562 else
563 ucontrol->value.enumerated.item[0] = (val >> reg.lchan_shift) & (reg.enum_c - 1); 587 ucontrol->value.enumerated.item[0] = (val >> reg.lchan_shift) & (reg.enum_c - 1);
564 588
565 snd_azf3328_dbgmixer("get_enum: %02x is %04x -> %d|%d (shift %02d, enum_c %d)\n", 589 snd_azf3328_dbgmixer("get_enum: %02x is %04x -> %d|%d (shift %02d, enum_c %d)\n",
@@ -579,16 +603,13 @@ snd_azf3328_put_mixer_enum(struct snd_kcontrol *kcontrol,
579 snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value); 603 snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value);
580 oreg = snd_azf3328_mixer_inw(chip, reg.reg); 604 oreg = snd_azf3328_mixer_inw(chip, reg.reg);
581 val = oreg; 605 val = oreg;
582 if (reg.reg == IDX_MIXER_REC_SELECT) 606 if (reg.reg == IDX_MIXER_REC_SELECT) {
583 {
584 if (ucontrol->value.enumerated.item[0] > reg.enum_c - 1U || 607 if (ucontrol->value.enumerated.item[0] > reg.enum_c - 1U ||
585 ucontrol->value.enumerated.item[1] > reg.enum_c - 1U) 608 ucontrol->value.enumerated.item[1] > reg.enum_c - 1U)
586 return -EINVAL; 609 return -EINVAL;
587 val = (ucontrol->value.enumerated.item[0] << 8) | 610 val = (ucontrol->value.enumerated.item[0] << 8) |
588 (ucontrol->value.enumerated.item[1] << 0); 611 (ucontrol->value.enumerated.item[1] << 0);
589 } 612 } else {
590 else
591 {
592 if (ucontrol->value.enumerated.item[0] > reg.enum_c - 1U) 613 if (ucontrol->value.enumerated.item[0] > reg.enum_c - 1U)
593 return -EINVAL; 614 return -EINVAL;
594 val &= ~((reg.enum_c - 1) << reg.lchan_shift); 615 val &= ~((reg.enum_c - 1) << reg.lchan_shift);
@@ -629,13 +650,14 @@ static const struct snd_kcontrol_new snd_azf3328_mixer_controls[] __devinitdata
629 AZF3328_MIXER_VOL_MONO("Modem Playback Volume", IDX_MIXER_MODEMOUT, 0x1f, 1), 650 AZF3328_MIXER_VOL_MONO("Modem Playback Volume", IDX_MIXER_MODEMOUT, 0x1f, 1),
630 AZF3328_MIXER_SWITCH("Modem Capture Switch", IDX_MIXER_MODEMIN, 15, 1), 651 AZF3328_MIXER_SWITCH("Modem Capture Switch", IDX_MIXER_MODEMIN, 15, 1),
631 AZF3328_MIXER_VOL_MONO("Modem Capture Volume", IDX_MIXER_MODEMIN, 0x1f, 1), 652 AZF3328_MIXER_VOL_MONO("Modem Capture Volume", IDX_MIXER_MODEMIN, 0x1f, 1),
632 AZF3328_MIXER_ENUM("Modem Out Select", IDX_MIXER_ADVCTL2, 2, 8), 653 AZF3328_MIXER_ENUM("Mic Select", IDX_MIXER_ADVCTL2, 2, 8),
633 AZF3328_MIXER_ENUM("Mono Select Source", IDX_MIXER_ADVCTL2, 2, 9), 654 AZF3328_MIXER_ENUM("Mono Output Select", IDX_MIXER_ADVCTL2, 2, 9),
655 AZF3328_MIXER_ENUM("PCM", IDX_MIXER_ADVCTL2, 2, 15), /* PCM Out Path, place in front since it controls *both* 3D and Bass/Treble! */
634 AZF3328_MIXER_VOL_SPECIAL("Tone Control - Treble", IDX_MIXER_BASSTREBLE, 0x07, 1, 0), 656 AZF3328_MIXER_VOL_SPECIAL("Tone Control - Treble", IDX_MIXER_BASSTREBLE, 0x07, 1, 0),
635 AZF3328_MIXER_VOL_SPECIAL("Tone Control - Bass", IDX_MIXER_BASSTREBLE, 0x07, 9, 0), 657 AZF3328_MIXER_VOL_SPECIAL("Tone Control - Bass", IDX_MIXER_BASSTREBLE, 0x07, 9, 0),
636 AZF3328_MIXER_SWITCH("3D Control - Switch", IDX_MIXER_ADVCTL2, 13, 0), 658 AZF3328_MIXER_SWITCH("3D Control - Switch", IDX_MIXER_ADVCTL2, 13, 0),
637 AZF3328_MIXER_VOL_SPECIAL("3D Control - Wide", IDX_MIXER_ADVCTL1, 0x07, 1, 0), /* "3D Width" */ 659 AZF3328_MIXER_VOL_SPECIAL("3D Control - Width", IDX_MIXER_ADVCTL1, 0x07, 1, 0), /* "3D Width" */
638 AZF3328_MIXER_VOL_SPECIAL("3D Control - Space", IDX_MIXER_ADVCTL1, 0x03, 8, 0), /* "Hifi 3D" */ 660 AZF3328_MIXER_VOL_SPECIAL("3D Control - Depth", IDX_MIXER_ADVCTL1, 0x03, 8, 0), /* "Hifi 3D" */
639#if MIXER_TESTING 661#if MIXER_TESTING
640 AZF3328_MIXER_SWITCH("0", IDX_MIXER_ADVCTL2, 0, 0), 662 AZF3328_MIXER_SWITCH("0", IDX_MIXER_ADVCTL2, 0, 0),
641 AZF3328_MIXER_SWITCH("1", IDX_MIXER_ADVCTL2, 1, 0), 663 AZF3328_MIXER_SWITCH("1", IDX_MIXER_ADVCTL2, 1, 0),
@@ -813,22 +835,18 @@ snd_azf3328_setdmaa(struct snd_azf3328 *chip,
813 unsigned int is_running; 835 unsigned int is_running;
814 836
815 snd_azf3328_dbgcallenter(); 837 snd_azf3328_dbgcallenter();
816 if (do_recording) 838 if (do_recording) {
817 {
818 /* access capture registers, i.e. skip playback reg section */ 839 /* access capture registers, i.e. skip playback reg section */
819 portbase = chip->codec_port + 0x20; 840 portbase = chip->codec_port + 0x20;
820 is_running = chip->is_recording; 841 is_running = chip->is_recording;
821 } 842 } else {
822 else
823 {
824 /* access the playback register section */ 843 /* access the playback register section */
825 portbase = chip->codec_port + 0x00; 844 portbase = chip->codec_port + 0x00;
826 is_running = chip->is_playing; 845 is_running = chip->is_playing;
827 } 846 }
828 847
829 /* AZF3328 uses a two buffer pointer DMA playback approach */ 848 /* AZF3328 uses a two buffer pointer DMA playback approach */
830 if (!is_running) 849 if (!is_running) {
831 {
832 unsigned long addr_area2; 850 unsigned long addr_area2;
833 unsigned long count_areas, count_tmp; /* width 32bit -- overflow!! */ 851 unsigned long count_areas, count_tmp; /* width 32bit -- overflow!! */
834 count_areas = size/2; 852 count_areas = size/2;
@@ -961,6 +979,13 @@ snd_azf3328_playback_trigger(struct snd_pcm_substream *substream, int cmd)
961 chip->is_playing = 1; 979 chip->is_playing = 1;
962 snd_azf3328_dbgplay("STARTED PLAYBACK\n"); 980 snd_azf3328_dbgplay("STARTED PLAYBACK\n");
963 break; 981 break;
982 case SNDRV_PCM_TRIGGER_RESUME:
983 snd_azf3328_dbgplay("RESUME PLAYBACK\n");
984 /* resume playback if we were active */
985 if (chip->is_playing)
986 snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS,
987 snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS) | DMA_RESUME);
988 break;
964 case SNDRV_PCM_TRIGGER_STOP: 989 case SNDRV_PCM_TRIGGER_STOP:
965 snd_azf3328_dbgplay("STOP PLAYBACK\n"); 990 snd_azf3328_dbgplay("STOP PLAYBACK\n");
966 991
@@ -988,6 +1013,12 @@ snd_azf3328_playback_trigger(struct snd_pcm_substream *substream, int cmd)
988 chip->is_playing = 0; 1013 chip->is_playing = 0;
989 snd_azf3328_dbgplay("STOPPED PLAYBACK\n"); 1014 snd_azf3328_dbgplay("STOPPED PLAYBACK\n");
990 break; 1015 break;
1016 case SNDRV_PCM_TRIGGER_SUSPEND:
1017 snd_azf3328_dbgplay("SUSPEND PLAYBACK\n");
1018 /* make sure playback is stopped */
1019 snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS,
1020 snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS) & ~DMA_RESUME);
1021 break;
991 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 1022 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
992 snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_PUSH NIY!\n"); 1023 snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_PUSH NIY!\n");
993 break; 1024 break;
@@ -995,6 +1026,7 @@ snd_azf3328_playback_trigger(struct snd_pcm_substream *substream, int cmd)
995 snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_RELEASE NIY!\n"); 1026 snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_RELEASE NIY!\n");
996 break; 1027 break;
997 default: 1028 default:
1029 printk(KERN_ERR "FIXME: unknown trigger mode!\n");
998 return -EINVAL; 1030 return -EINVAL;
999 } 1031 }
1000 1032
@@ -1068,6 +1100,13 @@ snd_azf3328_capture_trigger(struct snd_pcm_substream *substream, int cmd)
1068 chip->is_recording = 1; 1100 chip->is_recording = 1;
1069 snd_azf3328_dbgplay("STARTED CAPTURE\n"); 1101 snd_azf3328_dbgplay("STARTED CAPTURE\n");
1070 break; 1102 break;
1103 case SNDRV_PCM_TRIGGER_RESUME:
1104 snd_azf3328_dbgplay("RESUME CAPTURE\n");
1105 /* resume recording if we were active */
1106 if (chip->is_recording)
1107 snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS,
1108 snd_azf3328_codec_inw(chip, IDX_IO_REC_FLAGS) | DMA_RESUME);
1109 break;
1071 case SNDRV_PCM_TRIGGER_STOP: 1110 case SNDRV_PCM_TRIGGER_STOP:
1072 snd_azf3328_dbgplay("STOP CAPTURE\n"); 1111 snd_azf3328_dbgplay("STOP CAPTURE\n");
1073 1112
@@ -1088,6 +1127,12 @@ snd_azf3328_capture_trigger(struct snd_pcm_substream *substream, int cmd)
1088 chip->is_recording = 0; 1127 chip->is_recording = 0;
1089 snd_azf3328_dbgplay("STOPPED CAPTURE\n"); 1128 snd_azf3328_dbgplay("STOPPED CAPTURE\n");
1090 break; 1129 break;
1130 case SNDRV_PCM_TRIGGER_SUSPEND:
1131 snd_azf3328_dbgplay("SUSPEND CAPTURE\n");
1132 /* make sure recording is stopped */
1133 snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS,
1134 snd_azf3328_codec_inw(chip, IDX_IO_REC_FLAGS) & ~DMA_RESUME);
1135 break;
1091 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 1136 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
1092 snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_PUSH NIY!\n"); 1137 snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_PUSH NIY!\n");
1093 break; 1138 break;
@@ -1095,6 +1140,7 @@ snd_azf3328_capture_trigger(struct snd_pcm_substream *substream, int cmd)
1095 snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_RELEASE NIY!\n"); 1140 snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_RELEASE NIY!\n");
1096 break; 1141 break;
1097 default: 1142 default:
1143 printk(KERN_ERR "FIXME: unknown trigger mode!\n");
1098 return -EINVAL; 1144 return -EINVAL;
1099 } 1145 }
1100 1146
@@ -1163,8 +1209,7 @@ snd_azf3328_interrupt(int irq, void *dev_id, struct pt_regs *regs)
1163 snd_azf3328_codec_inw(chip, IDX_IO_PLAY_IRQTYPE), 1209 snd_azf3328_codec_inw(chip, IDX_IO_PLAY_IRQTYPE),
1164 status); 1210 status);
1165 1211
1166 if (status & IRQ_TIMER) 1212 if (status & IRQ_TIMER) {
1167 {
1168 /* snd_azf3328_dbgplay("timer %ld\n", inl(chip->codec_port+IDX_IO_TIMER_VALUE) & TIMER_VALUE_MASK); */ 1213 /* snd_azf3328_dbgplay("timer %ld\n", inl(chip->codec_port+IDX_IO_TIMER_VALUE) & TIMER_VALUE_MASK); */
1169 if (chip->timer) 1214 if (chip->timer)
1170 snd_timer_interrupt(chip->timer, chip->timer->sticks); 1215 snd_timer_interrupt(chip->timer, chip->timer->sticks);
@@ -1174,50 +1219,43 @@ snd_azf3328_interrupt(int irq, void *dev_id, struct pt_regs *regs)
1174 spin_unlock(&chip->reg_lock); 1219 spin_unlock(&chip->reg_lock);
1175 snd_azf3328_dbgplay("azt3328: timer IRQ\n"); 1220 snd_azf3328_dbgplay("azt3328: timer IRQ\n");
1176 } 1221 }
1177 if (status & IRQ_PLAYBACK) 1222 if (status & IRQ_PLAYBACK) {
1178 {
1179 spin_lock(&chip->reg_lock); 1223 spin_lock(&chip->reg_lock);
1180 which = snd_azf3328_codec_inb(chip, IDX_IO_PLAY_IRQTYPE); 1224 which = snd_azf3328_codec_inb(chip, IDX_IO_PLAY_IRQTYPE);
1181 /* ack all IRQ types immediately */ 1225 /* ack all IRQ types immediately */
1182 snd_azf3328_codec_outb(chip, IDX_IO_PLAY_IRQTYPE, which); 1226 snd_azf3328_codec_outb(chip, IDX_IO_PLAY_IRQTYPE, which);
1183 spin_unlock(&chip->reg_lock); 1227 spin_unlock(&chip->reg_lock);
1184 1228
1185 if (chip->pcm && chip->playback_substream) 1229 if (chip->pcm && chip->playback_substream) {
1186 {
1187 snd_pcm_period_elapsed(chip->playback_substream); 1230 snd_pcm_period_elapsed(chip->playback_substream);
1188 snd_azf3328_dbgplay("PLAY period done (#%x), @ %x\n", 1231 snd_azf3328_dbgplay("PLAY period done (#%x), @ %x\n",
1189 which, 1232 which,
1190 inl(chip->codec_port+IDX_IO_PLAY_DMA_CURRPOS)); 1233 inl(chip->codec_port+IDX_IO_PLAY_DMA_CURRPOS));
1191 } 1234 } else
1192 else
1193 snd_azf3328_dbgplay("azt3328: ouch, irq handler problem!\n"); 1235 snd_azf3328_dbgplay("azt3328: ouch, irq handler problem!\n");
1194 if (which & IRQ_PLAY_SOMETHING) 1236 if (which & IRQ_PLAY_SOMETHING)
1195 snd_azf3328_dbgplay("azt3328: unknown play IRQ type occurred, please report!\n"); 1237 snd_azf3328_dbgplay("azt3328: unknown play IRQ type occurred, please report!\n");
1196 } 1238 }
1197 if (status & IRQ_RECORDING) 1239 if (status & IRQ_RECORDING) {
1198 {
1199 spin_lock(&chip->reg_lock); 1240 spin_lock(&chip->reg_lock);
1200 which = snd_azf3328_codec_inb(chip, IDX_IO_REC_IRQTYPE); 1241 which = snd_azf3328_codec_inb(chip, IDX_IO_REC_IRQTYPE);
1201 /* ack all IRQ types immediately */ 1242 /* ack all IRQ types immediately */
1202 snd_azf3328_codec_outb(chip, IDX_IO_REC_IRQTYPE, which); 1243 snd_azf3328_codec_outb(chip, IDX_IO_REC_IRQTYPE, which);
1203 spin_unlock(&chip->reg_lock); 1244 spin_unlock(&chip->reg_lock);
1204 1245
1205 if (chip->pcm && chip->capture_substream) 1246 if (chip->pcm && chip->capture_substream) {
1206 {
1207 snd_pcm_period_elapsed(chip->capture_substream); 1247 snd_pcm_period_elapsed(chip->capture_substream);
1208 snd_azf3328_dbgplay("REC period done (#%x), @ %x\n", 1248 snd_azf3328_dbgplay("REC period done (#%x), @ %x\n",
1209 which, 1249 which,
1210 inl(chip->codec_port+IDX_IO_REC_DMA_CURRPOS)); 1250 inl(chip->codec_port+IDX_IO_REC_DMA_CURRPOS));
1211 } 1251 } else
1212 else
1213 snd_azf3328_dbgplay("azt3328: ouch, irq handler problem!\n"); 1252 snd_azf3328_dbgplay("azt3328: ouch, irq handler problem!\n");
1214 if (which & IRQ_REC_SOMETHING) 1253 if (which & IRQ_REC_SOMETHING)
1215 snd_azf3328_dbgplay("azt3328: unknown rec IRQ type occurred, please report!\n"); 1254 snd_azf3328_dbgplay("azt3328: unknown rec IRQ type occurred, please report!\n");
1216 } 1255 }
1217 /* MPU401 has less critical IRQ requirements 1256 /* MPU401 has less critical IRQ requirements
1218 * than timer and playback/recording, right? */ 1257 * than timer and playback/recording, right? */
1219 if (status & IRQ_MPU401) 1258 if (status & IRQ_MPU401) {
1220 {
1221 snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data, regs); 1259 snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data, regs);
1222 1260
1223 /* hmm, do we have to ack the IRQ here somehow? 1261 /* hmm, do we have to ack the IRQ here somehow?
@@ -1511,8 +1549,7 @@ snd_azf3328_timer_start(struct snd_timer *timer)
1511 snd_azf3328_dbgcallenter(); 1549 snd_azf3328_dbgcallenter();
1512 chip = snd_timer_chip(timer); 1550 chip = snd_timer_chip(timer);
1513 delay = ((timer->sticks * seqtimer_scaling) - 1) & TIMER_VALUE_MASK; 1551 delay = ((timer->sticks * seqtimer_scaling) - 1) & TIMER_VALUE_MASK;
1514 if (delay < 49) 1552 if (delay < 49) {
1515 {
1516 /* uhoh, that's not good, since user-space won't know about 1553 /* uhoh, that's not good, since user-space won't know about
1517 * this timing tweak 1554 * this timing tweak
1518 * (we need to do it to avoid a lockup, though) */ 1555 * (we need to do it to avoid a lockup, though) */
@@ -1766,9 +1803,11 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
1766 goto out_err; 1803 goto out_err;
1767 } 1804 }
1768 1805
1806 card->private_data = chip;
1807
1769 if ((err = snd_mpu401_uart_new( card, 0, MPU401_HW_MPU401, 1808 if ((err = snd_mpu401_uart_new( card, 0, MPU401_HW_MPU401,
1770 chip->mpu_port, 1, pci->irq, 0, 1809 chip->mpu_port, MPU401_INFO_INTEGRATED,
1771 &chip->rmidi)) < 0) { 1810 pci->irq, 0, &chip->rmidi)) < 0) {
1772 snd_printk(KERN_ERR "azf3328: no MPU-401 device at 0x%lx?\n", chip->mpu_port); 1811 snd_printk(KERN_ERR "azf3328: no MPU-401 device at 0x%lx?\n", chip->mpu_port);
1773 goto out_err; 1812 goto out_err;
1774 } 1813 }
@@ -1791,6 +1830,8 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
1791 } 1830 }
1792 } 1831 }
1793 1832
1833 opl3->private_data = chip;
1834
1794 sprintf(card->longname, "%s at 0x%lx, irq %i", 1835 sprintf(card->longname, "%s at 0x%lx, irq %i",
1795 card->shortname, chip->codec_port, chip->irq); 1836 card->shortname, chip->codec_port, chip->irq);
1796 1837
@@ -1834,11 +1875,80 @@ snd_azf3328_remove(struct pci_dev *pci)
1834 snd_azf3328_dbgcallleave(); 1875 snd_azf3328_dbgcallleave();
1835} 1876}
1836 1877
1878#ifdef CONFIG_PM
1879static int
1880snd_azf3328_suspend(struct pci_dev *pci, pm_message_t state)
1881{
1882 struct snd_card *card = pci_get_drvdata(pci);
1883 struct snd_azf3328 *chip = card->private_data;
1884 int reg;
1885
1886 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
1887
1888 snd_pcm_suspend_all(chip->pcm);
1889
1890 for (reg = 0; reg < AZF_IO_SIZE_MIXER_PM / 2; reg++)
1891 chip->saved_regs_mixer[reg] = inw(chip->mixer_port + reg * 2);
1892
1893 /* make sure to disable master volume etc. to prevent looping sound */
1894 snd_azf3328_mixer_set_mute(chip, IDX_MIXER_PLAY_MASTER, 1);
1895 snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 1);
1896
1897 for (reg = 0; reg < AZF_IO_SIZE_CODEC_PM / 2; reg++)
1898 chip->saved_regs_codec[reg] = inw(chip->codec_port + reg * 2);
1899 for (reg = 0; reg < AZF_IO_SIZE_IO2_PM / 2; reg++)
1900 chip->saved_regs_io2[reg] = inw(chip->io2_port + reg * 2);
1901 for (reg = 0; reg < AZF_IO_SIZE_MPU_PM / 2; reg++)
1902 chip->saved_regs_mpu[reg] = inw(chip->mpu_port + reg * 2);
1903 for (reg = 0; reg < AZF_IO_SIZE_SYNTH_PM / 2; reg++)
1904 chip->saved_regs_synth[reg] = inw(chip->synth_port + reg * 2);
1905
1906 pci_set_power_state(pci, PCI_D3hot);
1907 pci_disable_device(pci);
1908 pci_save_state(pci);
1909 return 0;
1910}
1911
1912static int
1913snd_azf3328_resume(struct pci_dev *pci)
1914{
1915 struct snd_card *card = pci_get_drvdata(pci);
1916 struct snd_azf3328 *chip = card->private_data;
1917 int reg;
1918
1919 pci_restore_state(pci);
1920 pci_enable_device(pci);
1921 pci_set_power_state(pci, PCI_D0);
1922 pci_set_master(pci);
1923
1924 for (reg = 0; reg < AZF_IO_SIZE_IO2_PM / 2; reg++)
1925 outw(chip->saved_regs_io2[reg], chip->io2_port + reg * 2);
1926 for (reg = 0; reg < AZF_IO_SIZE_MPU_PM / 2; reg++)
1927 outw(chip->saved_regs_mpu[reg], chip->mpu_port + reg * 2);
1928 for (reg = 0; reg < AZF_IO_SIZE_SYNTH_PM / 2; reg++)
1929 outw(chip->saved_regs_synth[reg], chip->synth_port + reg * 2);
1930 for (reg = 0; reg < AZF_IO_SIZE_MIXER_PM / 2; reg++)
1931 outw(chip->saved_regs_mixer[reg], chip->mixer_port + reg * 2);
1932 for (reg = 0; reg < AZF_IO_SIZE_CODEC_PM / 2; reg++)
1933 outw(chip->saved_regs_codec[reg], chip->codec_port + reg * 2);
1934
1935 snd_power_change_state(card, SNDRV_CTL_POWER_D0);
1936 return 0;
1937}
1938#endif
1939
1940
1941
1942
1837static struct pci_driver driver = { 1943static struct pci_driver driver = {
1838 .name = "AZF3328", 1944 .name = "AZF3328",
1839 .id_table = snd_azf3328_ids, 1945 .id_table = snd_azf3328_ids,
1840 .probe = snd_azf3328_probe, 1946 .probe = snd_azf3328_probe,
1841 .remove = __devexit_p(snd_azf3328_remove), 1947 .remove = __devexit_p(snd_azf3328_remove),
1948#ifdef CONFIG_PM
1949 .suspend = snd_azf3328_suspend,
1950 .resume = snd_azf3328_resume,
1951#endif
1842}; 1952};
1843 1953
1844static int __init 1954static int __init
diff --git a/sound/pci/azt3328.h b/sound/pci/azt3328.h
index f489bdaf6d40..b4f3e3cd006b 100644
--- a/sound/pci/azt3328.h
+++ b/sound/pci/azt3328.h
@@ -5,6 +5,9 @@
5 5
6/*** main I/O area port indices ***/ 6/*** main I/O area port indices ***/
7/* (only 0x70 of 0x80 bytes saved/restored by Windows driver) */ 7/* (only 0x70 of 0x80 bytes saved/restored by Windows driver) */
8#define AZF_IO_SIZE_CODEC 0x80
9#define AZF_IO_SIZE_CODEC_PM 0x70
10
8/* the driver initialisation suggests a layout of 4 main areas: 11/* the driver initialisation suggests a layout of 4 main areas:
9 * from 0x00 (playback), from 0x20 (recording) and from 0x40 (maybe MPU401??). 12 * from 0x00 (playback), from 0x20 (recording) and from 0x40 (maybe MPU401??).
10 * And another area from 0x60 to 0x6f (DirectX timer, IRQ management, 13 * And another area from 0x60 to 0x6f (DirectX timer, IRQ management,
@@ -87,7 +90,7 @@
87#define IDX_IO_REC_DMA_CURROFS 0x34 /* PU:0x00000000 */ 90#define IDX_IO_REC_DMA_CURROFS 0x34 /* PU:0x00000000 */
88#define IDX_IO_REC_SOUNDFORMAT 0x36 /* PU:0x0000 */ 91#define IDX_IO_REC_SOUNDFORMAT 0x36 /* PU:0x0000 */
89 92
90/** hmm, what is this I/O area for? MPU401?? (after playback, recording, ???, timer) **/ 93/** hmm, what is this I/O area for? MPU401?? or external DAC via I2S?? (after playback, recording, ???, timer) **/
91#define IDX_IO_SOMETHING_FLAGS 0x40 /* gets set to 0x34 just like port 0x0 and 0x20 on card init, PU:0x0000 */ 94#define IDX_IO_SOMETHING_FLAGS 0x40 /* gets set to 0x34 just like port 0x0 and 0x20 on card init, PU:0x0000 */
92/* general */ 95/* general */
93#define IDX_IO_42H 0x42 /* PU:0x0001 */ 96#define IDX_IO_42H 0x42 /* PU:0x0001 */
@@ -107,7 +110,8 @@
107 #define IRQ_UNKNOWN2 0x0080 /* probably unused */ 110 #define IRQ_UNKNOWN2 0x0080 /* probably unused */
108#define IDX_IO_66H 0x66 /* writing 0xffff returns 0x0000 */ 111#define IDX_IO_66H 0x66 /* writing 0xffff returns 0x0000 */
109#define IDX_IO_SOME_VALUE 0x68 /* this is set to e.g. 0x3ff or 0x300, and writable; maybe some buffer limit, but I couldn't find out more, PU:0x00ff */ 112#define IDX_IO_SOME_VALUE 0x68 /* this is set to e.g. 0x3ff or 0x300, and writable; maybe some buffer limit, but I couldn't find out more, PU:0x00ff */
110#define IDX_IO_6AH 0x6A /* this WORD can be set to have bits 0x0028 activated; actually inhibits PCM playback!!! maybe power management?? */ 113#define IDX_IO_6AH 0x6A /* this WORD can be set to have bits 0x0028 activated (FIXME: correct??); actually inhibits PCM playback!!! maybe power management?? */
114 #define IO_6A_PAUSE_PLAYBACK 0x0200 /* bit 9; sure, this pauses playback, but what the heck is this really about?? */
111#define IDX_IO_6CH 0x6C 115#define IDX_IO_6CH 0x6C
112#define IDX_IO_6EH 0x6E /* writing 0xffff returns 0x83fe */ 116#define IDX_IO_6EH 0x6E /* writing 0xffff returns 0x83fe */
113/* further I/O indices not saved/restored, so probably not used */ 117/* further I/O indices not saved/restored, so probably not used */
@@ -115,15 +119,25 @@
115 119
116/*** I/O 2 area port indices ***/ 120/*** I/O 2 area port indices ***/
117/* (only 0x06 of 0x08 bytes saved/restored by Windows driver) */ 121/* (only 0x06 of 0x08 bytes saved/restored by Windows driver) */
122#define AZF_IO_SIZE_IO2 0x08
123#define AZF_IO_SIZE_IO2_PM 0x06
124
118#define IDX_IO2_LEGACY_ADDR 0x04 125#define IDX_IO2_LEGACY_ADDR 0x04
119 #define LEGACY_SOMETHING 0x01 /* OPL3?? */ 126 #define LEGACY_SOMETHING 0x01 /* OPL3?? */
120 #define LEGACY_JOY 0x08 127 #define LEGACY_JOY 0x08
121 128
129#define AZF_IO_SIZE_MPU 0x04
130#define AZF_IO_SIZE_MPU_PM 0x04
131
132#define AZF_IO_SIZE_SYNTH 0x08
133#define AZF_IO_SIZE_SYNTH_PM 0x06
122 134
123/*** mixer I/O area port indices ***/ 135/*** mixer I/O area port indices ***/
124/* (only 0x22 of 0x40 bytes saved/restored by Windows driver) 136/* (only 0x22 of 0x40 bytes saved/restored by Windows driver)
125 * generally spoken: AC97 register index = AZF3328 mixer reg index + 2 137 * UNFORTUNATELY azf3328 is NOT truly AC97 compliant: see main file intro */
126 * (in other words: AZF3328 NOT fully AC97 compliant) */ 138#define AZF_IO_SIZE_MIXER 0x40
139#define AZF_IO_SIZE_MIXER_PM 0x22
140
127 #define MIXER_VOLUME_RIGHT_MASK 0x001f 141 #define MIXER_VOLUME_RIGHT_MASK 0x001f
128 #define MIXER_VOLUME_LEFT_MASK 0x1f00 142 #define MIXER_VOLUME_LEFT_MASK 0x1f00
129 #define MIXER_MUTE_MASK 0x8000 143 #define MIXER_MUTE_MASK 0x8000
@@ -156,14 +170,14 @@
156#define IDX_MIXER_ADVCTL1 0x1e 170#define IDX_MIXER_ADVCTL1 0x1e
157 /* unlisted bits are unmodifiable */ 171 /* unlisted bits are unmodifiable */
158 #define MIXER_ADVCTL1_3DWIDTH_MASK 0x000e 172 #define MIXER_ADVCTL1_3DWIDTH_MASK 0x000e
159 #define MIXER_ADVCTL1_HIFI3D_MASK 0x0300 173 #define MIXER_ADVCTL1_HIFI3D_MASK 0x0300 /* yup, this is missing the high bit that official AC97 contains, plus it doesn't have linear bit value range behaviour but instead acts weirdly (possibly we're dealing with two *different* 3D settings here??) */
160#define IDX_MIXER_ADVCTL2 0x20 /* resembles AC97_GENERAL_PURPOSE reg! */ 174#define IDX_MIXER_ADVCTL2 0x20 /* subset of AC97_GENERAL_PURPOSE reg! */
161 /* unlisted bits are unmodifiable */ 175 /* unlisted bits are unmodifiable */
162 #define MIXER_ADVCTL2_BIT7 0x0080 /* WaveOut 3D Bypass? mutes WaveOut at LineOut */ 176 #define MIXER_ADVCTL2_LPBK 0x0080 /* Loopback mode -- Win driver: "WaveOut3DBypass"? mutes WaveOut at LineOut */
163 #define MIXER_ADVCTL2_BIT8 0x0100 /* is this Modem Out Select? */ 177 #define MIXER_ADVCTL2_MS 0x0100 /* Mic Select 0=Mic1, 1=Mic2 -- Win driver: "ModemOutSelect"?? */
164 #define MIXER_ADVCTL2_BIT9 0x0200 /* Mono Select Source? */ 178 #define MIXER_ADVCTL2_MIX 0x0200 /* Mono output select 0=Mix, 1=Mic; Win driver: "MonoSelectSource"?? */
165 #define MIXER_ADVCTL2_BIT13 0x2000 /* 3D enable? */ 179 #define MIXER_ADVCTL2_3D 0x2000 /* 3D Enhancement 1=on */
166 #define MIXER_ADVCTL2_BIT15 0x8000 /* unknown */ 180 #define MIXER_ADVCTL2_POP 0x8000 /* Pcm Out Path, 0=pre 3D, 1=post 3D */
167 181
168#define IDX_MIXER_SOMETHING30H 0x30 /* used, but unknown??? */ 182#define IDX_MIXER_SOMETHING30H 0x30 /* used, but unknown??? */
169 183
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c
index 9ee07d4aac1e..c33642d8d9a1 100644
--- a/sound/pci/bt87x.c
+++ b/sound/pci/bt87x.c
@@ -44,7 +44,7 @@ MODULE_SUPPORTED_DEVICE("{{Brooktree,Bt878},"
44static int index[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -2}; /* Exclude the first card */ 44static int index[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -2}; /* Exclude the first card */
45static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ 45static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
46static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ 46static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
47static int digital_rate[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0 }; /* digital input rate */ 47static int digital_rate[SNDRV_CARDS]; /* digital input rate */
48static int load_all; /* allow to load the non-whitelisted cards */ 48static int load_all; /* allow to load the non-whitelisted cards */
49 49
50module_param_array(index, int, NULL, 0444); 50module_param_array(index, int, NULL, 0444);
@@ -781,10 +781,12 @@ static struct pci_device_id snd_bt87x_ids[] __devinitdata = {
781 BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, 0x0070, 0x13eb, 32000), 781 BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, 0x0070, 0x13eb, 32000),
782 /* Viewcast Osprey 200 */ 782 /* Viewcast Osprey 200 */
783 BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0xff01, 44100), 783 BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0xff01, 44100),
784 /* AVerMedia Studio No. 103, 203, ...? */
785 BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1461, 0x0003, 48000),
786 /* Leadtek Winfast tv 2000xp delux */ 784 /* Leadtek Winfast tv 2000xp delux */
787 BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x107d, 0x6606, 32000), 785 BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x107d, 0x6606, 32000),
786 /* Voodoo TV 200 */
787 BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x121a, 0x3000, 32000),
788 /* AVerMedia Studio No. 103, 203, ...? */
789 BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1461, 0x0003, 48000),
788 { } 790 { }
789}; 791};
790MODULE_DEVICE_TABLE(pci, snd_bt87x_ids); 792MODULE_DEVICE_TABLE(pci, snd_bt87x_ids);
diff --git a/sound/pci/ca0106/ca0106.h b/sound/pci/ca0106/ca0106.h
index c8131ea92ed6..9cb66c59f523 100644
--- a/sound/pci/ca0106/ca0106.h
+++ b/sound/pci/ca0106/ca0106.h
@@ -537,9 +537,9 @@
537#endif 537#endif
538 538
539#define ADC_MUX_MASK 0x0000000f //Mask for ADC Mux 539#define ADC_MUX_MASK 0x0000000f //Mask for ADC Mux
540#define ADC_MUX_PHONE 0x00000001 //Value to select TAD at ADC Mux (Not used)
540#define ADC_MUX_MIC 0x00000002 //Value to select Mic at ADC Mux 541#define ADC_MUX_MIC 0x00000002 //Value to select Mic at ADC Mux
541#define ADC_MUX_LINEIN 0x00000004 //Value to select LineIn at ADC Mux 542#define ADC_MUX_LINEIN 0x00000004 //Value to select LineIn at ADC Mux
542#define ADC_MUX_PHONE 0x00000001 //Value to select TAD at ADC Mux (Not used)
543#define ADC_MUX_AUX 0x00000008 //Value to select Aux at ADC Mux 543#define ADC_MUX_AUX 0x00000008 //Value to select Aux at ADC Mux
544 544
545#define SET_CHANNEL 0 /* Testing channel outputs 0=Front, 1=Center/LFE, 2=Unknown, 3=Rear */ 545#define SET_CHANNEL 0 /* Testing channel outputs 0=Front, 1=Center/LFE, 2=Unknown, 3=Rear */
@@ -604,6 +604,8 @@ struct snd_ca0106 {
604 u32 spdif_bits[4]; /* s/pdif out setup */ 604 u32 spdif_bits[4]; /* s/pdif out setup */
605 int spdif_enable; 605 int spdif_enable;
606 int capture_source; 606 int capture_source;
607 int i2c_capture_source;
608 u8 i2c_capture_volume[4][2];
607 int capture_mic_line_in; 609 int capture_mic_line_in;
608 610
609 struct snd_dma_buffer buffer; 611 struct snd_dma_buffer buffer;
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index fd8bfebfbd54..59bf9bd02534 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -186,8 +186,8 @@ static struct snd_ca0106_details ca0106_chip_details[] = {
186 /* New Audigy SE. Has a different DAC. */ 186 /* New Audigy SE. Has a different DAC. */
187 /* SB0570: 187 /* SB0570:
188 * CTRL:CA0106-DAT 188 * CTRL:CA0106-DAT
189 * ADC: WM8768GEDS 189 * ADC: WM8775EDS
190 * DAC: WM8775EDS 190 * DAC: WM8768GEDS
191 */ 191 */
192 { .serial = 0x100a1102, 192 { .serial = 0x100a1102,
193 .name = "Audigy SE [SB0570]", 193 .name = "Audigy SE [SB0570]",
@@ -195,9 +195,14 @@ static struct snd_ca0106_details ca0106_chip_details[] = {
195 .i2c_adc = 1, 195 .i2c_adc = 1,
196 .spi_dac = 1 } , 196 .spi_dac = 1 } ,
197 /* MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97 */ 197 /* MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97 */
198 /* SB0438
199 * CTRL:CA0106-DAT
200 * ADC: WM8775SEDS
201 * DAC: CS4382-KQZ
202 */
198 { .serial = 0x10091462, 203 { .serial = 0x10091462,
199 .name = "MSI K8N Diamond MB [SB0438]", 204 .name = "MSI K8N Diamond MB [SB0438]",
200 .gpio_type = 1, 205 .gpio_type = 2,
201 .i2c_adc = 1 } , 206 .i2c_adc = 1 } ,
202 /* Shuttle XPC SD31P which has an onboard Creative Labs 207 /* Shuttle XPC SD31P which has an onboard Creative Labs
203 * Sound Blaster Live! 24-bit EAX 208 * Sound Blaster Live! 24-bit EAX
@@ -326,6 +331,7 @@ int snd_ca0106_spi_write(struct snd_ca0106 * emu,
326 return 0; 331 return 0;
327} 332}
328 333
334/* The ADC does not support i2c read, so only write is implemented */
329int snd_ca0106_i2c_write(struct snd_ca0106 *emu, 335int snd_ca0106_i2c_write(struct snd_ca0106 *emu,
330 u32 reg, 336 u32 reg,
331 u32 value) 337 u32 value)
@@ -340,6 +346,7 @@ int snd_ca0106_i2c_write(struct snd_ca0106 *emu,
340 } 346 }
341 347
342 tmp = reg << 25 | value << 16; 348 tmp = reg << 25 | value << 16;
349 // snd_printk("I2C-write:reg=0x%x, value=0x%x\n", reg, value);
343 /* Not sure what this I2C channel controls. */ 350 /* Not sure what this I2C channel controls. */
344 /* snd_ca0106_ptr_write(emu, I2C_D0, 0, tmp); */ 351 /* snd_ca0106_ptr_write(emu, I2C_D0, 0, tmp); */
345 352
@@ -348,8 +355,9 @@ int snd_ca0106_i2c_write(struct snd_ca0106 *emu,
348 355
349 for (retry = 0; retry < 10; retry++) { 356 for (retry = 0; retry < 10; retry++) {
350 /* Send the data to i2c */ 357 /* Send the data to i2c */
351 tmp = snd_ca0106_ptr_read(emu, I2C_A, 0); 358 //tmp = snd_ca0106_ptr_read(emu, I2C_A, 0);
352 tmp = tmp & ~(I2C_A_ADC_READ|I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD_MASK); 359 //tmp = tmp & ~(I2C_A_ADC_READ|I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD_MASK);
360 tmp = 0;
353 tmp = tmp | (I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD); 361 tmp = tmp | (I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD);
354 snd_ca0106_ptr_write(emu, I2C_A, 0, tmp); 362 snd_ca0106_ptr_write(emu, I2C_A, 0, tmp);
355 363
@@ -1181,7 +1189,7 @@ static unsigned int spi_dac_init[] = {
1181 0x02ff, 1189 0x02ff,
1182 0x0400, 1190 0x0400,
1183 0x0520, 1191 0x0520,
1184 0x0600, 1192 0x0620, /* Set 24 bit. Was 0x0600 */
1185 0x08ff, 1193 0x08ff,
1186 0x0aff, 1194 0x0aff,
1187 0x0cff, 1195 0x0cff,
@@ -1200,6 +1208,22 @@ static unsigned int spi_dac_init[] = {
1200 0x1400, 1208 0x1400,
1201}; 1209};
1202 1210
1211static unsigned int i2c_adc_init[][2] = {
1212 { 0x17, 0x00 }, /* Reset */
1213 { 0x07, 0x00 }, /* Timeout */
1214 { 0x0b, 0x22 }, /* Interface control */
1215 { 0x0c, 0x22 }, /* Master mode control */
1216 { 0x0d, 0x08 }, /* Powerdown control */
1217 { 0x0e, 0xcf }, /* Attenuation Left 0x01 = -103dB, 0xff = 24dB */
1218 { 0x0f, 0xcf }, /* Attenuation Right 0.5dB steps */
1219 { 0x10, 0x7b }, /* ALC Control 1 */
1220 { 0x11, 0x00 }, /* ALC Control 2 */
1221 { 0x12, 0x32 }, /* ALC Control 3 */
1222 { 0x13, 0x00 }, /* Noise gate control */
1223 { 0x14, 0xa6 }, /* Limiter control */
1224 { 0x15, ADC_MUX_LINEIN }, /* ADC Mixer control */
1225};
1226
1203static int __devinit snd_ca0106_create(struct snd_card *card, 1227static int __devinit snd_ca0106_create(struct snd_card *card,
1204 struct pci_dev *pci, 1228 struct pci_dev *pci,
1205 struct snd_ca0106 **rchip) 1229 struct snd_ca0106 **rchip)
@@ -1361,7 +1385,12 @@ static int __devinit snd_ca0106_create(struct snd_card *card,
1361 snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC, Line in, TAD in, AUX in */ 1385 snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC, Line in, TAD in, AUX in */
1362 chip->capture_source = 3; /* Set CAPTURE_SOURCE */ 1386 chip->capture_source = 3; /* Set CAPTURE_SOURCE */
1363 1387
1364 if (chip->details->gpio_type == 1) { /* The SB0410 and SB0413 use GPIO differently. */ 1388 if (chip->details->gpio_type == 2) { /* The SB0438 use GPIO differently. */
1389 /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */
1390 outl(0x0, chip->port+GPIO);
1391 //outl(0x00f0e000, chip->port+GPIO); /* Analog */
1392 outl(0x005f5301, chip->port+GPIO); /* Analog */
1393 } else if (chip->details->gpio_type == 1) { /* The SB0410 and SB0413 use GPIO differently. */
1365 /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */ 1394 /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */
1366 outl(0x0, chip->port+GPIO); 1395 outl(0x0, chip->port+GPIO);
1367 //outl(0x00f0e000, chip->port+GPIO); /* Analog */ 1396 //outl(0x00f0e000, chip->port+GPIO); /* Analog */
@@ -1379,7 +1408,19 @@ static int __devinit snd_ca0106_create(struct snd_card *card,
1379 outl(HCFG_AC97 | HCFG_AUDIOENABLE, chip->port+HCFG); /* AC97 2.0, Enable outputs. */ 1408 outl(HCFG_AC97 | HCFG_AUDIOENABLE, chip->port+HCFG); /* AC97 2.0, Enable outputs. */
1380 1409
1381 if (chip->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */ 1410 if (chip->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */
1382 snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); /* Enable Line-in capture. MIC in currently untested. */ 1411 int size, n;
1412
1413 size = ARRAY_SIZE(i2c_adc_init);
1414 //snd_printk("I2C:array size=0x%x\n", size);
1415 for (n=0; n < size; n++) {
1416 snd_ca0106_i2c_write(chip, i2c_adc_init[n][0], i2c_adc_init[n][1]);
1417 }
1418 for (n=0; n < 4; n++) {
1419 chip->i2c_capture_volume[n][0]= 0xcf;
1420 chip->i2c_capture_volume[n][1]= 0xcf;
1421 }
1422 chip->i2c_capture_source=2; /* Line in */
1423 //snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); /* Enable Line-in capture. MIC in currently untested. */
1383 } 1424 }
1384 if (chip->details->spi_dac == 1) { /* The SB0570 use SPI to control DAC. */ 1425 if (chip->details->spi_dac == 1) { /* The SB0570 use SPI to control DAC. */
1385 int size, n; 1426 int size, n;
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c
index 06fe055674fb..146eed70dce6 100644
--- a/sound/pci/ca0106/ca0106_mixer.c
+++ b/sound/pci/ca0106/ca0106_mixer.c
@@ -171,6 +171,76 @@ static int snd_ca0106_capture_source_put(struct snd_kcontrol *kcontrol,
171 return change; 171 return change;
172} 172}
173 173
174static int snd_ca0106_i2c_capture_source_info(struct snd_kcontrol *kcontrol,
175 struct snd_ctl_elem_info *uinfo)
176{
177 static char *texts[6] = {
178 "Phone", "Mic", "Line in", "Aux"
179 };
180
181 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
182 uinfo->count = 1;
183 uinfo->value.enumerated.items = 4;
184 if (uinfo->value.enumerated.item > 3)
185 uinfo->value.enumerated.item = 3;
186 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
187 return 0;
188}
189
190static int snd_ca0106_i2c_capture_source_get(struct snd_kcontrol *kcontrol,
191 struct snd_ctl_elem_value *ucontrol)
192{
193 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
194
195 ucontrol->value.enumerated.item[0] = emu->i2c_capture_source;
196 return 0;
197}
198
199static int snd_ca0106_i2c_capture_source_put(struct snd_kcontrol *kcontrol,
200 struct snd_ctl_elem_value *ucontrol)
201{
202 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
203 unsigned int source_id;
204 unsigned int ngain, ogain;
205 int change = 0;
206 u32 source;
207 /* If the capture source has changed,
208 * update the capture volume from the cached value
209 * for the particular source.
210 */
211 source_id = ucontrol->value.enumerated.item[0] ;
212 change = (emu->i2c_capture_source != source_id);
213 if (change) {
214 snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */
215 ngain = emu->i2c_capture_volume[source_id][0]; /* Left */
216 ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */
217 if (ngain != ogain)
218 snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff));
219 ngain = emu->i2c_capture_volume[source_id][1]; /* Left */
220 ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Left */
221 if (ngain != ogain)
222 snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
223 source = 1 << source_id;
224 snd_ca0106_i2c_write(emu, ADC_MUX, source); /* Set source */
225 emu->i2c_capture_source = source_id;
226 }
227 return change;
228}
229
230static int snd_ca0106_capture_line_in_side_out_info(struct snd_kcontrol *kcontrol,
231 struct snd_ctl_elem_info *uinfo)
232{
233 static char *texts[2] = { "Side out", "Line in" };
234
235 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
236 uinfo->count = 1;
237 uinfo->value.enumerated.items = 2;
238 if (uinfo->value.enumerated.item > 1)
239 uinfo->value.enumerated.item = 1;
240 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
241 return 0;
242}
243
174static int snd_ca0106_capture_mic_line_in_info(struct snd_kcontrol *kcontrol, 244static int snd_ca0106_capture_mic_line_in_info(struct snd_kcontrol *kcontrol,
175 struct snd_ctl_elem_info *uinfo) 245 struct snd_ctl_elem_info *uinfo)
176{ 246{
@@ -207,16 +277,16 @@ static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol,
207 if (change) { 277 if (change) {
208 emu->capture_mic_line_in = val; 278 emu->capture_mic_line_in = val;
209 if (val) { 279 if (val) {
210 snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_PHONE); /* Mute input */ 280 //snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */
211 tmp = inl(emu->port+GPIO) & ~0x400; 281 tmp = inl(emu->port+GPIO) & ~0x400;
212 tmp = tmp | 0x400; 282 tmp = tmp | 0x400;
213 outl(tmp, emu->port+GPIO); 283 outl(tmp, emu->port+GPIO);
214 snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC); 284 //snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC);
215 } else { 285 } else {
216 snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_PHONE); /* Mute input */ 286 //snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */
217 tmp = inl(emu->port+GPIO) & ~0x400; 287 tmp = inl(emu->port+GPIO) & ~0x400;
218 outl(tmp, emu->port+GPIO); 288 outl(tmp, emu->port+GPIO);
219 snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN); 289 //snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN);
220 } 290 }
221 } 291 }
222 return change; 292 return change;
@@ -225,12 +295,22 @@ static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol,
225static struct snd_kcontrol_new snd_ca0106_capture_mic_line_in __devinitdata = 295static struct snd_kcontrol_new snd_ca0106_capture_mic_line_in __devinitdata =
226{ 296{
227 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 297 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
228 .name = "Mic/Line in Capture", 298 .name = "Shared Mic/Line in Capture Switch",
229 .info = snd_ca0106_capture_mic_line_in_info, 299 .info = snd_ca0106_capture_mic_line_in_info,
230 .get = snd_ca0106_capture_mic_line_in_get, 300 .get = snd_ca0106_capture_mic_line_in_get,
231 .put = snd_ca0106_capture_mic_line_in_put 301 .put = snd_ca0106_capture_mic_line_in_put
232}; 302};
233 303
304static struct snd_kcontrol_new snd_ca0106_capture_line_in_side_out __devinitdata =
305{
306 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
307 .name = "Shared Line in/Side out Capture Switch",
308 .info = snd_ca0106_capture_line_in_side_out_info,
309 .get = snd_ca0106_capture_mic_line_in_get,
310 .put = snd_ca0106_capture_mic_line_in_put
311};
312
313
234static int snd_ca0106_spdif_info(struct snd_kcontrol *kcontrol, 314static int snd_ca0106_spdif_info(struct snd_kcontrol *kcontrol,
235 struct snd_ctl_elem_info *uinfo) 315 struct snd_ctl_elem_info *uinfo)
236{ 316{
@@ -329,15 +409,81 @@ static int snd_ca0106_volume_put(struct snd_kcontrol *kcontrol,
329 return 1; 409 return 1;
330} 410}
331 411
412static int snd_ca0106_i2c_volume_info(struct snd_kcontrol *kcontrol,
413 struct snd_ctl_elem_info *uinfo)
414{
415 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
416 uinfo->count = 2;
417 uinfo->value.integer.min = 0;
418 uinfo->value.integer.max = 255;
419 return 0;
420}
421
422static int snd_ca0106_i2c_volume_get(struct snd_kcontrol *kcontrol,
423 struct snd_ctl_elem_value *ucontrol)
424{
425 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
426 int source_id;
427
428 source_id = kcontrol->private_value;
429
430 ucontrol->value.integer.value[0] = emu->i2c_capture_volume[source_id][0];
431 ucontrol->value.integer.value[1] = emu->i2c_capture_volume[source_id][1];
432 return 0;
433}
434
435static int snd_ca0106_i2c_volume_put(struct snd_kcontrol *kcontrol,
436 struct snd_ctl_elem_value *ucontrol)
437{
438 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
439 unsigned int ogain;
440 unsigned int ngain;
441 int source_id;
442 int change = 0;
443
444 source_id = kcontrol->private_value;
445 ogain = emu->i2c_capture_volume[source_id][0]; /* Left */
446 ngain = ucontrol->value.integer.value[0];
447 if (ngain > 0xff)
448 return 0;
449 if (ogain != ngain) {
450 if (emu->i2c_capture_source == source_id)
451 snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) );
452 emu->i2c_capture_volume[source_id][0] = ucontrol->value.integer.value[0];
453 change = 1;
454 }
455 ogain = emu->i2c_capture_volume[source_id][1]; /* Right */
456 ngain = ucontrol->value.integer.value[1];
457 if (ngain > 0xff)
458 return 0;
459 if (ogain != ngain) {
460 if (emu->i2c_capture_source == source_id)
461 snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
462 emu->i2c_capture_volume[source_id][1] = ucontrol->value.integer.value[1];
463 change = 1;
464 }
465
466 return change;
467}
468
332#define CA_VOLUME(xname,chid,reg) \ 469#define CA_VOLUME(xname,chid,reg) \
333{ \ 470{ \
334 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 471 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
335 .info = snd_ca0106_volume_info, \ 472 .info = snd_ca0106_volume_info, \
336 .get = snd_ca0106_volume_get, \ 473 .get = snd_ca0106_volume_get, \
337 .put = snd_ca0106_volume_put, \ 474 .put = snd_ca0106_volume_put, \
338 .private_value = ((chid) << 8) | (reg) \ 475 .private_value = ((chid) << 8) | (reg) \
339} 476}
340 477
478#define I2C_VOLUME(xname,chid) \
479{ \
480 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
481 .info = snd_ca0106_i2c_volume_info, \
482 .get = snd_ca0106_i2c_volume_get, \
483 .put = snd_ca0106_i2c_volume_put, \
484 .private_value = chid \
485}
486
341 487
342static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = { 488static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = {
343 CA_VOLUME("Analog Front Playback Volume", 489 CA_VOLUME("Analog Front Playback Volume",
@@ -361,6 +507,11 @@ static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = {
361 CA_VOLUME("CAPTURE feedback Playback Volume", 507 CA_VOLUME("CAPTURE feedback Playback Volume",
362 1, CAPTURE_CONTROL), 508 1, CAPTURE_CONTROL),
363 509
510 I2C_VOLUME("Phone Capture Volume", 0),
511 I2C_VOLUME("Mic Capture Volume", 1),
512 I2C_VOLUME("Line in Capture Volume", 2),
513 I2C_VOLUME("Aux Capture Volume", 3),
514
364 { 515 {
365 .access = SNDRV_CTL_ELEM_ACCESS_READ, 516 .access = SNDRV_CTL_ELEM_ACCESS_READ,
366 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 517 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -378,12 +529,19 @@ static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = {
378 }, 529 },
379 { 530 {
380 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 531 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
381 .name = "Capture Source", 532 .name = "Digital Capture Source",
382 .info = snd_ca0106_capture_source_info, 533 .info = snd_ca0106_capture_source_info,
383 .get = snd_ca0106_capture_source_get, 534 .get = snd_ca0106_capture_source_get,
384 .put = snd_ca0106_capture_source_put 535 .put = snd_ca0106_capture_source_put
385 }, 536 },
386 { 537 {
538 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
539 .name = "Capture Source",
540 .info = snd_ca0106_i2c_capture_source_info,
541 .get = snd_ca0106_i2c_capture_source_get,
542 .put = snd_ca0106_i2c_capture_source_put
543 },
544 {
387 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 545 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
388 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), 546 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
389 .count = 4, 547 .count = 4,
@@ -477,7 +635,10 @@ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu)
477 return err; 635 return err;
478 } 636 }
479 if (emu->details->i2c_adc == 1) { 637 if (emu->details->i2c_adc == 1) {
480 err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu)); 638 if (emu->details->gpio_type == 1)
639 err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu));
640 else /* gpio_type == 2 */
641 err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_line_in_side_out, emu));
481 if (err < 0) 642 if (err < 0)
482 return err; 643 return err;
483 } 644 }
diff --git a/sound/pci/ca0106/ca0106_proc.c b/sound/pci/ca0106/ca0106_proc.c
index 63757273bfb7..75ca421eb3a1 100644
--- a/sound/pci/ca0106/ca0106_proc.c
+++ b/sound/pci/ca0106/ca0106_proc.c
@@ -431,33 +431,30 @@ int __devinit snd_ca0106_proc_init(struct snd_ca0106 * emu)
431 struct snd_info_entry *entry; 431 struct snd_info_entry *entry;
432 432
433 if(! snd_card_proc_new(emu->card, "iec958", &entry)) 433 if(! snd_card_proc_new(emu->card, "iec958", &entry))
434 snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_iec958); 434 snd_info_set_text_ops(entry, emu, snd_ca0106_proc_iec958);
435 if(! snd_card_proc_new(emu->card, "ca0106_reg32", &entry)) { 435 if(! snd_card_proc_new(emu->card, "ca0106_reg32", &entry)) {
436 snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read32); 436 snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read32);
437 entry->c.text.write_size = 64;
438 entry->c.text.write = snd_ca0106_proc_reg_write32; 437 entry->c.text.write = snd_ca0106_proc_reg_write32;
439 entry->mode |= S_IWUSR; 438 entry->mode |= S_IWUSR;
440 } 439 }
441 if(! snd_card_proc_new(emu->card, "ca0106_reg16", &entry)) 440 if(! snd_card_proc_new(emu->card, "ca0106_reg16", &entry))
442 snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read16); 441 snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read16);
443 if(! snd_card_proc_new(emu->card, "ca0106_reg8", &entry)) 442 if(! snd_card_proc_new(emu->card, "ca0106_reg8", &entry))
444 snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read8); 443 snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read8);
445 if(! snd_card_proc_new(emu->card, "ca0106_regs1", &entry)) { 444 if(! snd_card_proc_new(emu->card, "ca0106_regs1", &entry)) {
446 snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read1); 445 snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read1);
447 entry->c.text.write_size = 64;
448 entry->c.text.write = snd_ca0106_proc_reg_write; 446 entry->c.text.write = snd_ca0106_proc_reg_write;
449 entry->mode |= S_IWUSR; 447 entry->mode |= S_IWUSR;
450// entry->private_data = emu; 448// entry->private_data = emu;
451 } 449 }
452 if(! snd_card_proc_new(emu->card, "ca0106_i2c", &entry)) { 450 if(! snd_card_proc_new(emu->card, "ca0106_i2c", &entry)) {
453 snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_i2c_write); 451 snd_info_set_text_ops(entry, emu, snd_ca0106_proc_i2c_write);
454 entry->c.text.write_size = 64;
455 entry->c.text.write = snd_ca0106_proc_i2c_write; 452 entry->c.text.write = snd_ca0106_proc_i2c_write;
456 entry->mode |= S_IWUSR; 453 entry->mode |= S_IWUSR;
457// entry->private_data = emu; 454// entry->private_data = emu;
458 } 455 }
459 if(! snd_card_proc_new(emu->card, "ca0106_regs2", &entry)) 456 if(! snd_card_proc_new(emu->card, "ca0106_regs2", &entry))
460 snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read2); 457 snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read2);
461 return 0; 458 return 0;
462} 459}
463 460
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
index e5ce2dabd081..0938c158b5c9 100644
--- a/sound/pci/cmipci.c
+++ b/sound/pci/cmipci.c
@@ -2121,7 +2121,7 @@ static struct snd_kcontrol_new snd_cmipci_mixers[] __devinitdata = {
2121 CMIPCI_MIXER_VOL_MONO("Mic Capture Volume", CM_REG_MIXER2, CM_VADMIC_SHIFT, 7), 2121 CMIPCI_MIXER_VOL_MONO("Mic Capture Volume", CM_REG_MIXER2, CM_VADMIC_SHIFT, 7),
2122 CMIPCI_SB_VOL_MONO("Phone Playback Volume", CM_REG_EXTENT_IND, 5, 7), 2122 CMIPCI_SB_VOL_MONO("Phone Playback Volume", CM_REG_EXTENT_IND, 5, 7),
2123 CMIPCI_DOUBLE("Phone Playback Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 4, 4, 1, 0, 0), 2123 CMIPCI_DOUBLE("Phone Playback Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 4, 4, 1, 0, 0),
2124 CMIPCI_DOUBLE("PC Speaker Playnack Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 3, 3, 1, 0, 0), 2124 CMIPCI_DOUBLE("PC Speaker Playback Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 3, 3, 1, 0, 0),
2125 CMIPCI_DOUBLE("Mic Boost Capture Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 0, 0, 1, 0, 0), 2125 CMIPCI_DOUBLE("Mic Boost Capture Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 0, 0, 1, 0, 0),
2126}; 2126};
2127 2127
@@ -2602,7 +2602,7 @@ static void __devinit snd_cmipci_proc_init(struct cmipci *cm)
2602 struct snd_info_entry *entry; 2602 struct snd_info_entry *entry;
2603 2603
2604 if (! snd_card_proc_new(cm->card, "cmipci", &entry)) 2604 if (! snd_card_proc_new(cm->card, "cmipci", &entry))
2605 snd_info_set_text_ops(entry, cm, 1024, snd_cmipci_proc_read); 2605 snd_info_set_text_ops(entry, cm, snd_cmipci_proc_read);
2606} 2606}
2607#else /* !CONFIG_PROC_FS */ 2607#else /* !CONFIG_PROC_FS */
2608static inline void snd_cmipci_proc_init(struct cmipci *cm) {} 2608static inline void snd_cmipci_proc_init(struct cmipci *cm) {}
@@ -2932,7 +2932,7 @@ static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pc
2932 } 2932 }
2933 2933
2934 integrated_midi = snd_cmipci_read_b(cm, CM_REG_MPU_PCI) != 0xff; 2934 integrated_midi = snd_cmipci_read_b(cm, CM_REG_MPU_PCI) != 0xff;
2935 if (integrated_midi) 2935 if (integrated_midi && mpu_port[dev] == 1)
2936 iomidi = cm->iobase + CM_REG_MPU_PCI; 2936 iomidi = cm->iobase + CM_REG_MPU_PCI;
2937 else { 2937 else {
2938 iomidi = mpu_port[dev]; 2938 iomidi = mpu_port[dev];
@@ -2981,7 +2981,9 @@ static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pc
2981 2981
2982 if (iomidi > 0) { 2982 if (iomidi > 0) {
2983 if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_CMIPCI, 2983 if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_CMIPCI,
2984 iomidi, integrated_midi, 2984 iomidi,
2985 (integrated_midi ?
2986 MPU401_INFO_INTEGRATED : 0),
2985 cm->irq, 0, &cm->rmidi)) < 0) { 2987 cm->irq, 0, &cm->rmidi)) < 0) {
2986 printk(KERN_ERR "cmipci: no UART401 device at 0x%lx\n", iomidi); 2988 printk(KERN_ERR "cmipci: no UART401 device at 0x%lx\n", iomidi);
2987 } 2989 }
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c
index b3c94d83450a..e77a4ce314b7 100644
--- a/sound/pci/cs4281.c
+++ b/sound/pci/cs4281.c
@@ -1184,7 +1184,7 @@ static void __devinit snd_cs4281_proc_init(struct cs4281 * chip)
1184 struct snd_info_entry *entry; 1184 struct snd_info_entry *entry;
1185 1185
1186 if (! snd_card_proc_new(chip->card, "cs4281", &entry)) 1186 if (! snd_card_proc_new(chip->card, "cs4281", &entry))
1187 snd_info_set_text_ops(entry, chip, 1024, snd_cs4281_proc_read); 1187 snd_info_set_text_ops(entry, chip, snd_cs4281_proc_read);
1188 if (! snd_card_proc_new(chip->card, "cs4281_BA0", &entry)) { 1188 if (! snd_card_proc_new(chip->card, "cs4281_BA0", &entry)) {
1189 entry->content = SNDRV_INFO_CONTENT_DATA; 1189 entry->content = SNDRV_INFO_CONTENT_DATA;
1190 entry->private_data = chip; 1190 entry->private_data = chip;
@@ -1379,6 +1379,13 @@ static int __devinit snd_cs4281_create(struct snd_card *card,
1379 chip->ba0_addr = pci_resource_start(pci, 0); 1379 chip->ba0_addr = pci_resource_start(pci, 0);
1380 chip->ba1_addr = pci_resource_start(pci, 1); 1380 chip->ba1_addr = pci_resource_start(pci, 1);
1381 1381
1382 chip->ba0 = ioremap_nocache(chip->ba0_addr, pci_resource_len(pci, 0));
1383 chip->ba1 = ioremap_nocache(chip->ba1_addr, pci_resource_len(pci, 1));
1384 if (!chip->ba0 || !chip->ba1) {
1385 snd_cs4281_free(chip);
1386 return -ENOMEM;
1387 }
1388
1382 if (request_irq(pci->irq, snd_cs4281_interrupt, SA_INTERRUPT|SA_SHIRQ, 1389 if (request_irq(pci->irq, snd_cs4281_interrupt, SA_INTERRUPT|SA_SHIRQ,
1383 "CS4281", chip)) { 1390 "CS4281", chip)) {
1384 snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); 1391 snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
@@ -1387,13 +1394,6 @@ static int __devinit snd_cs4281_create(struct snd_card *card,
1387 } 1394 }
1388 chip->irq = pci->irq; 1395 chip->irq = pci->irq;
1389 1396
1390 chip->ba0 = ioremap_nocache(chip->ba0_addr, pci_resource_len(pci, 0));
1391 chip->ba1 = ioremap_nocache(chip->ba1_addr, pci_resource_len(pci, 1));
1392 if (!chip->ba0 || !chip->ba1) {
1393 snd_cs4281_free(chip);
1394 return -ENOMEM;
1395 }
1396
1397 tmp = snd_cs4281_chip_init(chip); 1397 tmp = snd_cs4281_chip_init(chip);
1398 if (tmp) { 1398 if (tmp) {
1399 snd_cs4281_free(chip); 1399 snd_cs4281_free(chip);
diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c
index 848d772ae3c6..772dc52bfeb2 100644
--- a/sound/pci/cs46xx/cs46xx.c
+++ b/sound/pci/cs46xx/cs46xx.c
@@ -48,8 +48,8 @@ MODULE_SUPPORTED_DEVICE("{{Cirrus Logic,Sound Fusion (CS4280)},"
48static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ 48static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
49static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ 49static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
50static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ 50static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
51static int external_amp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; 51static int external_amp[SNDRV_CARDS];
52static int thinkpad[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; 52static int thinkpad[SNDRV_CARDS];
53static int mmap_valid[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; 53static int mmap_valid[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
54 54
55module_param_array(index, int, NULL, 0444); 55module_param_array(index, int, NULL, 0444);
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
index 69dbf542a6de..5c2114439204 100644
--- a/sound/pci/cs46xx/cs46xx_lib.c
+++ b/sound/pci/cs46xx/cs46xx_lib.c
@@ -2877,14 +2877,15 @@ static int snd_cs46xx_free(struct snd_cs46xx *chip)
2877 if (chip->region.idx[0].resource) 2877 if (chip->region.idx[0].resource)
2878 snd_cs46xx_hw_stop(chip); 2878 snd_cs46xx_hw_stop(chip);
2879 2879
2880 if (chip->irq >= 0)
2881 free_irq(chip->irq, chip);
2882
2880 for (idx = 0; idx < 5; idx++) { 2883 for (idx = 0; idx < 5; idx++) {
2881 struct snd_cs46xx_region *region = &chip->region.idx[idx]; 2884 struct snd_cs46xx_region *region = &chip->region.idx[idx];
2882 if (region->remap_addr) 2885 if (region->remap_addr)
2883 iounmap(region->remap_addr); 2886 iounmap(region->remap_addr);
2884 release_and_free_resource(region->resource); 2887 release_and_free_resource(region->resource);
2885 } 2888 }
2886 if (chip->irq >= 0)
2887 free_irq(chip->irq, chip);
2888 2889
2889 if (chip->active_ctrl) 2890 if (chip->active_ctrl)
2890 chip->active_ctrl(chip, -chip->amplifier); 2891 chip->active_ctrl(chip, -chip->amplifier);
diff --git a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c
index f407d2a5ce3b..5c9711c0265c 100644
--- a/sound/pci/cs46xx/dsp_spos.c
+++ b/sound/pci/cs46xx/dsp_spos.c
@@ -767,7 +767,6 @@ int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip)
767 if ((entry = snd_info_create_card_entry(card, "dsp", card->proc_root)) != NULL) { 767 if ((entry = snd_info_create_card_entry(card, "dsp", card->proc_root)) != NULL) {
768 entry->content = SNDRV_INFO_CONTENT_TEXT; 768 entry->content = SNDRV_INFO_CONTENT_TEXT;
769 entry->mode = S_IFDIR | S_IRUGO | S_IXUGO; 769 entry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
770 entry->c.text.read_size = 512;
771 770
772 if (snd_info_register(entry) < 0) { 771 if (snd_info_register(entry) < 0) {
773 snd_info_free_entry(entry); 772 snd_info_free_entry(entry);
@@ -784,7 +783,6 @@ int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip)
784 entry->content = SNDRV_INFO_CONTENT_TEXT; 783 entry->content = SNDRV_INFO_CONTENT_TEXT;
785 entry->private_data = chip; 784 entry->private_data = chip;
786 entry->mode = S_IFREG | S_IRUGO | S_IWUSR; 785 entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
787 entry->c.text.read_size = 512;
788 entry->c.text.read = cs46xx_dsp_proc_symbol_table_read; 786 entry->c.text.read = cs46xx_dsp_proc_symbol_table_read;
789 if (snd_info_register(entry) < 0) { 787 if (snd_info_register(entry) < 0) {
790 snd_info_free_entry(entry); 788 snd_info_free_entry(entry);
@@ -797,7 +795,6 @@ int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip)
797 entry->content = SNDRV_INFO_CONTENT_TEXT; 795 entry->content = SNDRV_INFO_CONTENT_TEXT;
798 entry->private_data = chip; 796 entry->private_data = chip;
799 entry->mode = S_IFREG | S_IRUGO | S_IWUSR; 797 entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
800 entry->c.text.read_size = 512;
801 entry->c.text.read = cs46xx_dsp_proc_modules_read; 798 entry->c.text.read = cs46xx_dsp_proc_modules_read;
802 if (snd_info_register(entry) < 0) { 799 if (snd_info_register(entry) < 0) {
803 snd_info_free_entry(entry); 800 snd_info_free_entry(entry);
@@ -810,7 +807,6 @@ int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip)
810 entry->content = SNDRV_INFO_CONTENT_TEXT; 807 entry->content = SNDRV_INFO_CONTENT_TEXT;
811 entry->private_data = chip; 808 entry->private_data = chip;
812 entry->mode = S_IFREG | S_IRUGO | S_IWUSR; 809 entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
813 entry->c.text.read_size = 512;
814 entry->c.text.read = cs46xx_dsp_proc_parameter_dump_read; 810 entry->c.text.read = cs46xx_dsp_proc_parameter_dump_read;
815 if (snd_info_register(entry) < 0) { 811 if (snd_info_register(entry) < 0) {
816 snd_info_free_entry(entry); 812 snd_info_free_entry(entry);
@@ -823,7 +819,6 @@ int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip)
823 entry->content = SNDRV_INFO_CONTENT_TEXT; 819 entry->content = SNDRV_INFO_CONTENT_TEXT;
824 entry->private_data = chip; 820 entry->private_data = chip;
825 entry->mode = S_IFREG | S_IRUGO | S_IWUSR; 821 entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
826 entry->c.text.read_size = 512;
827 entry->c.text.read = cs46xx_dsp_proc_sample_dump_read; 822 entry->c.text.read = cs46xx_dsp_proc_sample_dump_read;
828 if (snd_info_register(entry) < 0) { 823 if (snd_info_register(entry) < 0) {
829 snd_info_free_entry(entry); 824 snd_info_free_entry(entry);
@@ -836,7 +831,6 @@ int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip)
836 entry->content = SNDRV_INFO_CONTENT_TEXT; 831 entry->content = SNDRV_INFO_CONTENT_TEXT;
837 entry->private_data = chip; 832 entry->private_data = chip;
838 entry->mode = S_IFREG | S_IRUGO | S_IWUSR; 833 entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
839 entry->c.text.read_size = 512;
840 entry->c.text.read = cs46xx_dsp_proc_task_tree_read; 834 entry->c.text.read = cs46xx_dsp_proc_task_tree_read;
841 if (snd_info_register(entry) < 0) { 835 if (snd_info_register(entry) < 0) {
842 snd_info_free_entry(entry); 836 snd_info_free_entry(entry);
@@ -849,7 +843,6 @@ int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip)
849 entry->content = SNDRV_INFO_CONTENT_TEXT; 843 entry->content = SNDRV_INFO_CONTENT_TEXT;
850 entry->private_data = chip; 844 entry->private_data = chip;
851 entry->mode = S_IFREG | S_IRUGO | S_IWUSR; 845 entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
852 entry->c.text.read_size = 1024;
853 entry->c.text.read = cs46xx_dsp_proc_scb_read; 846 entry->c.text.read = cs46xx_dsp_proc_scb_read;
854 if (snd_info_register(entry) < 0) { 847 if (snd_info_register(entry) < 0) {
855 snd_info_free_entry(entry); 848 snd_info_free_entry(entry);
diff --git a/sound/pci/cs46xx/dsp_spos_scb_lib.c b/sound/pci/cs46xx/dsp_spos_scb_lib.c
index 2c4ee45fe10c..3844d18af19c 100644
--- a/sound/pci/cs46xx/dsp_spos_scb_lib.c
+++ b/sound/pci/cs46xx/dsp_spos_scb_lib.c
@@ -267,7 +267,6 @@ void cs46xx_dsp_proc_register_scb_desc (struct snd_cs46xx *chip,
267 entry->private_data = scb_info; 267 entry->private_data = scb_info;
268 entry->mode = S_IFREG | S_IRUGO | S_IWUSR; 268 entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
269 269
270 entry->c.text.read_size = 512;
271 entry->c.text.read = cs46xx_dsp_proc_scb_info_read; 270 entry->c.text.read = cs46xx_dsp_proc_scb_info_read;
272 271
273 if (snd_info_register(entry) < 0) { 272 if (snd_info_register(entry) < 0) {
diff --git a/sound/pci/cs5535audio/Makefile b/sound/pci/cs5535audio/Makefile
index 08d8ee6547d3..2911a8adc1f2 100644
--- a/sound/pci/cs5535audio/Makefile
+++ b/sound/pci/cs5535audio/Makefile
@@ -4,5 +4,9 @@
4 4
5snd-cs5535audio-objs := cs5535audio.o cs5535audio_pcm.o 5snd-cs5535audio-objs := cs5535audio.o cs5535audio_pcm.o
6 6
7ifdef CONFIG_PM
8snd-cs5535audio-objs += cs5535audio_pm.o
9endif
10
7# Toplevel Module Dependency 11# Toplevel Module Dependency
8obj-$(CONFIG_SND_CS5535AUDIO) += snd-cs5535audio.o 12obj-$(CONFIG_SND_CS5535AUDIO) += snd-cs5535audio.o
diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c
index 2c1213a35dcc..91c18a11fe87 100644
--- a/sound/pci/cs5535audio/cs5535audio.c
+++ b/sound/pci/cs5535audio/cs5535audio.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Driver for audio on multifunction CS5535 companion device 2 * Driver for audio on multifunction CS5535/6 companion device
3 * Copyright (C) Jaya Kumar 3 * Copyright (C) Jaya Kumar
4 * 4 *
5 * Based on Jaroslav Kysela and Takashi Iwai's examples. 5 * Based on Jaroslav Kysela and Takashi Iwai's examples.
@@ -40,16 +40,36 @@
40 40
41#define DRIVER_NAME "cs5535audio" 41#define DRIVER_NAME "cs5535audio"
42 42
43static char *ac97_quirk;
44module_param(ac97_quirk, charp, 0444);
45MODULE_PARM_DESC(ac97_quirk, "AC'97 board specific workarounds.");
46
47static struct ac97_quirk ac97_quirks[] __devinitdata = {
48#if 0 /* Not yet confirmed if all 5536 boards are HP only */
49 {
50 .subvendor = PCI_VENDOR_ID_AMD,
51 .subdevice = PCI_DEVICE_ID_AMD_CS5536_AUDIO,
52 .name = "AMD RDK",
53 .type = AC97_TUNE_HP_ONLY
54 },
55#endif
56 {}
57};
43 58
44static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; 59static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
45static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; 60static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
46static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; 61static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
47 62
63module_param_array(index, int, NULL, 0444);
64MODULE_PARM_DESC(index, "Index value for " DRIVER_NAME);
65module_param_array(id, charp, NULL, 0444);
66MODULE_PARM_DESC(id, "ID string for " DRIVER_NAME);
67module_param_array(enable, bool, NULL, 0444);
68MODULE_PARM_DESC(enable, "Enable " DRIVER_NAME);
69
48static struct pci_device_id snd_cs5535audio_ids[] __devinitdata = { 70static struct pci_device_id snd_cs5535audio_ids[] __devinitdata = {
49 { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_AUDIO, 71 { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_AUDIO) },
50 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, 72 { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_AUDIO) },
51 { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_AUDIO,
52 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
53 {} 73 {}
54}; 74};
55 75
@@ -90,7 +110,8 @@ static unsigned short snd_cs5535audio_codec_read(struct cs5535audio *cs5535au,
90 udelay(1); 110 udelay(1);
91 } while (--timeout); 111 } while (--timeout);
92 if (!timeout) 112 if (!timeout)
93 snd_printk(KERN_ERR "Failure reading cs5535 codec\n"); 113 snd_printk(KERN_ERR "Failure reading codec reg 0x%x,"
114 "Last value=0x%x\n", reg, val);
94 115
95 return (unsigned short) val; 116 return (unsigned short) val;
96} 117}
@@ -148,6 +169,8 @@ static int snd_cs5535audio_mixer(struct cs5535audio *cs5535au)
148 return err; 169 return err;
149 } 170 }
150 171
172 snd_ac97_tune_hardware(cs5535au->ac97, ac97_quirks, ac97_quirk);
173
151 return 0; 174 return 0;
152} 175}
153 176
@@ -347,6 +370,8 @@ static int __devinit snd_cs5535audio_probe(struct pci_dev *pci,
347 if ((err = snd_cs5535audio_create(card, pci, &cs5535au)) < 0) 370 if ((err = snd_cs5535audio_create(card, pci, &cs5535au)) < 0)
348 goto probefail_out; 371 goto probefail_out;
349 372
373 card->private_data = cs5535au;
374
350 if ((err = snd_cs5535audio_mixer(cs5535au)) < 0) 375 if ((err = snd_cs5535audio_mixer(cs5535au)) < 0)
351 goto probefail_out; 376 goto probefail_out;
352 377
@@ -383,6 +408,10 @@ static struct pci_driver driver = {
383 .id_table = snd_cs5535audio_ids, 408 .id_table = snd_cs5535audio_ids,
384 .probe = snd_cs5535audio_probe, 409 .probe = snd_cs5535audio_probe,
385 .remove = __devexit_p(snd_cs5535audio_remove), 410 .remove = __devexit_p(snd_cs5535audio_remove),
411#ifdef CONFIG_PM
412 .suspend = snd_cs5535audio_suspend,
413 .resume = snd_cs5535audio_resume,
414#endif
386}; 415};
387 416
388static int __init alsa_card_cs5535audio_init(void) 417static int __init alsa_card_cs5535audio_init(void)
diff --git a/sound/pci/cs5535audio/cs5535audio.h b/sound/pci/cs5535audio/cs5535audio.h
index 5e55a1a1ed65..4fd1f31a6cf9 100644
--- a/sound/pci/cs5535audio/cs5535audio.h
+++ b/sound/pci/cs5535audio/cs5535audio.h
@@ -74,6 +74,8 @@
74#define PRM_RDY_STS 0x00800000 74#define PRM_RDY_STS 0x00800000
75#define ACC_CODEC_CNTL_WR_CMD (~0x80000000) 75#define ACC_CODEC_CNTL_WR_CMD (~0x80000000)
76#define ACC_CODEC_CNTL_RD_CMD 0x80000000 76#define ACC_CODEC_CNTL_RD_CMD 0x80000000
77#define ACC_CODEC_CNTL_LNK_SHUTDOWN 0x00040000
78#define ACC_CODEC_CNTL_LNK_WRM_RST 0x00020000
77#define PRD_JMP 0x2000 79#define PRD_JMP 0x2000
78#define PRD_EOP 0x4000 80#define PRD_EOP 0x4000
79#define PRD_EOT 0x8000 81#define PRD_EOT 0x8000
@@ -88,6 +90,7 @@ struct cs5535audio_dma_ops {
88 void (*disable_dma)(struct cs5535audio *cs5535au); 90 void (*disable_dma)(struct cs5535audio *cs5535au);
89 void (*pause_dma)(struct cs5535audio *cs5535au); 91 void (*pause_dma)(struct cs5535audio *cs5535au);
90 void (*setup_prd)(struct cs5535audio *cs5535au, u32 prd_addr); 92 void (*setup_prd)(struct cs5535audio *cs5535au, u32 prd_addr);
93 u32 (*read_prd)(struct cs5535audio *cs5535au);
91 u32 (*read_dma_pntr)(struct cs5535audio *cs5535au); 94 u32 (*read_dma_pntr)(struct cs5535audio *cs5535au);
92}; 95};
93 96
@@ -103,11 +106,14 @@ struct cs5535audio_dma {
103 struct snd_pcm_substream *substream; 106 struct snd_pcm_substream *substream;
104 unsigned int buf_addr, buf_bytes; 107 unsigned int buf_addr, buf_bytes;
105 unsigned int period_bytes, periods; 108 unsigned int period_bytes, periods;
109 int suspended;
110 u32 saved_prd;
106}; 111};
107 112
108struct cs5535audio { 113struct cs5535audio {
109 struct snd_card *card; 114 struct snd_card *card;
110 struct snd_ac97 *ac97; 115 struct snd_ac97 *ac97;
116 struct snd_pcm *pcm;
111 int irq; 117 int irq;
112 struct pci_dev *pci; 118 struct pci_dev *pci;
113 unsigned long port; 119 unsigned long port;
@@ -117,6 +123,8 @@ struct cs5535audio {
117 struct cs5535audio_dma dmas[NUM_CS5535AUDIO_DMAS]; 123 struct cs5535audio_dma dmas[NUM_CS5535AUDIO_DMAS];
118}; 124};
119 125
126int snd_cs5535audio_suspend(struct pci_dev *pci, pm_message_t state);
127int snd_cs5535audio_resume(struct pci_dev *pci);
120int __devinit snd_cs5535audio_pcm(struct cs5535audio *cs5535audio); 128int __devinit snd_cs5535audio_pcm(struct cs5535audio *cs5535audio);
121 129
122#endif /* __SOUND_CS5535AUDIO_H */ 130#endif /* __SOUND_CS5535AUDIO_H */
diff --git a/sound/pci/cs5535audio/cs5535audio_pcm.c b/sound/pci/cs5535audio/cs5535audio_pcm.c
index 60bb82b2ff47..f0a48693d687 100644
--- a/sound/pci/cs5535audio/cs5535audio_pcm.c
+++ b/sound/pci/cs5535audio/cs5535audio_pcm.c
@@ -43,7 +43,8 @@ static struct snd_pcm_hardware snd_cs5535audio_playback =
43 SNDRV_PCM_INFO_BLOCK_TRANSFER | 43 SNDRV_PCM_INFO_BLOCK_TRANSFER |
44 SNDRV_PCM_INFO_MMAP_VALID | 44 SNDRV_PCM_INFO_MMAP_VALID |
45 SNDRV_PCM_INFO_PAUSE | 45 SNDRV_PCM_INFO_PAUSE |
46 SNDRV_PCM_INFO_SYNC_START 46 SNDRV_PCM_INFO_SYNC_START |
47 SNDRV_PCM_INFO_RESUME
47 ), 48 ),
48 .formats = ( 49 .formats = (
49 SNDRV_PCM_FMTBIT_S16_LE 50 SNDRV_PCM_FMTBIT_S16_LE
@@ -193,6 +194,11 @@ static void cs5535audio_playback_setup_prd(struct cs5535audio *cs5535au,
193 cs_writel(cs5535au, ACC_BM0_PRD, prd_addr); 194 cs_writel(cs5535au, ACC_BM0_PRD, prd_addr);
194} 195}
195 196
197static u32 cs5535audio_playback_read_prd(struct cs5535audio *cs5535au)
198{
199 return cs_readl(cs5535au, ACC_BM0_PRD);
200}
201
196static u32 cs5535audio_playback_read_dma_pntr(struct cs5535audio *cs5535au) 202static u32 cs5535audio_playback_read_dma_pntr(struct cs5535audio *cs5535au)
197{ 203{
198 return cs_readl(cs5535au, ACC_BM0_PNTR); 204 return cs_readl(cs5535au, ACC_BM0_PNTR);
@@ -219,6 +225,11 @@ static void cs5535audio_capture_setup_prd(struct cs5535audio *cs5535au,
219 cs_writel(cs5535au, ACC_BM1_PRD, prd_addr); 225 cs_writel(cs5535au, ACC_BM1_PRD, prd_addr);
220} 226}
221 227
228static u32 cs5535audio_capture_read_prd(struct cs5535audio *cs5535au)
229{
230 return cs_readl(cs5535au, ACC_BM1_PRD);
231}
232
222static u32 cs5535audio_capture_read_dma_pntr(struct cs5535audio *cs5535au) 233static u32 cs5535audio_capture_read_dma_pntr(struct cs5535audio *cs5535au)
223{ 234{
224 return cs_readl(cs5535au, ACC_BM1_PNTR); 235 return cs_readl(cs5535au, ACC_BM1_PNTR);
@@ -285,9 +296,17 @@ static int snd_cs5535audio_trigger(struct snd_pcm_substream *substream, int cmd)
285 case SNDRV_PCM_TRIGGER_START: 296 case SNDRV_PCM_TRIGGER_START:
286 dma->ops->enable_dma(cs5535au); 297 dma->ops->enable_dma(cs5535au);
287 break; 298 break;
299 case SNDRV_PCM_TRIGGER_RESUME:
300 dma->ops->enable_dma(cs5535au);
301 dma->suspended = 0;
302 break;
288 case SNDRV_PCM_TRIGGER_STOP: 303 case SNDRV_PCM_TRIGGER_STOP:
289 dma->ops->disable_dma(cs5535au); 304 dma->ops->disable_dma(cs5535au);
290 break; 305 break;
306 case SNDRV_PCM_TRIGGER_SUSPEND:
307 dma->ops->disable_dma(cs5535au);
308 dma->suspended = 1;
309 break;
291 default: 310 default:
292 snd_printk(KERN_ERR "unhandled trigger\n"); 311 snd_printk(KERN_ERR "unhandled trigger\n");
293 err = -EINVAL; 312 err = -EINVAL;
@@ -375,6 +394,7 @@ static struct cs5535audio_dma_ops snd_cs5535audio_playback_dma_ops = {
375 .enable_dma = cs5535audio_playback_enable_dma, 394 .enable_dma = cs5535audio_playback_enable_dma,
376 .disable_dma = cs5535audio_playback_disable_dma, 395 .disable_dma = cs5535audio_playback_disable_dma,
377 .setup_prd = cs5535audio_playback_setup_prd, 396 .setup_prd = cs5535audio_playback_setup_prd,
397 .read_prd = cs5535audio_playback_read_prd,
378 .pause_dma = cs5535audio_playback_pause_dma, 398 .pause_dma = cs5535audio_playback_pause_dma,
379 .read_dma_pntr = cs5535audio_playback_read_dma_pntr, 399 .read_dma_pntr = cs5535audio_playback_read_dma_pntr,
380}; 400};
@@ -384,6 +404,7 @@ static struct cs5535audio_dma_ops snd_cs5535audio_capture_dma_ops = {
384 .enable_dma = cs5535audio_capture_enable_dma, 404 .enable_dma = cs5535audio_capture_enable_dma,
385 .disable_dma = cs5535audio_capture_disable_dma, 405 .disable_dma = cs5535audio_capture_disable_dma,
386 .setup_prd = cs5535audio_capture_setup_prd, 406 .setup_prd = cs5535audio_capture_setup_prd,
407 .read_prd = cs5535audio_capture_read_prd,
387 .pause_dma = cs5535audio_capture_pause_dma, 408 .pause_dma = cs5535audio_capture_pause_dma,
388 .read_dma_pntr = cs5535audio_capture_read_dma_pntr, 409 .read_dma_pntr = cs5535audio_capture_read_dma_pntr,
389}; 410};
@@ -413,6 +434,7 @@ int __devinit snd_cs5535audio_pcm(struct cs5535audio *cs5535au)
413 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, 434 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
414 snd_dma_pci_data(cs5535au->pci), 435 snd_dma_pci_data(cs5535au->pci),
415 64*1024, 128*1024); 436 64*1024, 128*1024);
437 cs5535au->pcm = pcm;
416 438
417 return 0; 439 return 0;
418} 440}
diff --git a/sound/pci/cs5535audio/cs5535audio_pm.c b/sound/pci/cs5535audio/cs5535audio_pm.c
new file mode 100644
index 000000000000..aad0e69db9c1
--- /dev/null
+++ b/sound/pci/cs5535audio/cs5535audio_pm.c
@@ -0,0 +1,123 @@
1/*
2 * Power management for audio on multifunction CS5535 companion device
3 * Copyright (C) Jaya Kumar
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 */
20
21#include <linux/init.h>
22#include <linux/slab.h>
23#include <linux/pci.h>
24#include <linux/delay.h>
25#include <sound/driver.h>
26#include <sound/core.h>
27#include <sound/control.h>
28#include <sound/initval.h>
29#include <sound/asoundef.h>
30#include <sound/pcm.h>
31#include <sound/ac97_codec.h>
32#include "cs5535audio.h"
33
34static void snd_cs5535audio_stop_hardware(struct cs5535audio *cs5535au)
35{
36 /*
37 we depend on snd_ac97_suspend to tell the
38 AC97 codec to shutdown. the amd spec suggests
39 that the LNK_SHUTDOWN be done at the same time
40 that the codec power-down is issued. instead,
41 we do it just after rather than at the same
42 time. excluding codec specific build_ops->suspend
43 ac97 powerdown hits:
44 0x8000 EAPD
45 0x4000 Headphone amplifier
46 0x0300 ADC & DAC
47 0x0400 Analog Mixer powerdown (Vref on)
48 I am not sure if this is the best that we can do.
49 The remainder to be investigated are:
50 - analog mixer (vref off) 0x0800
51 - AC-link powerdown 0x1000
52 - codec internal clock 0x2000
53 */
54
55 /* set LNK_SHUTDOWN to shutdown AC link */
56 cs_writel(cs5535au, ACC_CODEC_CNTL, ACC_CODEC_CNTL_LNK_SHUTDOWN);
57
58}
59
60int snd_cs5535audio_suspend(struct pci_dev *pci, pm_message_t state)
61{
62 struct snd_card *card = pci_get_drvdata(pci);
63 struct cs5535audio *cs5535au = card->private_data;
64 int i;
65
66 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
67 for (i = 0; i < NUM_CS5535AUDIO_DMAS; i++) {
68 struct cs5535audio_dma *dma = &cs5535au->dmas[i];
69 if (dma && dma->substream && !dma->suspended)
70 dma->saved_prd = dma->ops->read_prd(cs5535au);
71 }
72 snd_pcm_suspend_all(cs5535au->pcm);
73 snd_ac97_suspend(cs5535au->ac97);
74 /* save important regs, then disable aclink in hw */
75 snd_cs5535audio_stop_hardware(cs5535au);
76 pci_disable_device(pci);
77 pci_save_state(pci);
78
79 return 0;
80}
81
82int snd_cs5535audio_resume(struct pci_dev *pci)
83{
84 struct snd_card *card = pci_get_drvdata(pci);
85 struct cs5535audio *cs5535au = card->private_data;
86 u32 tmp;
87 int timeout;
88 int i;
89
90 pci_restore_state(pci);
91 pci_enable_device(pci);
92 pci_set_master(pci);
93
94 /* set LNK_WRM_RST to reset AC link */
95 cs_writel(cs5535au, ACC_CODEC_CNTL, ACC_CODEC_CNTL_LNK_WRM_RST);
96
97 timeout = 50;
98 do {
99 tmp = cs_readl(cs5535au, ACC_CODEC_STATUS);
100 if (tmp & PRM_RDY_STS)
101 break;
102 udelay(1);
103 } while (--timeout);
104
105 if (!timeout)
106 snd_printk(KERN_ERR "Failure getting AC Link ready\n");
107
108 /* we depend on ac97 to perform the codec power up */
109 snd_ac97_resume(cs5535au->ac97);
110 /* set up rate regs, dma. actual initiation is done in trig */
111 for (i = 0; i < NUM_CS5535AUDIO_DMAS; i++) {
112 struct cs5535audio_dma *dma = &cs5535au->dmas[i];
113 if (dma && dma->substream && dma->suspended) {
114 dma->substream->ops->prepare(dma->substream);
115 dma->ops->setup_prd(cs5535au, dma->saved_prd);
116 }
117 }
118
119 snd_power_change_state(card, SNDRV_CTL_POWER_D0);
120
121 return 0;
122}
123
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c
index 42b11ba1d210..549673ea14a9 100644
--- a/sound/pci/emu10k1/emu10k1.c
+++ b/sound/pci/emu10k1/emu10k1.c
@@ -46,13 +46,13 @@ MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB Live!/PCI512/E-mu APS},"
46static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ 46static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
47static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ 47static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
48static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ 48static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
49static int extin[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; 49static int extin[SNDRV_CARDS];
50static int extout[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; 50static int extout[SNDRV_CARDS];
51static int seq_ports[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4}; 51static int seq_ports[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4};
52static int max_synth_voices[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 64}; 52static int max_synth_voices[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 64};
53static int max_buffer_size[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 128}; 53static int max_buffer_size[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 128};
54static int enable_ir[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; 54static int enable_ir[SNDRV_CARDS];
55static uint subsystem[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; /* Force card subsystem model */ 55static uint subsystem[SNDRV_CARDS]; /* Force card subsystem model */
56 56
57module_param_array(index, int, NULL, 0444); 57module_param_array(index, int, NULL, 0444);
58MODULE_PARM_DESC(index, "Index value for the EMU10K1 soundcard."); 58MODULE_PARM_DESC(index, "Index value for the EMU10K1 soundcard.");
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index 6bfa08436efa..42a358f989c3 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -777,14 +777,6 @@ static int snd_emu10k1_dev_free(struct snd_device *device)
777 777
778static struct snd_emu_chip_details emu_chip_details[] = { 778static struct snd_emu_chip_details emu_chip_details[] = {
779 /* Audigy 2 Value AC3 out does not work yet. Need to find out how to turn off interpolators.*/ 779 /* Audigy 2 Value AC3 out does not work yet. Need to find out how to turn off interpolators.*/
780 /* Audigy4 SB0400 */
781 {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10211102,
782 .driver = "Audigy2", .name = "Audigy 4 [SB0400]",
783 .id = "Audigy2",
784 .emu10k2_chip = 1,
785 .ca0108_chip = 1,
786 .spk71 = 1,
787 .ac97_chip = 1} ,
788 /* Tested by James@superbug.co.uk 3rd July 2005 */ 780 /* Tested by James@superbug.co.uk 3rd July 2005 */
789 /* DSP: CA0108-IAT 781 /* DSP: CA0108-IAT
790 * DAC: CS4382-KQ 782 * DAC: CS4382-KQ
@@ -799,13 +791,59 @@ static struct snd_emu_chip_details emu_chip_details[] = {
799 .ca0108_chip = 1, 791 .ca0108_chip = 1,
800 .spk71 = 1, 792 .spk71 = 1,
801 .ac97_chip = 1} , 793 .ac97_chip = 1} ,
794 /* Audigy4 (Not PRO) SB0610 */
795 /* Tested by James@superbug.co.uk 4th April 2006 */
796 /* A_IOCFG bits
797 * Output
798 * 0: ?
799 * 1: ?
800 * 2: ?
801 * 3: 0 - Digital Out, 1 - Line in
802 * 4: ?
803 * 5: ?
804 * 6: ?
805 * 7: ?
806 * Input
807 * 8: ?
808 * 9: ?
809 * A: Green jack sense (Front)
810 * B: ?
811 * C: Black jack sense (Rear/Side Right)
812 * D: Yellow jack sense (Center/LFE/Side Left)
813 * E: ?
814 * F: ?
815 *
816 * Digital Out/Line in switch using A_IOCFG bit 3 (0x08)
817 * 0 - Digital Out
818 * 1 - Line in
819 */
820 /* Mic input not tested.
821 * Analog CD input not tested
822 * Digital Out not tested.
823 * Line in working.
824 * Audio output 5.1 working. Side outputs not working.
825 */
826 /* DSP: CA10300-IAT LF
827 * DAC: Cirrus Logic CS4382-KQZ
828 * ADC: Philips 1361T
829 * AC97: Sigmatel STAC9750
830 * CA0151: None
831 */
832 {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10211102,
833 .driver = "Audigy2", .name = "Audigy 4 [SB0610]",
834 .id = "Audigy2",
835 .emu10k2_chip = 1,
836 .ca0108_chip = 1,
837 .spk71 = 1,
838 .adc_1361t = 1, /* 24 bit capture instead of 16bit */
839 .ac97_chip = 1} ,
802 /* Audigy 2 ZS Notebook Cardbus card.*/ 840 /* Audigy 2 ZS Notebook Cardbus card.*/
803 /* Tested by James@superbug.co.uk 22th December 2005 */ 841 /* Tested by James@superbug.co.uk 22th December 2005 */
804 /* Audio output 7.1/Headphones working. 842 /* Audio output 7.1/Headphones working.
805 * Digital output working. (AC3 not checked, only PCM) 843 * Digital output working. (AC3 not checked, only PCM)
806 * Audio inputs not tested. 844 * Audio inputs not tested.
807 */ 845 */
808 /* DSP: Tiny2 846 /* DSP: Tina2
809 * DAC: Wolfson WM8768/WM8568 847 * DAC: Wolfson WM8768/WM8568
810 * ADC: Wolfson WM8775 848 * ADC: Wolfson WM8775
811 * AC97: None 849 * AC97: None
@@ -1421,16 +1459,3 @@ void snd_emu10k1_resume_regs(struct snd_emu10k1 *emu)
1421 } 1459 }
1422} 1460}
1423#endif 1461#endif
1424
1425/* memory.c */
1426EXPORT_SYMBOL(snd_emu10k1_synth_alloc);
1427EXPORT_SYMBOL(snd_emu10k1_synth_free);
1428EXPORT_SYMBOL(snd_emu10k1_synth_bzero);
1429EXPORT_SYMBOL(snd_emu10k1_synth_copy_from_user);
1430EXPORT_SYMBOL(snd_emu10k1_memblk_map);
1431/* voice.c */
1432EXPORT_SYMBOL(snd_emu10k1_voice_alloc);
1433EXPORT_SYMBOL(snd_emu10k1_voice_free);
1434/* io.c */
1435EXPORT_SYMBOL(snd_emu10k1_ptr_read);
1436EXPORT_SYMBOL(snd_emu10k1_ptr_write);
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
index d51290c18167..0fb27e4be07b 100644
--- a/sound/pci/emu10k1/emu10k1x.c
+++ b/sound/pci/emu10k1/emu10k1x.c
@@ -1055,8 +1055,7 @@ static int __devinit snd_emu10k1x_proc_init(struct emu10k1x * emu)
1055 struct snd_info_entry *entry; 1055 struct snd_info_entry *entry;
1056 1056
1057 if(! snd_card_proc_new(emu->card, "emu10k1x_regs", &entry)) { 1057 if(! snd_card_proc_new(emu->card, "emu10k1x_regs", &entry)) {
1058 snd_info_set_text_ops(entry, emu, 1024, snd_emu10k1x_proc_reg_read); 1058 snd_info_set_text_ops(entry, emu, snd_emu10k1x_proc_reg_read);
1059 entry->c.text.write_size = 64;
1060 entry->c.text.write = snd_emu10k1x_proc_reg_write; 1059 entry->c.text.write = snd_emu10k1x_proc_reg_write;
1061 entry->mode |= S_IWUSR; 1060 entry->mode |= S_IWUSR;
1062 entry->private_data = emu; 1061 entry->private_data = emu;
diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c
index 2a9d12d10680..c31f3d0877fa 100644
--- a/sound/pci/emu10k1/emumixer.c
+++ b/sound/pci/emu10k1/emumixer.c
@@ -777,6 +777,8 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
777 }; 777 };
778 static char *audigy_remove_ctls[] = { 778 static char *audigy_remove_ctls[] = {
779 /* Master/PCM controls on ac97 of Audigy has no effect */ 779 /* Master/PCM controls on ac97 of Audigy has no effect */
780 /* On the Audigy2 the AC97 playback is piped into
781 * the Philips ADC for 24bit capture */
780 "PCM Playback Switch", 782 "PCM Playback Switch",
781 "PCM Playback Volume", 783 "PCM Playback Volume",
782 "Master Mono Playback Switch", 784 "Master Mono Playback Switch",
@@ -804,6 +806,47 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
804 "AMic Playback Volume", "Mic Playback Volume", 806 "AMic Playback Volume", "Mic Playback Volume",
805 NULL 807 NULL
806 }; 808 };
809 static char *audigy_remove_ctls_1361t_adc[] = {
810 /* On the Audigy2 the AC97 playback is piped into
811 * the Philips ADC for 24bit capture */
812 "PCM Playback Switch",
813 "PCM Playback Volume",
814 "Master Mono Playback Switch",
815 "Master Mono Playback Volume",
816 "Capture Source",
817 "Capture Switch",
818 "Capture Volume",
819 "Mic Capture Volume",
820 "Headphone Playback Switch",
821 "Headphone Playback Volume",
822 "3D Control - Center",
823 "3D Control - Depth",
824 "3D Control - Switch",
825 "Line2 Playback Volume",
826 "Line2 Capture Volume",
827 NULL
828 };
829 static char *audigy_rename_ctls_1361t_adc[] = {
830 "Master Playback Switch", "Master Capture Switch",
831 "Master Playback Volume", "Master Capture Volume",
832 "Wave Master Playback Volume", "Master Playback Volume",
833 "PC Speaker Playback Switch", "PC Speaker Capture Switch",
834 "PC Speaker Playback Volume", "PC Speaker Capture Volume",
835 "Phone Playback Switch", "Phone Capture Switch",
836 "Phone Playback Volume", "Phone Capture Volume",
837 "Mic Playback Switch", "Mic Capture Switch",
838 "Mic Playback Volume", "Mic Capture Volume",
839 "Line Playback Switch", "Line Capture Switch",
840 "Line Playback Volume", "Line Capture Volume",
841 "CD Playback Switch", "CD Capture Switch",
842 "CD Playback Volume", "CD Capture Volume",
843 "Aux Playback Switch", "Aux Capture Switch",
844 "Aux Playback Volume", "Aux Capture Volume",
845 "Video Playback Switch", "Video Capture Switch",
846 "Video Playback Volume", "Video Capture Volume",
847
848 NULL
849 };
807 850
808 if (emu->card_capabilities->ac97_chip) { 851 if (emu->card_capabilities->ac97_chip) {
809 struct snd_ac97_bus *pbus; 852 struct snd_ac97_bus *pbus;
@@ -834,7 +877,10 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
834 snd_ac97_write_cache(emu->ac97, AC97_MASTER, 0x0000); 877 snd_ac97_write_cache(emu->ac97, AC97_MASTER, 0x0000);
835 /* set capture source to mic */ 878 /* set capture source to mic */
836 snd_ac97_write_cache(emu->ac97, AC97_REC_SEL, 0x0000); 879 snd_ac97_write_cache(emu->ac97, AC97_REC_SEL, 0x0000);
837 c = audigy_remove_ctls; 880 if (emu->card_capabilities->adc_1361t)
881 c = audigy_remove_ctls_1361t_adc;
882 else
883 c = audigy_remove_ctls;
838 } else { 884 } else {
839 /* 885 /*
840 * Credits for cards based on STAC9758: 886 * Credits for cards based on STAC9758:
@@ -863,11 +909,15 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
863 } 909 }
864 910
865 if (emu->audigy) 911 if (emu->audigy)
866 c = audigy_rename_ctls; 912 if (emu->card_capabilities->adc_1361t)
913 c = audigy_rename_ctls_1361t_adc;
914 else
915 c = audigy_rename_ctls;
867 else 916 else
868 c = emu10k1_rename_ctls; 917 c = emu10k1_rename_ctls;
869 for (; *c; c += 2) 918 for (; *c; c += 2)
870 rename_ctl(card, c[0], c[1]); 919 rename_ctl(card, c[0], c[1]);
920
871 if (emu->card_capabilities->subsystem == 0x20071102) { /* Audigy 4 Pro */ 921 if (emu->card_capabilities->subsystem == 0x20071102) { /* Audigy 4 Pro */
872 rename_ctl(card, "Line2 Capture Volume", "Line1/Mic Capture Volume"); 922 rename_ctl(card, "Line2 Capture Volume", "Line1/Mic Capture Volume");
873 rename_ctl(card, "Analog Mix Capture Volume", "Line2 Capture Volume"); 923 rename_ctl(card, "Analog Mix Capture Volume", "Line2 Capture Volume");
diff --git a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c
index 90f1c52703a1..b939e03aaedf 100644
--- a/sound/pci/emu10k1/emuproc.c
+++ b/sound/pci/emu10k1/emuproc.c
@@ -532,57 +532,51 @@ int __devinit snd_emu10k1_proc_init(struct snd_emu10k1 * emu)
532 struct snd_info_entry *entry; 532 struct snd_info_entry *entry;
533#ifdef CONFIG_SND_DEBUG 533#ifdef CONFIG_SND_DEBUG
534 if (! snd_card_proc_new(emu->card, "io_regs", &entry)) { 534 if (! snd_card_proc_new(emu->card, "io_regs", &entry)) {
535 snd_info_set_text_ops(entry, emu, 1024, snd_emu_proc_io_reg_read); 535 snd_info_set_text_ops(entry, emu, snd_emu_proc_io_reg_read);
536 entry->c.text.write_size = 64;
537 entry->c.text.write = snd_emu_proc_io_reg_write; 536 entry->c.text.write = snd_emu_proc_io_reg_write;
538 entry->mode |= S_IWUSR; 537 entry->mode |= S_IWUSR;
539 } 538 }
540 if (! snd_card_proc_new(emu->card, "ptr_regs00a", &entry)) { 539 if (! snd_card_proc_new(emu->card, "ptr_regs00a", &entry)) {
541 snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read00a); 540 snd_info_set_text_ops(entry, emu, snd_emu_proc_ptr_reg_read00a);
542 entry->c.text.write_size = 64;
543 entry->c.text.write = snd_emu_proc_ptr_reg_write00; 541 entry->c.text.write = snd_emu_proc_ptr_reg_write00;
544 entry->mode |= S_IWUSR; 542 entry->mode |= S_IWUSR;
545 } 543 }
546 if (! snd_card_proc_new(emu->card, "ptr_regs00b", &entry)) { 544 if (! snd_card_proc_new(emu->card, "ptr_regs00b", &entry)) {
547 snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read00b); 545 snd_info_set_text_ops(entry, emu, snd_emu_proc_ptr_reg_read00b);
548 entry->c.text.write_size = 64;
549 entry->c.text.write = snd_emu_proc_ptr_reg_write00; 546 entry->c.text.write = snd_emu_proc_ptr_reg_write00;
550 entry->mode |= S_IWUSR; 547 entry->mode |= S_IWUSR;
551 } 548 }
552 if (! snd_card_proc_new(emu->card, "ptr_regs20a", &entry)) { 549 if (! snd_card_proc_new(emu->card, "ptr_regs20a", &entry)) {
553 snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read20a); 550 snd_info_set_text_ops(entry, emu, snd_emu_proc_ptr_reg_read20a);
554 entry->c.text.write_size = 64;
555 entry->c.text.write = snd_emu_proc_ptr_reg_write20; 551 entry->c.text.write = snd_emu_proc_ptr_reg_write20;
556 entry->mode |= S_IWUSR; 552 entry->mode |= S_IWUSR;
557 } 553 }
558 if (! snd_card_proc_new(emu->card, "ptr_regs20b", &entry)) { 554 if (! snd_card_proc_new(emu->card, "ptr_regs20b", &entry)) {
559 snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read20b); 555 snd_info_set_text_ops(entry, emu, snd_emu_proc_ptr_reg_read20b);
560 entry->c.text.write_size = 64;
561 entry->c.text.write = snd_emu_proc_ptr_reg_write20; 556 entry->c.text.write = snd_emu_proc_ptr_reg_write20;
562 entry->mode |= S_IWUSR; 557 entry->mode |= S_IWUSR;
563 } 558 }
564 if (! snd_card_proc_new(emu->card, "ptr_regs20c", &entry)) { 559 if (! snd_card_proc_new(emu->card, "ptr_regs20c", &entry)) {
565 snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read20c); 560 snd_info_set_text_ops(entry, emu, snd_emu_proc_ptr_reg_read20c);
566 entry->c.text.write_size = 64;
567 entry->c.text.write = snd_emu_proc_ptr_reg_write20; 561 entry->c.text.write = snd_emu_proc_ptr_reg_write20;
568 entry->mode |= S_IWUSR; 562 entry->mode |= S_IWUSR;
569 } 563 }
570#endif 564#endif
571 565
572 if (! snd_card_proc_new(emu->card, "emu10k1", &entry)) 566 if (! snd_card_proc_new(emu->card, "emu10k1", &entry))
573 snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_read); 567 snd_info_set_text_ops(entry, emu, snd_emu10k1_proc_read);
574 568
575 if (emu->card_capabilities->emu10k2_chip) { 569 if (emu->card_capabilities->emu10k2_chip) {
576 if (! snd_card_proc_new(emu->card, "spdif-in", &entry)) 570 if (! snd_card_proc_new(emu->card, "spdif-in", &entry))
577 snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_spdif_read); 571 snd_info_set_text_ops(entry, emu, snd_emu10k1_proc_spdif_read);
578 } 572 }
579 if (emu->card_capabilities->ca0151_chip) { 573 if (emu->card_capabilities->ca0151_chip) {
580 if (! snd_card_proc_new(emu->card, "capture-rates", &entry)) 574 if (! snd_card_proc_new(emu->card, "capture-rates", &entry))
581 snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_rates_read); 575 snd_info_set_text_ops(entry, emu, snd_emu10k1_proc_rates_read);
582 } 576 }
583 577
584 if (! snd_card_proc_new(emu->card, "voices", &entry)) 578 if (! snd_card_proc_new(emu->card, "voices", &entry))
585 snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_voices_read); 579 snd_info_set_text_ops(entry, emu, snd_emu10k1_proc_voices_read);
586 580
587 if (! snd_card_proc_new(emu->card, "fx8010_gpr", &entry)) { 581 if (! snd_card_proc_new(emu->card, "fx8010_gpr", &entry)) {
588 entry->content = SNDRV_INFO_CONTENT_DATA; 582 entry->content = SNDRV_INFO_CONTENT_DATA;
@@ -616,7 +610,6 @@ int __devinit snd_emu10k1_proc_init(struct snd_emu10k1 * emu)
616 entry->content = SNDRV_INFO_CONTENT_TEXT; 610 entry->content = SNDRV_INFO_CONTENT_TEXT;
617 entry->private_data = emu; 611 entry->private_data = emu;
618 entry->mode = S_IFREG | S_IRUGO /*| S_IWUSR*/; 612 entry->mode = S_IFREG | S_IRUGO /*| S_IWUSR*/;
619 entry->c.text.read_size = 128*1024;
620 entry->c.text.read = snd_emu10k1_proc_acode_read; 613 entry->c.text.read = snd_emu10k1_proc_acode_read;
621 } 614 }
622 return 0; 615 return 0;
diff --git a/sound/pci/emu10k1/io.c b/sound/pci/emu10k1/io.c
index ef5304df8c11..029e7856c43b 100644
--- a/sound/pci/emu10k1/io.c
+++ b/sound/pci/emu10k1/io.c
@@ -62,6 +62,8 @@ unsigned int snd_emu10k1_ptr_read(struct snd_emu10k1 * emu, unsigned int reg, un
62 } 62 }
63} 63}
64 64
65EXPORT_SYMBOL(snd_emu10k1_ptr_read);
66
65void snd_emu10k1_ptr_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned int chn, unsigned int data) 67void snd_emu10k1_ptr_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned int chn, unsigned int data)
66{ 68{
67 unsigned int regptr; 69 unsigned int regptr;
@@ -92,6 +94,8 @@ void snd_emu10k1_ptr_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned i
92 } 94 }
93} 95}
94 96
97EXPORT_SYMBOL(snd_emu10k1_ptr_write);
98
95unsigned int snd_emu10k1_ptr20_read(struct snd_emu10k1 * emu, 99unsigned int snd_emu10k1_ptr20_read(struct snd_emu10k1 * emu,
96 unsigned int reg, 100 unsigned int reg,
97 unsigned int chn) 101 unsigned int chn)
diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c
index e7ec98649f04..4fcaefe5a3c5 100644
--- a/sound/pci/emu10k1/memory.c
+++ b/sound/pci/emu10k1/memory.c
@@ -287,6 +287,8 @@ int snd_emu10k1_memblk_map(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *b
287 return err; 287 return err;
288} 288}
289 289
290EXPORT_SYMBOL(snd_emu10k1_memblk_map);
291
290/* 292/*
291 * page allocation for DMA 293 * page allocation for DMA
292 */ 294 */
@@ -387,6 +389,7 @@ snd_emu10k1_synth_alloc(struct snd_emu10k1 *hw, unsigned int size)
387 return (struct snd_util_memblk *)blk; 389 return (struct snd_util_memblk *)blk;
388} 390}
389 391
392EXPORT_SYMBOL(snd_emu10k1_synth_alloc);
390 393
391/* 394/*
392 * free a synth sample area 395 * free a synth sample area
@@ -409,6 +412,7 @@ snd_emu10k1_synth_free(struct snd_emu10k1 *emu, struct snd_util_memblk *memblk)
409 return 0; 412 return 0;
410} 413}
411 414
415EXPORT_SYMBOL(snd_emu10k1_synth_free);
412 416
413/* check new allocation range */ 417/* check new allocation range */
414static void get_single_page_range(struct snd_util_memhdr *hdr, 418static void get_single_page_range(struct snd_util_memhdr *hdr,
@@ -540,6 +544,8 @@ int snd_emu10k1_synth_bzero(struct snd_emu10k1 *emu, struct snd_util_memblk *blk
540 return 0; 544 return 0;
541} 545}
542 546
547EXPORT_SYMBOL(snd_emu10k1_synth_bzero);
548
543/* 549/*
544 * copy_from_user(blk + offset, data, size) 550 * copy_from_user(blk + offset, data, size)
545 */ 551 */
@@ -568,3 +574,5 @@ int snd_emu10k1_synth_copy_from_user(struct snd_emu10k1 *emu, struct snd_util_me
568 } while (offset < end_offset); 574 } while (offset < end_offset);
569 return 0; 575 return 0;
570} 576}
577
578EXPORT_SYMBOL(snd_emu10k1_synth_copy_from_user);
diff --git a/sound/pci/emu10k1/p17v.h b/sound/pci/emu10k1/p17v.h
new file mode 100644
index 000000000000..7ddb5be632cf
--- /dev/null
+++ b/sound/pci/emu10k1/p17v.h
@@ -0,0 +1,111 @@
1/*
2 * Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk>
3 * Driver p17v chips
4 * Version: 0.01
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 */
21
22/******************************************************************************/
23/* Audigy2Value Tina (P17V) pointer-offset register set,
24 * accessed through the PTR20 and DATA24 registers */
25/******************************************************************************/
26
27/* 00 - 07: Not used */
28#define P17V_PLAYBACK_FIFO_PTR 0x08 /* Current playback fifo pointer
29 * and number of sound samples in cache.
30 */
31/* 09 - 12: Not used */
32#define P17V_CAPTURE_FIFO_PTR 0x13 /* Current capture fifo pointer
33 * and number of sound samples in cache.
34 */
35/* 14 - 17: Not used */
36#define P17V_PB_CHN_SEL 0x18 /* P17v playback channel select */
37#define P17V_SE_SLOT_SEL_L 0x19 /* Sound Engine slot select low */
38#define P17V_SE_SLOT_SEL_H 0x1a /* Sound Engine slot select high */
39/* 1b - 1f: Not used */
40/* 20 - 2f: Not used */
41/* 30 - 3b: Not used */
42#define P17V_SPI 0x3c /* SPI interface register */
43#define P17V_I2C_ADDR 0x3d /* I2C Address */
44#define P17V_I2C_0 0x3e /* I2C Data */
45#define P17V_I2C_1 0x3f /* I2C Data */
46
47#define P17V_START_AUDIO 0x40 /* Start Audio bit */
48/* 41 - 47: Reserved */
49#define P17V_START_CAPTURE 0x48 /* Start Capture bit */
50#define P17V_CAPTURE_FIFO_BASE 0x49 /* Record FIFO base address */
51#define P17V_CAPTURE_FIFO_SIZE 0x4a /* Record FIFO buffer size */
52#define P17V_CAPTURE_FIFO_INDEX 0x4b /* Record FIFO capture index */
53#define P17V_CAPTURE_VOL_H 0x4c /* P17v capture volume control */
54#define P17V_CAPTURE_VOL_L 0x4d /* P17v capture volume control */
55/* 4e - 4f: Not used */
56/* 50 - 5f: Not used */
57#define P17V_SRCSel 0x60 /* SRC48 and SRCMulti sample rate select
58 * and output select
59 */
60#define P17V_MIXER_AC97_10K1_VOL_L 0x61 /* 10K to Mixer_AC97 input volume control */
61#define P17V_MIXER_AC97_10K1_VOL_H 0x62 /* 10K to Mixer_AC97 input volume control */
62#define P17V_MIXER_AC97_P17V_VOL_L 0x63 /* P17V to Mixer_AC97 input volume control */
63#define P17V_MIXER_AC97_P17V_VOL_H 0x64 /* P17V to Mixer_AC97 input volume control */
64#define P17V_MIXER_AC97_SRP_REC_VOL_L 0x65 /* SRP Record to Mixer_AC97 input volume control */
65#define P17V_MIXER_AC97_SRP_REC_VOL_H 0x66 /* SRP Record to Mixer_AC97 input volume control */
66/* 67 - 68: Reserved */
67#define P17V_MIXER_Spdif_10K1_VOL_L 0x69 /* 10K to Mixer_Spdif input volume control */
68#define P17V_MIXER_Spdif_10K1_VOL_H 0x6A /* 10K to Mixer_Spdif input volume control */
69#define P17V_MIXER_Spdif_P17V_VOL_L 0x6B /* P17V to Mixer_Spdif input volume control */
70#define P17V_MIXER_Spdif_P17V_VOL_H 0x6C /* P17V to Mixer_Spdif input volume control */
71#define P17V_MIXER_Spdif_SRP_REC_VOL_L 0x6D /* SRP Record to Mixer_Spdif input volume control */
72#define P17V_MIXER_Spdif_SRP_REC_VOL_H 0x6E /* SRP Record to Mixer_Spdif input volume control */
73/* 6f - 70: Reserved */
74#define P17V_MIXER_I2S_10K1_VOL_L 0x71 /* 10K to Mixer_I2S input volume control */
75#define P17V_MIXER_I2S_10K1_VOL_H 0x72 /* 10K to Mixer_I2S input volume control */
76#define P17V_MIXER_I2S_P17V_VOL_L 0x73 /* P17V to Mixer_I2S input volume control */
77#define P17V_MIXER_I2S_P17V_VOL_H 0x74 /* P17V to Mixer_I2S input volume control */
78#define P17V_MIXER_I2S_SRP_REC_VOL_L 0x75 /* SRP Record to Mixer_I2S input volume control */
79#define P17V_MIXER_I2S_SRP_REC_VOL_H 0x76 /* SRP Record to Mixer_I2S input volume control */
80/* 77 - 78: Reserved */
81#define P17V_MIXER_AC97_ENABLE 0x79 /* Mixer AC97 input audio enable */
82#define P17V_MIXER_SPDIF_ENABLE 0x7A /* Mixer SPDIF input audio enable */
83#define P17V_MIXER_I2S_ENABLE 0x7B /* Mixer I2S input audio enable */
84#define P17V_AUDIO_OUT_ENABLE 0x7C /* Audio out enable */
85#define P17V_MIXER_ATT 0x7D /* SRP Mixer Attenuation Select */
86#define P17V_SRP_RECORD_SRR 0x7E /* SRP Record channel source Select */
87#define P17V_SOFT_RESET_SRP_MIXER 0x7F /* SRP and mixer soft reset */
88
89#define P17V_AC97_OUT_MASTER_VOL_L 0x80 /* AC97 Output master volume control */
90#define P17V_AC97_OUT_MASTER_VOL_H 0x81 /* AC97 Output master volume control */
91#define P17V_SPDIF_OUT_MASTER_VOL_L 0x82 /* SPDIF Output master volume control */
92#define P17V_SPDIF_OUT_MASTER_VOL_H 0x83 /* SPDIF Output master volume control */
93#define P17V_I2S_OUT_MASTER_VOL_L 0x84 /* I2S Output master volume control */
94#define P17V_I2S_OUT_MASTER_VOL_H 0x85 /* I2S Output master volume control */
95/* 86 - 87: Not used */
96#define P17V_I2S_CHANNEL_SWAP_PHASE_INVERSE 0x88 /* I2S out mono channel swap
97 * and phase inverse */
98#define P17V_SPDIF_CHANNEL_SWAP_PHASE_INVERSE 0x89 /* SPDIF out mono channel swap
99 * and phase inverse */
100/* 8A: Not used */
101#define P17V_SRP_P17V_ESR 0x8B /* SRP_P17V estimated sample rate and rate lock */
102#define P17V_SRP_REC_ESR 0x8C /* SRP_REC estimated sample rate and rate lock */
103#define P17V_SRP_BYPASS 0x8D /* srps channel bypass and srps bypass */
104/* 8E - 92: Not used */
105#define P17V_I2S_SRC_SEL 0x93 /* I2SIN mode sel */
106
107
108
109
110
111
diff --git a/sound/pci/emu10k1/tina2.h b/sound/pci/emu10k1/tina2.h
index 5c43abf03e89..f2d8eb6c89e1 100644
--- a/sound/pci/emu10k1/tina2.h
+++ b/sound/pci/emu10k1/tina2.h
@@ -1,11 +1,7 @@
1/* 1/*
2 * Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk> 2 * Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk>
3 * Driver p16v chips 3 * Driver tina2 chips
4 * Version: 0.21 4 * Version: 0.1
5 *
6 *
7 * This code was initally based on code from ALSA's emu10k1x.c which is:
8 * Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com>
9 * 5 *
10 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by 7 * it under the terms of the GNU General Public License as published by
diff --git a/sound/pci/emu10k1/voice.c b/sound/pci/emu10k1/voice.c
index 56ffb7dc3ee2..94eca82dd4fc 100644
--- a/sound/pci/emu10k1/voice.c
+++ b/sound/pci/emu10k1/voice.c
@@ -139,6 +139,8 @@ int snd_emu10k1_voice_alloc(struct snd_emu10k1 *emu, int type, int number,
139 return result; 139 return result;
140} 140}
141 141
142EXPORT_SYMBOL(snd_emu10k1_voice_alloc);
143
142int snd_emu10k1_voice_free(struct snd_emu10k1 *emu, 144int snd_emu10k1_voice_free(struct snd_emu10k1 *emu,
143 struct snd_emu10k1_voice *pvoice) 145 struct snd_emu10k1_voice *pvoice)
144{ 146{
@@ -153,3 +155,5 @@ int snd_emu10k1_voice_free(struct snd_emu10k1 *emu,
153 spin_unlock_irqrestore(&emu->voice_lock, flags); 155 spin_unlock_irqrestore(&emu->voice_lock, flags);
154 return 0; 156 return 0;
155} 157}
158
159EXPORT_SYMBOL(snd_emu10k1_voice_free);
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index ca9e34e88f62..9d46bbee2a40 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -1915,7 +1915,7 @@ static void __devinit snd_ensoniq_proc_init(struct ensoniq * ensoniq)
1915 struct snd_info_entry *entry; 1915 struct snd_info_entry *entry;
1916 1916
1917 if (! snd_card_proc_new(ensoniq->card, "audiopci", &entry)) 1917 if (! snd_card_proc_new(ensoniq->card, "audiopci", &entry))
1918 snd_info_set_text_ops(entry, ensoniq, 1024, snd_ensoniq_proc_read); 1918 snd_info_set_text_ops(entry, ensoniq, snd_ensoniq_proc_read);
1919} 1919}
1920 1920
1921/* 1921/*
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
index 6f9094ca4fb4..ca6603fe0b11 100644
--- a/sound/pci/es1938.c
+++ b/sound/pci/es1938.c
@@ -1756,7 +1756,8 @@ static int __devinit snd_es1938_probe(struct pci_dev *pci,
1756 } 1756 }
1757 } 1757 }
1758 if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, 1758 if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
1759 chip->mpu_port, 1, chip->irq, 0, &chip->rmidi) < 0) { 1759 chip->mpu_port, MPU401_INFO_INTEGRATED,
1760 chip->irq, 0, &chip->rmidi) < 0) {
1760 printk(KERN_ERR "es1938: unable to initialize MPU-401\n"); 1761 printk(KERN_ERR "es1938: unable to initialize MPU-401\n");
1761 } else { 1762 } else {
1762 // this line is vital for MIDI interrupt handling on ess-solo1 1763 // this line is vital for MIDI interrupt handling on ess-solo1
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index 5ff4175c7b6d..bfa0876e715e 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -132,7 +132,7 @@ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card *
132static int total_bufsize[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1024 }; 132static int total_bufsize[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1024 };
133static int pcm_substreams_p[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4 }; 133static int pcm_substreams_p[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4 };
134static int pcm_substreams_c[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1 }; 134static int pcm_substreams_c[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1 };
135static int clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; 135static int clock[SNDRV_CARDS];
136static int use_pm[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; 136static int use_pm[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};
137static int enable_mpu[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; 137static int enable_mpu[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};
138#ifdef SUPPORT_JOYSTICK 138#ifdef SUPPORT_JOYSTICK
@@ -2727,7 +2727,8 @@ static int __devinit snd_es1968_probe(struct pci_dev *pci,
2727 } 2727 }
2728 if (enable_mpu[dev]) { 2728 if (enable_mpu[dev]) {
2729 if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, 2729 if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
2730 chip->io_port + ESM_MPU401_PORT, 1, 2730 chip->io_port + ESM_MPU401_PORT,
2731 MPU401_INFO_INTEGRATED,
2731 chip->irq, 0, &chip->rmidi)) < 0) { 2732 chip->irq, 0, &chip->rmidi)) < 0) {
2732 printk(KERN_WARNING "es1968: skipping MPU-401 MIDI support..\n"); 2733 printk(KERN_WARNING "es1968: skipping MPU-401 MIDI support..\n");
2733 } 2734 }
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
index d72fc28c580e..0afa573dd244 100644
--- a/sound/pci/fm801.c
+++ b/sound/pci/fm801.c
@@ -56,7 +56,7 @@ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card *
56 * 3 = MediaForte 64-PCR 56 * 3 = MediaForte 64-PCR
57 * High 16-bits are video (radio) device number + 1 57 * High 16-bits are video (radio) device number + 1
58 */ 58 */
59static int tea575x_tuner[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0 }; 59static int tea575x_tuner[SNDRV_CARDS];
60 60
61module_param_array(index, int, NULL, 0444); 61module_param_array(index, int, NULL, 0444);
62MODULE_PARM_DESC(index, "Index value for the FM801 soundcard."); 62MODULE_PARM_DESC(index, "Index value for the FM801 soundcard.");
@@ -1448,7 +1448,8 @@ static int __devinit snd_card_fm801_probe(struct pci_dev *pci,
1448 return err; 1448 return err;
1449 } 1449 }
1450 if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_FM801, 1450 if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_FM801,
1451 FM801_REG(chip, MPU401_DATA), 1, 1451 FM801_REG(chip, MPU401_DATA),
1452 MPU401_INFO_INTEGRATED,
1452 chip->irq, 0, &chip->rmidi)) < 0) { 1453 chip->irq, 0, &chip->rmidi)) < 0) {
1453 snd_card_free(card); 1454 snd_card_free(card);
1454 return err; 1455 return err;
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
index ddfb5ff7fb8f..dbacba6177db 100644
--- a/sound/pci/hda/Makefile
+++ b/sound/pci/hda/Makefile
@@ -1,5 +1,5 @@
1snd-hda-intel-objs := hda_intel.o 1snd-hda-intel-objs := hda_intel.o
2snd-hda-codec-objs := hda_codec.o hda_generic.o patch_realtek.o patch_cmedia.o patch_analog.o patch_sigmatel.o patch_si3054.o 2snd-hda-codec-objs := hda_codec.o hda_generic.o patch_realtek.o patch_cmedia.o patch_analog.o patch_sigmatel.o patch_si3054.o patch_atihdmi.o
3ifdef CONFIG_PROC_FS 3ifdef CONFIG_PROC_FS
4snd-hda-codec-objs += hda_proc.o 4snd-hda-codec-objs += hda_proc.o
5endif 5endif
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 5bee3b536478..8c2a8174ece1 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -86,6 +86,8 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, int dire
86 return res; 86 return res;
87} 87}
88 88
89EXPORT_SYMBOL(snd_hda_codec_read);
90
89/** 91/**
90 * snd_hda_codec_write - send a single command without waiting for response 92 * snd_hda_codec_write - send a single command without waiting for response
91 * @codec: the HDA codec 93 * @codec: the HDA codec
@@ -108,6 +110,8 @@ int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct,
108 return err; 110 return err;
109} 111}
110 112
113EXPORT_SYMBOL(snd_hda_codec_write);
114
111/** 115/**
112 * snd_hda_sequence_write - sequence writes 116 * snd_hda_sequence_write - sequence writes
113 * @codec: the HDA codec 117 * @codec: the HDA codec
@@ -122,6 +126,8 @@ void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq)
122 snd_hda_codec_write(codec, seq->nid, 0, seq->verb, seq->param); 126 snd_hda_codec_write(codec, seq->nid, 0, seq->verb, seq->param);
123} 127}
124 128
129EXPORT_SYMBOL(snd_hda_sequence_write);
130
125/** 131/**
126 * snd_hda_get_sub_nodes - get the range of sub nodes 132 * snd_hda_get_sub_nodes - get the range of sub nodes
127 * @codec: the HDA codec 133 * @codec: the HDA codec
@@ -140,6 +146,8 @@ int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid, hda_nid_t *sta
140 return (int)(parm & 0x7fff); 146 return (int)(parm & 0x7fff);
141} 147}
142 148
149EXPORT_SYMBOL(snd_hda_get_sub_nodes);
150
143/** 151/**
144 * snd_hda_get_connections - get connection list 152 * snd_hda_get_connections - get connection list
145 * @codec: the HDA codec 153 * @codec: the HDA codec
@@ -256,6 +264,8 @@ int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex)
256 return 0; 264 return 0;
257} 265}
258 266
267EXPORT_SYMBOL(snd_hda_queue_unsol_event);
268
259/* 269/*
260 * process queueud unsolicited events 270 * process queueud unsolicited events
261 */ 271 */
@@ -384,6 +394,7 @@ int snd_hda_bus_new(struct snd_card *card, const struct hda_bus_template *temp,
384 return 0; 394 return 0;
385} 395}
386 396
397EXPORT_SYMBOL(snd_hda_bus_new);
387 398
388/* 399/*
389 * find a matching codec preset 400 * find a matching codec preset
@@ -587,6 +598,8 @@ int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
587 return 0; 598 return 0;
588} 599}
589 600
601EXPORT_SYMBOL(snd_hda_codec_new);
602
590/** 603/**
591 * snd_hda_codec_setup_stream - set up the codec for streaming 604 * snd_hda_codec_setup_stream - set up the codec for streaming
592 * @codec: the CODEC to set up 605 * @codec: the CODEC to set up
@@ -609,6 +622,7 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, u32 stre
609 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format); 622 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format);
610} 623}
611 624
625EXPORT_SYMBOL(snd_hda_codec_setup_stream);
612 626
613/* 627/*
614 * amp access functions 628 * amp access functions
@@ -1294,6 +1308,7 @@ int snd_hda_build_controls(struct hda_bus *bus)
1294 return 0; 1308 return 0;
1295} 1309}
1296 1310
1311EXPORT_SYMBOL(snd_hda_build_controls);
1297 1312
1298/* 1313/*
1299 * stream formats 1314 * stream formats
@@ -1382,6 +1397,8 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
1382 return val; 1397 return val;
1383} 1398}
1384 1399
1400EXPORT_SYMBOL(snd_hda_calc_stream_format);
1401
1385/** 1402/**
1386 * snd_hda_query_supported_pcm - query the supported PCM rates and formats 1403 * snd_hda_query_supported_pcm - query the supported PCM rates and formats
1387 * @codec: the HDA codec 1404 * @codec: the HDA codec
@@ -1663,6 +1680,7 @@ int snd_hda_build_pcms(struct hda_bus *bus)
1663 return 0; 1680 return 0;
1664} 1681}
1665 1682
1683EXPORT_SYMBOL(snd_hda_build_pcms);
1666 1684
1667/** 1685/**
1668 * snd_hda_check_board_config - compare the current codec with the config table 1686 * snd_hda_check_board_config - compare the current codec with the config table
@@ -2165,6 +2183,8 @@ int snd_hda_suspend(struct hda_bus *bus, pm_message_t state)
2165 return 0; 2183 return 0;
2166} 2184}
2167 2185
2186EXPORT_SYMBOL(snd_hda_suspend);
2187
2168/** 2188/**
2169 * snd_hda_resume - resume the codecs 2189 * snd_hda_resume - resume the codecs
2170 * @bus: the HDA bus 2190 * @bus: the HDA bus
@@ -2187,6 +2207,8 @@ int snd_hda_resume(struct hda_bus *bus)
2187 return 0; 2207 return 0;
2188} 2208}
2189 2209
2210EXPORT_SYMBOL(snd_hda_resume);
2211
2190/** 2212/**
2191 * snd_hda_resume_ctls - resume controls in the new control list 2213 * snd_hda_resume_ctls - resume controls in the new control list
2192 * @codec: the HDA codec 2214 * @codec: the HDA codec
@@ -2247,25 +2269,6 @@ int snd_hda_resume_spdif_in(struct hda_codec *codec)
2247#endif 2269#endif
2248 2270
2249/* 2271/*
2250 * symbols exported for controller modules
2251 */
2252EXPORT_SYMBOL(snd_hda_codec_read);
2253EXPORT_SYMBOL(snd_hda_codec_write);
2254EXPORT_SYMBOL(snd_hda_sequence_write);
2255EXPORT_SYMBOL(snd_hda_get_sub_nodes);
2256EXPORT_SYMBOL(snd_hda_queue_unsol_event);
2257EXPORT_SYMBOL(snd_hda_bus_new);
2258EXPORT_SYMBOL(snd_hda_codec_new);
2259EXPORT_SYMBOL(snd_hda_codec_setup_stream);
2260EXPORT_SYMBOL(snd_hda_calc_stream_format);
2261EXPORT_SYMBOL(snd_hda_build_pcms);
2262EXPORT_SYMBOL(snd_hda_build_controls);
2263#ifdef CONFIG_PM
2264EXPORT_SYMBOL(snd_hda_suspend);
2265EXPORT_SYMBOL(snd_hda_resume);
2266#endif
2267
2268/*
2269 * INIT part 2272 * INIT part
2270 */ 2273 */
2271 2274
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index e821d65afa11..4070b5cd9b6b 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -82,6 +82,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},"
82 "{Intel, ICH8}," 82 "{Intel, ICH8},"
83 "{ATI, SB450}," 83 "{ATI, SB450},"
84 "{ATI, SB600}," 84 "{ATI, SB600},"
85 "{ATI, RS600},"
85 "{VIA, VT8251}," 86 "{VIA, VT8251},"
86 "{VIA, VT8237A}," 87 "{VIA, VT8237A},"
87 "{SiS, SIS966}," 88 "{SiS, SIS966},"
@@ -167,6 +168,12 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
167#define ULI_PLAYBACK_INDEX 5 168#define ULI_PLAYBACK_INDEX 5
168#define ULI_NUM_PLAYBACK 6 169#define ULI_NUM_PLAYBACK 6
169 170
171/* ATI HDMI has 1 playback and 0 capture */
172#define ATIHDMI_CAPTURE_INDEX 0
173#define ATIHDMI_NUM_CAPTURE 0
174#define ATIHDMI_PLAYBACK_INDEX 0
175#define ATIHDMI_NUM_PLAYBACK 1
176
170/* this number is statically defined for simplicity */ 177/* this number is statically defined for simplicity */
171#define MAX_AZX_DEV 16 178#define MAX_AZX_DEV 16
172 179
@@ -331,6 +338,7 @@ struct azx {
331enum { 338enum {
332 AZX_DRIVER_ICH, 339 AZX_DRIVER_ICH,
333 AZX_DRIVER_ATI, 340 AZX_DRIVER_ATI,
341 AZX_DRIVER_ATIHDMI,
334 AZX_DRIVER_VIA, 342 AZX_DRIVER_VIA,
335 AZX_DRIVER_SIS, 343 AZX_DRIVER_SIS,
336 AZX_DRIVER_ULI, 344 AZX_DRIVER_ULI,
@@ -340,6 +348,7 @@ enum {
340static char *driver_short_names[] __devinitdata = { 348static char *driver_short_names[] __devinitdata = {
341 [AZX_DRIVER_ICH] = "HDA Intel", 349 [AZX_DRIVER_ICH] = "HDA Intel",
342 [AZX_DRIVER_ATI] = "HDA ATI SB", 350 [AZX_DRIVER_ATI] = "HDA ATI SB",
351 [AZX_DRIVER_ATIHDMI] = "HDA ATI HDMI",
343 [AZX_DRIVER_VIA] = "HDA VIA VT82xx", 352 [AZX_DRIVER_VIA] = "HDA VIA VT82xx",
344 [AZX_DRIVER_SIS] = "HDA SIS966", 353 [AZX_DRIVER_SIS] = "HDA SIS966",
345 [AZX_DRIVER_ULI] = "HDA ULI M5461", 354 [AZX_DRIVER_ULI] = "HDA ULI M5461",
@@ -1393,10 +1402,10 @@ static int azx_free(struct azx *chip)
1393 msleep(1); 1402 msleep(1);
1394 } 1403 }
1395 1404
1396 if (chip->remap_addr)
1397 iounmap(chip->remap_addr);
1398 if (chip->irq >= 0) 1405 if (chip->irq >= 0)
1399 free_irq(chip->irq, (void*)chip); 1406 free_irq(chip->irq, (void*)chip);
1407 if (chip->remap_addr)
1408 iounmap(chip->remap_addr);
1400 1409
1401 if (chip->bdl.area) 1410 if (chip->bdl.area)
1402 snd_dma_free_pages(&chip->bdl); 1411 snd_dma_free_pages(&chip->bdl);
@@ -1495,6 +1504,12 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
1495 chip->playback_index_offset = ULI_PLAYBACK_INDEX; 1504 chip->playback_index_offset = ULI_PLAYBACK_INDEX;
1496 chip->capture_index_offset = ULI_CAPTURE_INDEX; 1505 chip->capture_index_offset = ULI_CAPTURE_INDEX;
1497 break; 1506 break;
1507 case AZX_DRIVER_ATIHDMI:
1508 chip->playback_streams = ATIHDMI_NUM_PLAYBACK;
1509 chip->capture_streams = ATIHDMI_NUM_CAPTURE;
1510 chip->playback_index_offset = ATIHDMI_PLAYBACK_INDEX;
1511 chip->capture_index_offset = ATIHDMI_CAPTURE_INDEX;
1512 break;
1498 default: 1513 default:
1499 chip->playback_streams = ICH6_NUM_PLAYBACK; 1514 chip->playback_streams = ICH6_NUM_PLAYBACK;
1500 chip->capture_streams = ICH6_NUM_CAPTURE; 1515 chip->capture_streams = ICH6_NUM_CAPTURE;
@@ -1621,6 +1636,7 @@ static struct pci_device_id azx_ids[] __devinitdata = {
1621 { 0x8086, 0x284b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH8 */ 1636 { 0x8086, 0x284b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH8 */
1622 { 0x1002, 0x437b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB450 */ 1637 { 0x1002, 0x437b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB450 */
1623 { 0x1002, 0x4383, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB600 */ 1638 { 0x1002, 0x4383, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB600 */
1639 { 0x1002, 0x793b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RS600 HDMI */
1624 { 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_VIA }, /* VIA VT8251/VT8237A */ 1640 { 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_VIA }, /* VIA VT8251/VT8237A */
1625 { 0x1039, 0x7502, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_SIS }, /* SIS966 */ 1641 { 0x1039, 0x7502, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_SIS }, /* SIS966 */
1626 { 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ULI }, /* ULI M5461 */ 1642 { 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ULI }, /* ULI M5461 */
diff --git a/sound/pci/hda/hda_patch.h b/sound/pci/hda/hda_patch.h
index acaef3c811b8..0b668793face 100644
--- a/sound/pci/hda/hda_patch.h
+++ b/sound/pci/hda/hda_patch.h
@@ -12,6 +12,8 @@ extern struct hda_codec_preset snd_hda_preset_analog[];
12extern struct hda_codec_preset snd_hda_preset_sigmatel[]; 12extern struct hda_codec_preset snd_hda_preset_sigmatel[];
13/* SiLabs 3054/3055 modem codecs */ 13/* SiLabs 3054/3055 modem codecs */
14extern struct hda_codec_preset snd_hda_preset_si3054[]; 14extern struct hda_codec_preset snd_hda_preset_si3054[];
15/* ATI HDMI codecs */
16extern struct hda_codec_preset snd_hda_preset_atihdmi[];
15 17
16static const struct hda_codec_preset *hda_preset_tables[] = { 18static const struct hda_codec_preset *hda_preset_tables[] = {
17 snd_hda_preset_realtek, 19 snd_hda_preset_realtek,
@@ -19,5 +21,6 @@ static const struct hda_codec_preset *hda_preset_tables[] = {
19 snd_hda_preset_analog, 21 snd_hda_preset_analog,
20 snd_hda_preset_sigmatel, 22 snd_hda_preset_sigmatel,
21 snd_hda_preset_si3054, 23 snd_hda_preset_si3054,
24 snd_hda_preset_atihdmi,
22 NULL 25 NULL
23}; 26};
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c
index ca514a6a5875..c2f0fe85bf35 100644
--- a/sound/pci/hda/hda_proc.c
+++ b/sound/pci/hda/hda_proc.c
@@ -182,6 +182,10 @@ static void print_pin_caps(struct snd_info_buffer *buffer,
182 snd_iprintf(buffer, " OUT"); 182 snd_iprintf(buffer, " OUT");
183 if (caps & AC_PINCAP_HP_DRV) 183 if (caps & AC_PINCAP_HP_DRV)
184 snd_iprintf(buffer, " HP"); 184 snd_iprintf(buffer, " HP");
185 if (caps & AC_PINCAP_EAPD)
186 snd_iprintf(buffer, " EAPD");
187 if (caps & AC_PINCAP_PRES_DETECT)
188 snd_iprintf(buffer, " Detect");
185 snd_iprintf(buffer, "\n"); 189 snd_iprintf(buffer, "\n");
186 caps = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); 190 caps = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
187 snd_iprintf(buffer, " Pin Default 0x%08x: [%s] %s at %s %s\n", caps, 191 snd_iprintf(buffer, " Pin Default 0x%08x: [%s] %s at %s %s\n", caps,
@@ -318,7 +322,7 @@ int snd_hda_codec_proc_new(struct hda_codec *codec)
318 if (err < 0) 322 if (err < 0)
319 return err; 323 return err;
320 324
321 snd_info_set_text_ops(entry, codec, 32 * 1024, print_codec_info); 325 snd_info_set_text_ops(entry, codec, print_codec_info);
322 return 0; 326 return 0;
323} 327}
324 328
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 40f000ba1362..dd4e00a82b55 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -789,6 +789,8 @@ static struct hda_board_config ad1986a_cfg_tbl[] = {
789 { .modelname = "3stack", .config = AD1986A_3STACK }, 789 { .modelname = "3stack", .config = AD1986A_3STACK },
790 { .pci_subvendor = 0x10de, .pci_subdevice = 0xcb84, 790 { .pci_subvendor = 0x10de, .pci_subdevice = 0xcb84,
791 .config = AD1986A_3STACK }, /* ASUS A8N-VM CSM */ 791 .config = AD1986A_3STACK }, /* ASUS A8N-VM CSM */
792 { .pci_subvendor = 0x1043, .pci_subdevice = 0x81b3,
793 .config = AD1986A_3STACK }, /* ASUS P5RD2-VM / P5GPL-X SE */
792 { .modelname = "laptop", .config = AD1986A_LAPTOP }, 794 { .modelname = "laptop", .config = AD1986A_LAPTOP },
793 { .pci_subvendor = 0x144d, .pci_subdevice = 0xc01e, 795 { .pci_subvendor = 0x144d, .pci_subdevice = 0xc01e,
794 .config = AD1986A_LAPTOP }, /* FSC V2060 */ 796 .config = AD1986A_LAPTOP }, /* FSC V2060 */
@@ -809,6 +811,8 @@ static struct hda_board_config ad1986a_cfg_tbl[] = {
809 .config = AD1986A_LAPTOP_EAPD }, /* ASUS Z62F */ 811 .config = AD1986A_LAPTOP_EAPD }, /* ASUS Z62F */
810 { .pci_subvendor = 0x103c, .pci_subdevice = 0x30af, 812 { .pci_subvendor = 0x103c, .pci_subdevice = 0x30af,
811 .config = AD1986A_LAPTOP_EAPD }, /* HP Compaq Presario B2800 */ 813 .config = AD1986A_LAPTOP_EAPD }, /* HP Compaq Presario B2800 */
814 { .pci_subvendor = 0x17aa, .pci_subdevice = 0x2066,
815 .config = AD1986A_LAPTOP_EAPD }, /* Lenovo 3000 N100-07684JU */
812 {} 816 {}
813}; 817};
814 818
@@ -963,7 +967,7 @@ static struct snd_kcontrol_new ad1983_mixers[] = {
963 }, 967 },
964 { 968 {
965 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 969 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
966 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Route", 970 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
967 .info = ad1983_spdif_route_info, 971 .info = ad1983_spdif_route_info,
968 .get = ad1983_spdif_route_get, 972 .get = ad1983_spdif_route_get,
969 .put = ad1983_spdif_route_put, 973 .put = ad1983_spdif_route_put,
@@ -1103,7 +1107,7 @@ static struct snd_kcontrol_new ad1981_mixers[] = {
1103 /* identical with AD1983 */ 1107 /* identical with AD1983 */
1104 { 1108 {
1105 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1109 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1106 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Route", 1110 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1107 .info = ad1983_spdif_route_info, 1111 .info = ad1983_spdif_route_info,
1108 .get = ad1983_spdif_route_get, 1112 .get = ad1983_spdif_route_get,
1109 .put = ad1983_spdif_route_put, 1113 .put = ad1983_spdif_route_put,
@@ -1329,13 +1333,60 @@ static int ad1981_hp_init(struct hda_codec *codec)
1329 return 0; 1333 return 0;
1330} 1334}
1331 1335
1336/* configuration for Lenovo Thinkpad T60 */
1337static struct snd_kcontrol_new ad1981_thinkpad_mixers[] = {
1338 HDA_CODEC_VOLUME("Master Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1339 HDA_CODEC_MUTE("Master Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1340 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1341 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1342 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1343 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1344 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1345 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1346 HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT),
1347 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1348 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1349 {
1350 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1351 .name = "Capture Source",
1352 .info = ad198x_mux_enum_info,
1353 .get = ad198x_mux_enum_get,
1354 .put = ad198x_mux_enum_put,
1355 },
1356 /* identical with AD1983 */
1357 {
1358 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1359 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1360 .info = ad1983_spdif_route_info,
1361 .get = ad1983_spdif_route_get,
1362 .put = ad1983_spdif_route_put,
1363 },
1364 { } /* end */
1365};
1366
1367static struct hda_input_mux ad1981_thinkpad_capture_source = {
1368 .num_items = 3,
1369 .items = {
1370 { "Mic", 0x0 },
1371 { "Mix", 0x2 },
1372 { "CD", 0x4 },
1373 },
1374};
1375
1332/* models */ 1376/* models */
1333enum { AD1981_BASIC, AD1981_HP }; 1377enum { AD1981_BASIC, AD1981_HP, AD1981_THINKPAD };
1334 1378
1335static struct hda_board_config ad1981_cfg_tbl[] = { 1379static struct hda_board_config ad1981_cfg_tbl[] = {
1336 { .modelname = "hp", .config = AD1981_HP }, 1380 { .modelname = "hp", .config = AD1981_HP },
1337 /* All HP models */ 1381 /* All HP models */
1338 { .pci_subvendor = 0x103c, .config = AD1981_HP }, 1382 { .pci_subvendor = 0x103c, .config = AD1981_HP },
1383 { .pci_subvendor = 0x30b0, .pci_subdevice = 0x103c,
1384 .config = AD1981_HP }, /* HP nx6320 (reversed SSID, H/W bug) */
1385 { .modelname = "thinkpad", .config = AD1981_THINKPAD },
1386 /* Lenovo Thinkpad T60/X60/Z6xx */
1387 { .pci_subvendor = 0x17aa, .config = AD1981_THINKPAD },
1388 { .pci_subvendor = 0x1014, .pci_subdevice = 0x0597,
1389 .config = AD1981_THINKPAD }, /* Z60m/t */
1339 { .modelname = "basic", .config = AD1981_BASIC }, 1390 { .modelname = "basic", .config = AD1981_BASIC },
1340 {} 1391 {}
1341}; 1392};
@@ -1381,6 +1432,10 @@ static int patch_ad1981(struct hda_codec *codec)
1381 codec->patch_ops.init = ad1981_hp_init; 1432 codec->patch_ops.init = ad1981_hp_init;
1382 codec->patch_ops.unsol_event = ad1981_hp_unsol_event; 1433 codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
1383 break; 1434 break;
1435 case AD1981_THINKPAD:
1436 spec->mixers[0] = ad1981_thinkpad_mixers;
1437 spec->input_mux = &ad1981_thinkpad_capture_source;
1438 break;
1384 } 1439 }
1385 1440
1386 return 0; 1441 return 0;
diff --git a/sound/pci/hda/patch_atihdmi.c b/sound/pci/hda/patch_atihdmi.c
new file mode 100644
index 000000000000..a27440ffd1c8
--- /dev/null
+++ b/sound/pci/hda/patch_atihdmi.c
@@ -0,0 +1,165 @@
1/*
2 * Universal Interface for Intel High Definition Audio Codec
3 *
4 * HD audio interface patch for ATI HDMI codecs
5 *
6 * Copyright (c) 2006 ATI Technologies Inc.
7 *
8 *
9 * This driver is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This driver is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24#include <sound/driver.h>
25#include <linux/init.h>
26#include <linux/delay.h>
27#include <linux/slab.h>
28#include <linux/pci.h>
29#include <sound/core.h>
30#include "hda_codec.h"
31#include "hda_local.h"
32
33struct atihdmi_spec {
34 struct hda_multi_out multiout;
35
36 struct hda_pcm pcm_rec;
37};
38
39static struct hda_verb atihdmi_basic_init[] = {
40 /* enable digital output on pin widget */
41 { 0x03, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
42 {} /* terminator */
43};
44
45/*
46 * Controls
47 */
48static int atihdmi_build_controls(struct hda_codec *codec)
49{
50 struct atihdmi_spec *spec = codec->spec;
51 int err;
52
53 err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
54 if (err < 0)
55 return err;
56
57 return 0;
58}
59
60static int atihdmi_init(struct hda_codec *codec)
61{
62 snd_hda_sequence_write(codec, atihdmi_basic_init);
63 return 0;
64}
65
66#ifdef CONFIG_PM
67/*
68 * resume
69 */
70static int atihdmi_resume(struct hda_codec *codec)
71{
72 atihdmi_init(codec);
73 snd_hda_resume_spdif_out(codec);
74
75 return 0;
76}
77#endif
78
79/*
80 * Digital out
81 */
82static int atihdmi_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
83 struct hda_codec *codec,
84 struct snd_pcm_substream *substream)
85{
86 struct atihdmi_spec *spec = codec->spec;
87 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
88}
89
90static int atihdmi_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
91 struct hda_codec *codec,
92 struct snd_pcm_substream *substream)
93{
94 struct atihdmi_spec *spec = codec->spec;
95 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
96}
97
98static struct hda_pcm_stream atihdmi_pcm_digital_playback = {
99 .substreams = 1,
100 .channels_min = 2,
101 .channels_max = 2,
102 .nid = 0x2, /* NID to query formats and rates and setup streams */
103 .ops = {
104 .open = atihdmi_dig_playback_pcm_open,
105 .close = atihdmi_dig_playback_pcm_close
106 },
107};
108
109static int atihdmi_build_pcms(struct hda_codec *codec)
110{
111 struct atihdmi_spec *spec = codec->spec;
112 struct hda_pcm *info = &spec->pcm_rec;
113
114 codec->num_pcms = 1;
115 codec->pcm_info = info;
116
117 info->name = "ATI HDMI";
118 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = atihdmi_pcm_digital_playback;
119
120 return 0;
121}
122
123static void atihdmi_free(struct hda_codec *codec)
124{
125 kfree(codec->spec);
126}
127
128static struct hda_codec_ops atihdmi_patch_ops = {
129 .build_controls = atihdmi_build_controls,
130 .build_pcms = atihdmi_build_pcms,
131 .init = atihdmi_init,
132 .free = atihdmi_free,
133#ifdef CONFIG_PM
134 .resume = atihdmi_resume,
135#endif
136};
137
138static int patch_atihdmi(struct hda_codec *codec)
139{
140 struct atihdmi_spec *spec;
141
142 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
143 if (spec == NULL)
144 return -ENOMEM;
145
146 codec->spec = spec;
147
148 spec->multiout.num_dacs = 0; /* no analog */
149 spec->multiout.max_channels = 2;
150 spec->multiout.dig_out_nid = 0x2; /* NID for copying analog to digital,
151 * seems to be unused in pure-digital
152 * case. */
153
154 codec->patch_ops = atihdmi_patch_ops;
155
156 return 0;
157}
158
159/*
160 * patch entries
161 */
162struct hda_codec_preset snd_hda_preset_atihdmi[] = {
163 { .id = 0x1002793c, .name = "ATI RS600 HDMI", .patch = patch_atihdmi },
164 {} /* terminator */
165};
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index f0e9a9c90780..98b9f16c26ff 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -2174,6 +2174,7 @@ static struct hda_board_config alc880_cfg_tbl[] = {
2174 2174
2175 { .modelname = "lg", .config = ALC880_LG }, 2175 { .modelname = "lg", .config = ALC880_LG },
2176 { .pci_subvendor = 0x1854, .pci_subdevice = 0x003b, .config = ALC880_LG }, 2176 { .pci_subvendor = 0x1854, .pci_subdevice = 0x003b, .config = ALC880_LG },
2177 { .pci_subvendor = 0x1854, .pci_subdevice = 0x0068, .config = ALC880_LG },
2177 2178
2178 { .modelname = "lg-lw", .config = ALC880_LG_LW }, 2179 { .modelname = "lg-lw", .config = ALC880_LG_LW },
2179 { .pci_subvendor = 0x1854, .pci_subdevice = 0x0018, .config = ALC880_LG_LW }, 2180 { .pci_subvendor = 0x1854, .pci_subdevice = 0x0018, .config = ALC880_LG_LW },
@@ -3105,6 +3106,7 @@ static struct hda_verb alc260_init_verbs[] = {
3105 { } 3106 { }
3106}; 3107};
3107 3108
3109#if 0 /* should be identical with alc260_init_verbs? */
3108static struct hda_verb alc260_hp_init_verbs[] = { 3110static struct hda_verb alc260_hp_init_verbs[] = {
3109 /* Headphone and output */ 3111 /* Headphone and output */
3110 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0}, 3112 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
@@ -3151,6 +3153,7 @@ static struct hda_verb alc260_hp_init_verbs[] = {
3151 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, 3153 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
3152 { } 3154 { }
3153}; 3155};
3156#endif
3154 3157
3155static struct hda_verb alc260_hp_3013_init_verbs[] = { 3158static struct hda_verb alc260_hp_3013_init_verbs[] = {
3156 /* Line out and output */ 3159 /* Line out and output */
@@ -3822,12 +3825,16 @@ static struct hda_board_config alc260_cfg_tbl[] = {
3822 { .modelname = "basic", .config = ALC260_BASIC }, 3825 { .modelname = "basic", .config = ALC260_BASIC },
3823 { .pci_subvendor = 0x104d, .pci_subdevice = 0x81bb, 3826 { .pci_subvendor = 0x104d, .pci_subdevice = 0x81bb,
3824 .config = ALC260_BASIC }, /* Sony VAIO */ 3827 .config = ALC260_BASIC }, /* Sony VAIO */
3828 { .pci_subvendor = 0x104d, .pci_subdevice = 0x81cc,
3829 .config = ALC260_BASIC }, /* Sony VAIO VGN-S3HP */
3830 { .pci_subvendor = 0x104d, .pci_subdevice = 0x81cd,
3831 .config = ALC260_BASIC }, /* Sony VAIO */
3825 { .pci_subvendor = 0x152d, .pci_subdevice = 0x0729, 3832 { .pci_subvendor = 0x152d, .pci_subdevice = 0x0729,
3826 .config = ALC260_BASIC }, /* CTL Travel Master U553W */ 3833 .config = ALC260_BASIC }, /* CTL Travel Master U553W */
3827 { .modelname = "hp", .config = ALC260_HP }, 3834 { .modelname = "hp", .config = ALC260_HP },
3828 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3010, .config = ALC260_HP }, 3835 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3010, .config = ALC260_HP },
3829 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3011, .config = ALC260_HP }, 3836 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3011, .config = ALC260_HP },
3830 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3012, .config = ALC260_HP }, 3837 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3012, .config = ALC260_HP_3013 },
3831 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3013, .config = ALC260_HP_3013 }, 3838 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3013, .config = ALC260_HP_3013 },
3832 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3014, .config = ALC260_HP }, 3839 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3014, .config = ALC260_HP },
3833 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3015, .config = ALC260_HP }, 3840 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3015, .config = ALC260_HP },
@@ -3862,7 +3869,7 @@ static struct alc_config_preset alc260_presets[] = {
3862 .mixers = { alc260_base_output_mixer, 3869 .mixers = { alc260_base_output_mixer,
3863 alc260_input_mixer, 3870 alc260_input_mixer,
3864 alc260_capture_alt_mixer }, 3871 alc260_capture_alt_mixer },
3865 .init_verbs = { alc260_hp_init_verbs }, 3872 .init_verbs = { alc260_init_verbs },
3866 .num_dacs = ARRAY_SIZE(alc260_dac_nids), 3873 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
3867 .dac_nids = alc260_dac_nids, 3874 .dac_nids = alc260_dac_nids,
3868 .num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids), 3875 .num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids),
@@ -4094,21 +4101,6 @@ static struct snd_kcontrol_new alc882_base_mixer[] = {
4094 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 4101 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
4095 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 4102 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
4096 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 4103 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
4097 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
4098 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
4099 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
4100 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
4101 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
4102 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
4103 {
4104 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4105 /* .name = "Capture Source", */
4106 .name = "Input Source",
4107 .count = 3,
4108 .info = alc882_mux_enum_info,
4109 .get = alc882_mux_enum_get,
4110 .put = alc882_mux_enum_put,
4111 },
4112 { } /* end */ 4104 { } /* end */
4113}; 4105};
4114 4106
@@ -4342,8 +4334,6 @@ static struct alc_config_preset alc882_presets[] = {
4342 .num_dacs = ARRAY_SIZE(alc882_dac_nids), 4334 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
4343 .dac_nids = alc882_dac_nids, 4335 .dac_nids = alc882_dac_nids,
4344 .dig_out_nid = ALC882_DIGOUT_NID, 4336 .dig_out_nid = ALC882_DIGOUT_NID,
4345 .num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
4346 .adc_nids = alc882_adc_nids,
4347 .dig_in_nid = ALC882_DIGIN_NID, 4337 .dig_in_nid = ALC882_DIGIN_NID,
4348 .num_channel_mode = ARRAY_SIZE(alc882_ch_modes), 4338 .num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
4349 .channel_mode = alc882_ch_modes, 4339 .channel_mode = alc882_ch_modes,
@@ -4355,8 +4345,6 @@ static struct alc_config_preset alc882_presets[] = {
4355 .num_dacs = ARRAY_SIZE(alc882_dac_nids), 4345 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
4356 .dac_nids = alc882_dac_nids, 4346 .dac_nids = alc882_dac_nids,
4357 .dig_out_nid = ALC882_DIGOUT_NID, 4347 .dig_out_nid = ALC882_DIGOUT_NID,
4358 .num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
4359 .adc_nids = alc882_adc_nids,
4360 .dig_in_nid = ALC882_DIGIN_NID, 4348 .dig_in_nid = ALC882_DIGIN_NID,
4361 .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes), 4349 .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes),
4362 .channel_mode = alc882_sixstack_modes, 4350 .channel_mode = alc882_sixstack_modes,
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 8c440fb98603..36f199442fdc 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -41,6 +41,7 @@
41#define STAC_REF 0 41#define STAC_REF 0
42#define STAC_D945GTP3 1 42#define STAC_D945GTP3 1
43#define STAC_D945GTP5 2 43#define STAC_D945GTP5 2
44#define STAC_MACMINI 3
44 45
45struct sigmatel_spec { 46struct sigmatel_spec {
46 struct snd_kcontrol_new *mixers[4]; 47 struct snd_kcontrol_new *mixers[4];
@@ -52,6 +53,7 @@ struct sigmatel_spec {
52 unsigned int mic_switch: 1; 53 unsigned int mic_switch: 1;
53 unsigned int alt_switch: 1; 54 unsigned int alt_switch: 1;
54 unsigned int hp_detect: 1; 55 unsigned int hp_detect: 1;
56 unsigned int gpio_mute: 1;
55 57
56 /* playback */ 58 /* playback */
57 struct hda_multi_out multiout; 59 struct hda_multi_out multiout;
@@ -293,6 +295,7 @@ static unsigned int *stac922x_brd_tbl[] = {
293 ref922x_pin_configs, 295 ref922x_pin_configs,
294 d945gtp3_pin_configs, 296 d945gtp3_pin_configs,
295 d945gtp5_pin_configs, 297 d945gtp5_pin_configs,
298 NULL, /* STAC_MACMINI */
296}; 299};
297 300
298static struct hda_board_config stac922x_cfg_tbl[] = { 301static struct hda_board_config stac922x_cfg_tbl[] = {
@@ -324,6 +327,9 @@ static struct hda_board_config stac922x_cfg_tbl[] = {
324 { .pci_subvendor = PCI_VENDOR_ID_INTEL, 327 { .pci_subvendor = PCI_VENDOR_ID_INTEL,
325 .pci_subdevice = 0x0417, 328 .pci_subdevice = 0x0417,
326 .config = STAC_D945GTP5 }, /* Intel D975XBK - 5 Stack */ 329 .config = STAC_D945GTP5 }, /* Intel D975XBK - 5 Stack */
330 { .pci_subvendor = 0x8384,
331 .pci_subdevice = 0x7680,
332 .config = STAC_MACMINI }, /* Apple Mac Mini (early 2006) */
327 {} /* terminator */ 333 {} /* terminator */
328}; 334};
329 335
@@ -841,6 +847,19 @@ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const
841 } 847 }
842 } 848 }
843 849
850 if (imux->num_items == 1) {
851 /*
852 * Set the current input for the muxes.
853 * The STAC9221 has two input muxes with identical source
854 * NID lists. Hopefully this won't get confused.
855 */
856 for (i = 0; i < spec->num_muxes; i++) {
857 snd_hda_codec_write(codec, spec->mux_nids[i], 0,
858 AC_VERB_SET_CONNECT_SEL,
859 imux->items[0].index);
860 }
861 }
862
844 return 0; 863 return 0;
845} 864}
846 865
@@ -946,6 +965,45 @@ static int stac9200_parse_auto_config(struct hda_codec *codec)
946 return 1; 965 return 1;
947} 966}
948 967
968/*
969 * Early 2006 Intel Macintoshes with STAC9220X5 codecs seem to have a
970 * funky external mute control using GPIO pins.
971 */
972
973static void stac922x_gpio_mute(struct hda_codec *codec, int pin, int muted)
974{
975 unsigned int gpiostate, gpiomask, gpiodir;
976
977 gpiostate = snd_hda_codec_read(codec, codec->afg, 0,
978 AC_VERB_GET_GPIO_DATA, 0);
979
980 if (!muted)
981 gpiostate |= (1 << pin);
982 else
983 gpiostate &= ~(1 << pin);
984
985 gpiomask = snd_hda_codec_read(codec, codec->afg, 0,
986 AC_VERB_GET_GPIO_MASK, 0);
987 gpiomask |= (1 << pin);
988
989 gpiodir = snd_hda_codec_read(codec, codec->afg, 0,
990 AC_VERB_GET_GPIO_DIRECTION, 0);
991 gpiodir |= (1 << pin);
992
993 /* AppleHDA seems to do this -- WTF is this verb?? */
994 snd_hda_codec_write(codec, codec->afg, 0, 0x7e7, 0);
995
996 snd_hda_codec_write(codec, codec->afg, 0,
997 AC_VERB_SET_GPIO_MASK, gpiomask);
998 snd_hda_codec_write(codec, codec->afg, 0,
999 AC_VERB_SET_GPIO_DIRECTION, gpiodir);
1000
1001 msleep(1);
1002
1003 snd_hda_codec_write(codec, codec->afg, 0,
1004 AC_VERB_SET_GPIO_DATA, gpiostate);
1005}
1006
949static int stac92xx_init(struct hda_codec *codec) 1007static int stac92xx_init(struct hda_codec *codec)
950{ 1008{
951 struct sigmatel_spec *spec = codec->spec; 1009 struct sigmatel_spec *spec = codec->spec;
@@ -982,6 +1040,11 @@ static int stac92xx_init(struct hda_codec *codec)
982 stac92xx_auto_set_pinctl(codec, cfg->dig_in_pin, 1040 stac92xx_auto_set_pinctl(codec, cfg->dig_in_pin,
983 AC_PINCTL_IN_EN); 1041 AC_PINCTL_IN_EN);
984 1042
1043 if (spec->gpio_mute) {
1044 stac922x_gpio_mute(codec, 0, 0);
1045 stac922x_gpio_mute(codec, 1, 0);
1046 }
1047
985 return 0; 1048 return 0;
986} 1049}
987 1050
@@ -1132,7 +1195,7 @@ static int patch_stac922x(struct hda_codec *codec)
1132 spec->board_config = snd_hda_check_board_config(codec, stac922x_cfg_tbl); 1195 spec->board_config = snd_hda_check_board_config(codec, stac922x_cfg_tbl);
1133 if (spec->board_config < 0) 1196 if (spec->board_config < 0)
1134 snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, using BIOS defaults\n"); 1197 snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, using BIOS defaults\n");
1135 else { 1198 else if (stac922x_brd_tbl[spec->board_config] != NULL) {
1136 spec->num_pins = 10; 1199 spec->num_pins = 10;
1137 spec->pin_nids = stac922x_pin_nids; 1200 spec->pin_nids = stac922x_pin_nids;
1138 spec->pin_configs = stac922x_brd_tbl[spec->board_config]; 1201 spec->pin_configs = stac922x_brd_tbl[spec->board_config];
@@ -1154,6 +1217,9 @@ static int patch_stac922x(struct hda_codec *codec)
1154 return err; 1217 return err;
1155 } 1218 }
1156 1219
1220 if (spec->board_config == STAC_MACMINI)
1221 spec->gpio_mute = 1;
1222
1157 codec->patch_ops = stac92xx_patch_ops; 1223 codec->patch_ops = stac92xx_patch_ops;
1158 1224
1159 return 0; 1225 return 0;
@@ -1262,13 +1328,13 @@ static int vaio_master_sw_put(struct snd_kcontrol *kcontrol,
1262 int change; 1328 int change;
1263 1329
1264 change = snd_hda_codec_amp_update(codec, 0x02, 0, HDA_OUTPUT, 0, 1330 change = snd_hda_codec_amp_update(codec, 0x02, 0, HDA_OUTPUT, 0,
1265 0x80, valp[0] & 0x80); 1331 0x80, (valp[0] ? 0 : 0x80));
1266 change |= snd_hda_codec_amp_update(codec, 0x02, 1, HDA_OUTPUT, 0, 1332 change |= snd_hda_codec_amp_update(codec, 0x02, 1, HDA_OUTPUT, 0,
1267 0x80, valp[1] & 0x80); 1333 0x80, (valp[1] ? 0 : 0x80));
1268 snd_hda_codec_amp_update(codec, 0x05, 0, HDA_OUTPUT, 0, 1334 snd_hda_codec_amp_update(codec, 0x05, 0, HDA_OUTPUT, 0,
1269 0x80, valp[0] & 0x80); 1335 0x80, (valp[0] ? 0 : 0x80));
1270 snd_hda_codec_amp_update(codec, 0x05, 1, HDA_OUTPUT, 0, 1336 snd_hda_codec_amp_update(codec, 0x05, 1, HDA_OUTPUT, 0,
1271 0x80, valp[1] & 0x80); 1337 0x80, (valp[1] ? 0 : 0x80));
1272 return change; 1338 return change;
1273} 1339}
1274 1340
@@ -1370,6 +1436,12 @@ struct hda_codec_preset snd_hda_preset_sigmatel[] = {
1370 { .id = 0x83847681, .name = "STAC9220D/9223D A2", .patch = patch_stac922x }, 1436 { .id = 0x83847681, .name = "STAC9220D/9223D A2", .patch = patch_stac922x },
1371 { .id = 0x83847682, .name = "STAC9221 A2", .patch = patch_stac922x }, 1437 { .id = 0x83847682, .name = "STAC9221 A2", .patch = patch_stac922x },
1372 { .id = 0x83847683, .name = "STAC9221D A2", .patch = patch_stac922x }, 1438 { .id = 0x83847683, .name = "STAC9221D A2", .patch = patch_stac922x },
1439 { .id = 0x83847618, .name = "STAC9227", .patch = patch_stac922x },
1440 { .id = 0x83847619, .name = "STAC9227", .patch = patch_stac922x },
1441 { .id = 0x83847616, .name = "STAC9228", .patch = patch_stac922x },
1442 { .id = 0x83847617, .name = "STAC9228", .patch = patch_stac922x },
1443 { .id = 0x83847614, .name = "STAC9229", .patch = patch_stac922x },
1444 { .id = 0x83847615, .name = "STAC9229", .patch = patch_stac922x },
1373 { .id = 0x83847620, .name = "STAC9274", .patch = patch_stac927x }, 1445 { .id = 0x83847620, .name = "STAC9274", .patch = patch_stac927x },
1374 { .id = 0x83847621, .name = "STAC9274D", .patch = patch_stac927x }, 1446 { .id = 0x83847621, .name = "STAC9274D", .patch = patch_stac927x },
1375 { .id = 0x83847622, .name = "STAC9273X", .patch = patch_stac927x }, 1447 { .id = 0x83847622, .name = "STAC9273X", .patch = patch_stac927x },
diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c
index 336dc489aee1..ca74f5b85f42 100644
--- a/sound/pci/ice1712/aureon.c
+++ b/sound/pci/ice1712/aureon.c
@@ -1281,9 +1281,15 @@ static int aureon_set_headphone_amp(struct snd_ice1712 *ice, int enable)
1281 1281
1282 tmp2 = tmp = snd_ice1712_gpio_read(ice); 1282 tmp2 = tmp = snd_ice1712_gpio_read(ice);
1283 if (enable) 1283 if (enable)
1284 tmp |= AUREON_HP_SEL; 1284 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT)
1285 tmp |= AUREON_HP_SEL;
1286 else
1287 tmp |= PRODIGY_HP_SEL;
1285 else 1288 else
1286 tmp &= ~ AUREON_HP_SEL; 1289 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT)
1290 tmp &= ~ AUREON_HP_SEL;
1291 else
1292 tmp &= ~ PRODIGY_HP_SEL;
1287 if (tmp != tmp2) { 1293 if (tmp != tmp2) {
1288 snd_ice1712_gpio_write(ice, tmp); 1294 snd_ice1712_gpio_write(ice, tmp);
1289 return 1; 1295 return 1;
@@ -2079,16 +2085,16 @@ static unsigned char prodigy71_eeprom[] __devinitdata = {
2079}; 2085};
2080 2086
2081static unsigned char prodigy71lt_eeprom[] __devinitdata = { 2087static unsigned char prodigy71lt_eeprom[] __devinitdata = {
2082 0x0b, /* SYSCINF: clock 512, spdif-in/ADC, 4DACs */ 2088 0x4b, /* SYSCINF: clock 512, spdif-in/ADC, 4DACs */
2083 0x80, /* ACLINK: I2S */ 2089 0x80, /* ACLINK: I2S */
2084 0xfc, /* I2S: vol, 96k, 24bit, 192k */ 2090 0xfc, /* I2S: vol, 96k, 24bit, 192k */
2085 0xc3, /* SPDUF: out-en, out-int */ 2091 0xc3, /* SPDIF: out-en, out-int, spdif-in */
2086 0x00, /* GPIO_DIR */ 2092 0xff, /* GPIO_DIR */
2087 0x07, /* GPIO_DIR1 */ 2093 0xff, /* GPIO_DIR1 */
2088 0x00, /* GPIO_DIR2 */ 2094 0x5f, /* GPIO_DIR2 */
2089 0xff, /* GPIO_MASK */ 2095 0x00, /* GPIO_MASK */
2090 0xf8, /* GPIO_MASK1 */ 2096 0x00, /* GPIO_MASK1 */
2091 0xff, /* GPIO_MASK2 */ 2097 0x00, /* GPIO_MASK2 */
2092 0x00, /* GPIO_STATE */ 2098 0x00, /* GPIO_STATE */
2093 0x00, /* GPIO_STATE1 */ 2099 0x00, /* GPIO_STATE1 */
2094 0x00, /* GPIO_STATE2 */ 2100 0x00, /* GPIO_STATE2 */
diff --git a/sound/pci/ice1712/aureon.h b/sound/pci/ice1712/aureon.h
index 98a6752280f2..3b7bea656c57 100644
--- a/sound/pci/ice1712/aureon.h
+++ b/sound/pci/ice1712/aureon.h
@@ -58,5 +58,6 @@ extern struct snd_ice1712_card_info snd_vt1724_aureon_cards[];
58#define PRODIGY_WM_CS (1 << 8) 58#define PRODIGY_WM_CS (1 << 8)
59#define PRODIGY_SPI_MOSI (1 << 10) 59#define PRODIGY_SPI_MOSI (1 << 10)
60#define PRODIGY_SPI_CLK (1 << 9) 60#define PRODIGY_SPI_CLK (1 << 9)
61#define PRODIGY_HP_SEL (1 << 5)
61 62
62#endif /* __SOUND_AUREON_H */ 63#endif /* __SOUND_AUREON_H */
diff --git a/sound/pci/ice1712/ews.c b/sound/pci/ice1712/ews.c
index 2c529e741384..b135389fec6c 100644
--- a/sound/pci/ice1712/ews.c
+++ b/sound/pci/ice1712/ews.c
@@ -1031,6 +1031,9 @@ struct snd_ice1712_card_info snd_ice1712_ews_cards[] __devinitdata = {
1031 .model = "dmx6fire", 1031 .model = "dmx6fire",
1032 .chip_init = snd_ice1712_ews_init, 1032 .chip_init = snd_ice1712_ews_init,
1033 .build_controls = snd_ice1712_ews_add_controls, 1033 .build_controls = snd_ice1712_ews_add_controls,
1034 .mpu401_1_name = "MIDI-Front DMX6fire",
1035 .mpu401_2_name = "Wavetable DMX6fire",
1036 .mpu401_2_info_flags = MPU401_INFO_OUTPUT,
1034 }, 1037 },
1035 { } /* terminator */ 1038 { } /* terminator */
1036}; 1039};
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
index c56793b381e2..845907159b74 100644
--- a/sound/pci/ice1712/ice1712.c
+++ b/sound/pci/ice1712/ice1712.c
@@ -61,7 +61,6 @@
61#include <sound/core.h> 61#include <sound/core.h>
62#include <sound/cs8427.h> 62#include <sound/cs8427.h>
63#include <sound/info.h> 63#include <sound/info.h>
64#include <sound/mpu401.h>
65#include <sound/initval.h> 64#include <sound/initval.h>
66 65
67#include <sound/asoundef.h> 66#include <sound/asoundef.h>
@@ -1596,7 +1595,7 @@ static void __devinit snd_ice1712_proc_init(struct snd_ice1712 * ice)
1596 struct snd_info_entry *entry; 1595 struct snd_info_entry *entry;
1597 1596
1598 if (! snd_card_proc_new(ice->card, "ice1712", &entry)) 1597 if (! snd_card_proc_new(ice->card, "ice1712", &entry))
1599 snd_info_set_text_ops(entry, ice, 1024, snd_ice1712_proc_read); 1598 snd_info_set_text_ops(entry, ice, snd_ice1712_proc_read);
1600} 1599}
1601 1600
1602/* 1601/*
@@ -2398,13 +2397,14 @@ static int __devinit snd_ice1712_chip_init(struct snd_ice1712 *ice)
2398 udelay(200); 2397 udelay(200);
2399 outb(ICE1712_NATIVE, ICEREG(ice, CONTROL)); 2398 outb(ICE1712_NATIVE, ICEREG(ice, CONTROL));
2400 udelay(200); 2399 udelay(200);
2401 if (ice->eeprom.subvendor == ICE1712_SUBDEVICE_DMX6FIRE && !ice->dxr_enable) { 2400 if (ice->eeprom.subvendor == ICE1712_SUBDEVICE_DMX6FIRE &&
2402 /* Limit active ADCs and DACs to 6; */ 2401 !ice->dxr_enable)
2403 /* Note: DXR extension not supported */ 2402 /* Set eeprom value to limit active ADCs and DACs to 6;
2404 pci_write_config_byte(ice->pci, 0x60, 0x2a); 2403 * Also disable AC97 as no hardware in standard 6fire card/box
2405 } else { 2404 * Note: DXR extensions are not currently supported
2406 pci_write_config_byte(ice->pci, 0x60, ice->eeprom.data[ICE_EEP1_CODEC]); 2405 */
2407 } 2406 ice->eeprom.data[ICE_EEP1_CODEC] = 0x3a;
2407 pci_write_config_byte(ice->pci, 0x60, ice->eeprom.data[ICE_EEP1_CODEC]);
2408 pci_write_config_byte(ice->pci, 0x61, ice->eeprom.data[ICE_EEP1_ACLINK]); 2408 pci_write_config_byte(ice->pci, 0x61, ice->eeprom.data[ICE_EEP1_ACLINK]);
2409 pci_write_config_byte(ice->pci, 0x62, ice->eeprom.data[ICE_EEP1_I2SID]); 2409 pci_write_config_byte(ice->pci, 0x62, ice->eeprom.data[ICE_EEP1_I2SID]);
2410 pci_write_config_byte(ice->pci, 0x63, ice->eeprom.data[ICE_EEP1_SPDIF]); 2410 pci_write_config_byte(ice->pci, 0x63, ice->eeprom.data[ICE_EEP1_SPDIF]);
@@ -2737,21 +2737,38 @@ static int __devinit snd_ice1712_probe(struct pci_dev *pci,
2737 2737
2738 if (! c->no_mpu401) { 2738 if (! c->no_mpu401) {
2739 if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_ICE1712, 2739 if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_ICE1712,
2740 ICEREG(ice, MPU1_CTRL), 1, 2740 ICEREG(ice, MPU1_CTRL),
2741 (c->mpu401_1_info_flags |
2742 MPU401_INFO_INTEGRATED),
2741 ice->irq, 0, 2743 ice->irq, 0,
2742 &ice->rmidi[0])) < 0) { 2744 &ice->rmidi[0])) < 0) {
2743 snd_card_free(card); 2745 snd_card_free(card);
2744 return err; 2746 return err;
2745 } 2747 }
2746 2748 if (c->mpu401_1_name)
2747 if (ice->eeprom.data[ICE_EEP1_CODEC] & ICE1712_CFG_2xMPU401) 2749 /* Prefered name available in card_info */
2750 snprintf(ice->rmidi[0]->name,
2751 sizeof(ice->rmidi[0]->name),
2752 "%s %d", c->mpu401_1_name, card->number);
2753
2754 if (ice->eeprom.data[ICE_EEP1_CODEC] & ICE1712_CFG_2xMPU401) {
2755 /* 2nd port used */
2748 if ((err = snd_mpu401_uart_new(card, 1, MPU401_HW_ICE1712, 2756 if ((err = snd_mpu401_uart_new(card, 1, MPU401_HW_ICE1712,
2749 ICEREG(ice, MPU2_CTRL), 1, 2757 ICEREG(ice, MPU2_CTRL),
2758 (c->mpu401_2_info_flags |
2759 MPU401_INFO_INTEGRATED),
2750 ice->irq, 0, 2760 ice->irq, 0,
2751 &ice->rmidi[1])) < 0) { 2761 &ice->rmidi[1])) < 0) {
2752 snd_card_free(card); 2762 snd_card_free(card);
2753 return err; 2763 return err;
2754 } 2764 }
2765 if (c->mpu401_2_name)
2766 /* Prefered name available in card_info */
2767 snprintf(ice->rmidi[1]->name,
2768 sizeof(ice->rmidi[1]->name),
2769 "%s %d", c->mpu401_2_name,
2770 card->number);
2771 }
2755 } 2772 }
2756 2773
2757 snd_ice1712_set_input_clock_source(ice, 0); 2774 snd_ice1712_set_input_clock_source(ice, 0);
diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h
index 053f8e56fd68..ce27eac40d4e 100644
--- a/sound/pci/ice1712/ice1712.h
+++ b/sound/pci/ice1712/ice1712.h
@@ -29,6 +29,7 @@
29#include <sound/ak4xxx-adda.h> 29#include <sound/ak4xxx-adda.h>
30#include <sound/ak4114.h> 30#include <sound/ak4114.h>
31#include <sound/pcm.h> 31#include <sound/pcm.h>
32#include <sound/mpu401.h>
32 33
33 34
34/* 35/*
@@ -495,6 +496,10 @@ struct snd_ice1712_card_info {
495 int (*chip_init)(struct snd_ice1712 *); 496 int (*chip_init)(struct snd_ice1712 *);
496 int (*build_controls)(struct snd_ice1712 *); 497 int (*build_controls)(struct snd_ice1712 *);
497 unsigned int no_mpu401: 1; 498 unsigned int no_mpu401: 1;
499 unsigned int mpu401_1_info_flags;
500 unsigned int mpu401_2_info_flags;
501 const char *mpu401_1_name;
502 const char *mpu401_2_name;
498 unsigned int eeprom_size; 503 unsigned int eeprom_size;
499 unsigned char *eeprom_data; 504 unsigned char *eeprom_data;
500}; 505};
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index b1c007e022d2..34a58c629f47 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -1293,7 +1293,7 @@ static void __devinit snd_vt1724_proc_init(struct snd_ice1712 * ice)
1293 struct snd_info_entry *entry; 1293 struct snd_info_entry *entry;
1294 1294
1295 if (! snd_card_proc_new(ice->card, "ice1724", &entry)) 1295 if (! snd_card_proc_new(ice->card, "ice1724", &entry))
1296 snd_info_set_text_ops(entry, ice, 1024, snd_vt1724_proc_read); 1296 snd_info_set_text_ops(entry, ice, snd_vt1724_proc_read);
1297} 1297}
1298 1298
1299/* 1299/*
@@ -2388,7 +2388,8 @@ static int __devinit snd_vt1724_probe(struct pci_dev *pci,
2388 if (! c->no_mpu401) { 2388 if (! c->no_mpu401) {
2389 if (ice->eeprom.data[ICE_EEP2_SYSCONF] & VT1724_CFG_MPU401) { 2389 if (ice->eeprom.data[ICE_EEP2_SYSCONF] & VT1724_CFG_MPU401) {
2390 if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_ICE1712, 2390 if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_ICE1712,
2391 ICEREG1724(ice, MPU_CTRL), 1, 2391 ICEREG1724(ice, MPU_CTRL),
2392 MPU401_INFO_INTEGRATED,
2392 ice->irq, 0, 2393 ice->irq, 0,
2393 &ice->rmidi[0])) < 0) { 2394 &ice->rmidi[0])) < 0) {
2394 snd_card_free(card); 2395 snd_card_free(card);
diff --git a/sound/pci/ice1712/pontis.c b/sound/pci/ice1712/pontis.c
index d23fb3fc2133..0efcad9260a5 100644
--- a/sound/pci/ice1712/pontis.c
+++ b/sound/pci/ice1712/pontis.c
@@ -680,9 +680,8 @@ static void wm_proc_init(struct snd_ice1712 *ice)
680{ 680{
681 struct snd_info_entry *entry; 681 struct snd_info_entry *entry;
682 if (! snd_card_proc_new(ice->card, "wm_codec", &entry)) { 682 if (! snd_card_proc_new(ice->card, "wm_codec", &entry)) {
683 snd_info_set_text_ops(entry, ice, 1024, wm_proc_regs_read); 683 snd_info_set_text_ops(entry, ice, wm_proc_regs_read);
684 entry->mode |= S_IWUSR; 684 entry->mode |= S_IWUSR;
685 entry->c.text.write_size = 1024;
686 entry->c.text.write = wm_proc_regs_write; 685 entry->c.text.write = wm_proc_regs_write;
687 } 686 }
688} 687}
@@ -705,9 +704,8 @@ static void cs_proc_regs_read(struct snd_info_entry *entry, struct snd_info_buff
705static void cs_proc_init(struct snd_ice1712 *ice) 704static void cs_proc_init(struct snd_ice1712 *ice)
706{ 705{
707 struct snd_info_entry *entry; 706 struct snd_info_entry *entry;
708 if (! snd_card_proc_new(ice->card, "cs_codec", &entry)) { 707 if (! snd_card_proc_new(ice->card, "cs_codec", &entry))
709 snd_info_set_text_ops(entry, ice, 1024, cs_proc_regs_read); 708 snd_info_set_text_ops(entry, ice, cs_proc_regs_read);
710 }
711} 709}
712 710
713 711
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index 0df7602568e2..edc14475ef82 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -66,7 +66,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel,82801AA-ICH},"
66 66
67static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ 67static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
68static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ 68static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */
69static int ac97_clock = 0; 69static int ac97_clock;
70static char *ac97_quirk; 70static char *ac97_quirk;
71static int buggy_semaphore; 71static int buggy_semaphore;
72static int buggy_irq = -1; /* auto-check */ 72static int buggy_irq = -1; /* auto-check */
@@ -1807,6 +1807,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
1807 }, 1807 },
1808 { 1808 {
1809 .subvendor = 0x1028, 1809 .subvendor = 0x1028,
1810 .subdevice = 0x014e,
1811 .name = "Dell D800", /* STAC9750/51 */
1812 .type = AC97_TUNE_HP_ONLY
1813 },
1814 {
1815 .subvendor = 0x1028,
1810 .subdevice = 0x0163, 1816 .subdevice = 0x0163,
1811 .name = "Dell Unknown", /* STAC9750/51 */ 1817 .name = "Dell Unknown", /* STAC9750/51 */
1812 .type = AC97_TUNE_HP_ONLY 1818 .type = AC97_TUNE_HP_ONLY
@@ -2645,7 +2651,7 @@ static void __devinit snd_intel8x0_proc_init(struct intel8x0 * chip)
2645 struct snd_info_entry *entry; 2651 struct snd_info_entry *entry;
2646 2652
2647 if (! snd_card_proc_new(chip->card, "intel8x0", &entry)) 2653 if (! snd_card_proc_new(chip->card, "intel8x0", &entry))
2648 snd_info_set_text_ops(entry, chip, 1024, snd_intel8x0_proc_read); 2654 snd_info_set_text_ops(entry, chip, snd_intel8x0_proc_read);
2649} 2655}
2650#else 2656#else
2651#define snd_intel8x0_proc_init(x) 2657#define snd_intel8x0_proc_init(x)
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
index 720635f0cb81..24703d75b65a 100644
--- a/sound/pci/intel8x0m.c
+++ b/sound/pci/intel8x0m.c
@@ -59,7 +59,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel,82801AA-ICH},"
59 59
60static int index = -2; /* Exclude the first card */ 60static int index = -2; /* Exclude the first card */
61static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ 61static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */
62static int ac97_clock = 0; 62static int ac97_clock;
63 63
64module_param(index, int, 0444); 64module_param(index, int, 0444);
65MODULE_PARM_DESC(index, "Index value for Intel i8x0 modemcard."); 65MODULE_PARM_DESC(index, "Index value for Intel i8x0 modemcard.");
@@ -1092,7 +1092,7 @@ static void __devinit snd_intel8x0m_proc_init(struct intel8x0m * chip)
1092 struct snd_info_entry *entry; 1092 struct snd_info_entry *entry;
1093 1093
1094 if (! snd_card_proc_new(chip->card, "intel8x0m", &entry)) 1094 if (! snd_card_proc_new(chip->card, "intel8x0m", &entry))
1095 snd_info_set_text_ops(entry, chip, 1024, snd_intel8x0m_proc_read); 1095 snd_info_set_text_ops(entry, chip, snd_intel8x0m_proc_read);
1096} 1096}
1097#else /* !CONFIG_PROC_FS */ 1097#else /* !CONFIG_PROC_FS */
1098#define snd_intel8x0m_proc_init(chip) 1098#define snd_intel8x0m_proc_init(chip)
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
index e39fad1a4200..6e97932de34f 100644
--- a/sound/pci/korg1212/korg1212.c
+++ b/sound/pci/korg1212/korg1212.c
@@ -2085,7 +2085,7 @@ static void __devinit snd_korg1212_proc_init(struct snd_korg1212 *korg1212)
2085 struct snd_info_entry *entry; 2085 struct snd_info_entry *entry;
2086 2086
2087 if (! snd_card_proc_new(korg1212->card, "korg1212", &entry)) 2087 if (! snd_card_proc_new(korg1212->card, "korg1212", &entry))
2088 snd_info_set_text_ops(entry, korg1212, 1024, snd_korg1212_proc_read); 2088 snd_info_set_text_ops(entry, korg1212, snd_korg1212_proc_read);
2089} 2089}
2090 2090
2091static int 2091static int
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index 1928e06b6d82..1c344fbd964d 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -2861,7 +2861,8 @@ snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
2861#if 0 /* TODO: not supported yet */ 2861#if 0 /* TODO: not supported yet */
2862 /* TODO enable MIDI IRQ and I/O */ 2862 /* TODO enable MIDI IRQ and I/O */
2863 err = snd_mpu401_uart_new(chip->card, 0, MPU401_HW_MPU401, 2863 err = snd_mpu401_uart_new(chip->card, 0, MPU401_HW_MPU401,
2864 chip->iobase + MPU401_DATA_PORT, 1, 2864 chip->iobase + MPU401_DATA_PORT,
2865 MPU401_INFO_INTEGRATED,
2865 chip->irq, 0, &chip->rmidi); 2866 chip->irq, 0, &chip->rmidi);
2866 if (err < 0) 2867 if (err < 0)
2867 printk(KERN_WARNING "maestro3: no MIDI support.\n"); 2868 printk(KERN_WARNING "maestro3: no MIDI support.\n");
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c
index 09cc0786495a..366c4a7e65c6 100644
--- a/sound/pci/mixart/mixart.c
+++ b/sound/pci/mixart/mixart.c
@@ -1244,7 +1244,6 @@ static void __devinit snd_mixart_proc_init(struct snd_mixart *chip)
1244 /* text interface to read perf and temp meters */ 1244 /* text interface to read perf and temp meters */
1245 if (! snd_card_proc_new(chip->card, "board_info", &entry)) { 1245 if (! snd_card_proc_new(chip->card, "board_info", &entry)) {
1246 entry->private_data = chip; 1246 entry->private_data = chip;
1247 entry->c.text.read_size = 1024;
1248 entry->c.text.read = snd_mixart_proc_read; 1247 entry->c.text.read = snd_mixart_proc_read;
1249 } 1248 }
1250 1249
diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c
index dafa2235abaa..8198884b51ee 100644
--- a/sound/pci/pcxhr/pcxhr.c
+++ b/sound/pci/pcxhr/pcxhr.c
@@ -1150,9 +1150,9 @@ static void __devinit pcxhr_proc_init(struct snd_pcxhr *chip)
1150 struct snd_info_entry *entry; 1150 struct snd_info_entry *entry;
1151 1151
1152 if (! snd_card_proc_new(chip->card, "info", &entry)) 1152 if (! snd_card_proc_new(chip->card, "info", &entry))
1153 snd_info_set_text_ops(entry, chip, 1024, pcxhr_proc_info); 1153 snd_info_set_text_ops(entry, chip, pcxhr_proc_info);
1154 if (! snd_card_proc_new(chip->card, "sync", &entry)) 1154 if (! snd_card_proc_new(chip->card, "sync", &entry))
1155 snd_info_set_text_ops(entry, chip, 1024, pcxhr_proc_sync); 1155 snd_info_set_text_ops(entry, chip, pcxhr_proc_sync);
1156} 1156}
1157/* end of proc interface */ 1157/* end of proc interface */
1158 1158
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c
index d8cc985d7241..5618ec9740bd 100644
--- a/sound/pci/riptide/riptide.c
+++ b/sound/pci/riptide/riptide.c
@@ -1836,11 +1836,11 @@ static int snd_riptide_free(struct snd_riptide *chip)
1836 UNSET_GRESET(cif->hwport); 1836 UNSET_GRESET(cif->hwport);
1837 kfree(chip->cif); 1837 kfree(chip->cif);
1838 } 1838 }
1839 if (chip->irq >= 0)
1840 free_irq(chip->irq, chip);
1839 if (chip->fw_entry) 1841 if (chip->fw_entry)
1840 release_firmware(chip->fw_entry); 1842 release_firmware(chip->fw_entry);
1841 release_and_free_resource(chip->res_port); 1843 release_and_free_resource(chip->res_port);
1842 if (chip->irq >= 0)
1843 free_irq(chip->irq, chip);
1844 kfree(chip); 1844 kfree(chip);
1845 return 0; 1845 return 0;
1846} 1846}
@@ -1992,7 +1992,7 @@ static void __devinit snd_riptide_proc_init(struct snd_riptide *chip)
1992 struct snd_info_entry *entry; 1992 struct snd_info_entry *entry;
1993 1993
1994 if (!snd_card_proc_new(chip->card, "riptide", &entry)) 1994 if (!snd_card_proc_new(chip->card, "riptide", &entry))
1995 snd_info_set_text_ops(entry, chip, 4096, snd_riptide_proc_read); 1995 snd_info_set_text_ops(entry, chip, snd_riptide_proc_read);
1996} 1996}
1997 1997
1998static int __devinit snd_riptide_mixer(struct snd_riptide *chip) 1998static int __devinit snd_riptide_mixer(struct snd_riptide *chip)
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c
index 55b1d4838d97..2cb9fe98db2f 100644
--- a/sound/pci/rme32.c
+++ b/sound/pci/rme32.c
@@ -1368,18 +1368,18 @@ static int __devinit snd_rme32_create(struct rme32 * rme32)
1368 return err; 1368 return err;
1369 rme32->port = pci_resource_start(rme32->pci, 0); 1369 rme32->port = pci_resource_start(rme32->pci, 0);
1370 1370
1371 if (request_irq(pci->irq, snd_rme32_interrupt, SA_INTERRUPT | SA_SHIRQ, "RME32", (void *) rme32)) {
1372 snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
1373 return -EBUSY;
1374 }
1375 rme32->irq = pci->irq;
1376
1377 if ((rme32->iobase = ioremap_nocache(rme32->port, RME32_IO_SIZE)) == 0) { 1371 if ((rme32->iobase = ioremap_nocache(rme32->port, RME32_IO_SIZE)) == 0) {
1378 snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n", 1372 snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n",
1379 rme32->port, rme32->port + RME32_IO_SIZE - 1); 1373 rme32->port, rme32->port + RME32_IO_SIZE - 1);
1380 return -ENOMEM; 1374 return -ENOMEM;
1381 } 1375 }
1382 1376
1377 if (request_irq(pci->irq, snd_rme32_interrupt, SA_INTERRUPT | SA_SHIRQ, "RME32", (void *) rme32)) {
1378 snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
1379 return -EBUSY;
1380 }
1381 rme32->irq = pci->irq;
1382
1383 /* read the card's revision number */ 1383 /* read the card's revision number */
1384 pci_read_config_byte(pci, 8, &rme32->rev); 1384 pci_read_config_byte(pci, 8, &rme32->rev);
1385 1385
@@ -1578,7 +1578,7 @@ static void __devinit snd_rme32_proc_init(struct rme32 * rme32)
1578 struct snd_info_entry *entry; 1578 struct snd_info_entry *entry;
1579 1579
1580 if (! snd_card_proc_new(rme32->card, "rme32", &entry)) 1580 if (! snd_card_proc_new(rme32->card, "rme32", &entry))
1581 snd_info_set_text_ops(entry, rme32, 1024, snd_rme32_proc_read); 1581 snd_info_set_text_ops(entry, rme32, snd_rme32_proc_read);
1582} 1582}
1583 1583
1584/* 1584/*
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
index 3c1bc533d511..991cb18c14f3 100644
--- a/sound/pci/rme96.c
+++ b/sound/pci/rme96.c
@@ -1151,6 +1151,25 @@ static struct snd_pcm_hw_constraint_list hw_constraints_period_bytes = {
1151 .mask = 0 1151 .mask = 0
1152}; 1152};
1153 1153
1154static void
1155rme96_set_buffer_size_constraint(struct rme96 *rme96,
1156 struct snd_pcm_runtime *runtime)
1157{
1158 unsigned int size;
1159
1160 snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
1161 RME96_BUFFER_SIZE, RME96_BUFFER_SIZE);
1162 if ((size = rme96->playback_periodsize) != 0 ||
1163 (size = rme96->capture_periodsize) != 0)
1164 snd_pcm_hw_constraint_minmax(runtime,
1165 SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
1166 size, size);
1167 else
1168 snd_pcm_hw_constraint_list(runtime, 0,
1169 SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
1170 &hw_constraints_period_bytes);
1171}
1172
1154static int 1173static int
1155snd_rme96_playback_spdif_open(struct snd_pcm_substream *substream) 1174snd_rme96_playback_spdif_open(struct snd_pcm_substream *substream)
1156{ 1175{
@@ -1180,8 +1199,7 @@ snd_rme96_playback_spdif_open(struct snd_pcm_substream *substream)
1180 runtime->hw.rate_min = rate; 1199 runtime->hw.rate_min = rate;
1181 runtime->hw.rate_max = rate; 1200 runtime->hw.rate_max = rate;
1182 } 1201 }
1183 snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, RME96_BUFFER_SIZE, RME96_BUFFER_SIZE); 1202 rme96_set_buffer_size_constraint(rme96, runtime);
1184 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_period_bytes);
1185 1203
1186 rme96->wcreg_spdif_stream = rme96->wcreg_spdif; 1204 rme96->wcreg_spdif_stream = rme96->wcreg_spdif;
1187 rme96->spdif_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; 1205 rme96->spdif_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
@@ -1219,9 +1237,7 @@ snd_rme96_capture_spdif_open(struct snd_pcm_substream *substream)
1219 rme96->capture_substream = substream; 1237 rme96->capture_substream = substream;
1220 spin_unlock_irq(&rme96->lock); 1238 spin_unlock_irq(&rme96->lock);
1221 1239
1222 snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, RME96_BUFFER_SIZE, RME96_BUFFER_SIZE); 1240 rme96_set_buffer_size_constraint(rme96, runtime);
1223 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_period_bytes);
1224
1225 return 0; 1241 return 0;
1226} 1242}
1227 1243
@@ -1254,8 +1270,7 @@ snd_rme96_playback_adat_open(struct snd_pcm_substream *substream)
1254 runtime->hw.rate_min = rate; 1270 runtime->hw.rate_min = rate;
1255 runtime->hw.rate_max = rate; 1271 runtime->hw.rate_max = rate;
1256 } 1272 }
1257 snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, RME96_BUFFER_SIZE, RME96_BUFFER_SIZE); 1273 rme96_set_buffer_size_constraint(rme96, runtime);
1258 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_period_bytes);
1259 return 0; 1274 return 0;
1260} 1275}
1261 1276
@@ -1291,8 +1306,7 @@ snd_rme96_capture_adat_open(struct snd_pcm_substream *substream)
1291 rme96->capture_substream = substream; 1306 rme96->capture_substream = substream;
1292 spin_unlock_irq(&rme96->lock); 1307 spin_unlock_irq(&rme96->lock);
1293 1308
1294 snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, RME96_BUFFER_SIZE, RME96_BUFFER_SIZE); 1309 rme96_set_buffer_size_constraint(rme96, runtime);
1295 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_period_bytes);
1296 return 0; 1310 return 0;
1297} 1311}
1298 1312
@@ -1569,17 +1583,17 @@ snd_rme96_create(struct rme96 *rme96)
1569 return err; 1583 return err;
1570 rme96->port = pci_resource_start(rme96->pci, 0); 1584 rme96->port = pci_resource_start(rme96->pci, 0);
1571 1585
1586 if ((rme96->iobase = ioremap_nocache(rme96->port, RME96_IO_SIZE)) == 0) {
1587 snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n", rme96->port, rme96->port + RME96_IO_SIZE - 1);
1588 return -ENOMEM;
1589 }
1590
1572 if (request_irq(pci->irq, snd_rme96_interrupt, SA_INTERRUPT|SA_SHIRQ, "RME96", (void *)rme96)) { 1591 if (request_irq(pci->irq, snd_rme96_interrupt, SA_INTERRUPT|SA_SHIRQ, "RME96", (void *)rme96)) {
1573 snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); 1592 snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
1574 return -EBUSY; 1593 return -EBUSY;
1575 } 1594 }
1576 rme96->irq = pci->irq; 1595 rme96->irq = pci->irq;
1577 1596
1578 if ((rme96->iobase = ioremap_nocache(rme96->port, RME96_IO_SIZE)) == 0) {
1579 snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n", rme96->port, rme96->port + RME96_IO_SIZE - 1);
1580 return -ENOMEM;
1581 }
1582
1583 /* read the card's revision number */ 1597 /* read the card's revision number */
1584 pci_read_config_byte(pci, 8, &rme96->rev); 1598 pci_read_config_byte(pci, 8, &rme96->rev);
1585 1599
@@ -1805,7 +1819,7 @@ snd_rme96_proc_init(struct rme96 *rme96)
1805 struct snd_info_entry *entry; 1819 struct snd_info_entry *entry;
1806 1820
1807 if (! snd_card_proc_new(rme96->card, "rme96", &entry)) 1821 if (! snd_card_proc_new(rme96->card, "rme96", &entry))
1808 snd_info_set_text_ops(entry, rme96, 1024, snd_rme96_proc_read); 1822 snd_info_set_text_ops(entry, rme96, snd_rme96_proc_read);
1809} 1823}
1810 1824
1811/* 1825/*
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index 61f82f0d5cc6..eaf3c22449ad 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -389,7 +389,7 @@ MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP},"
389 389
390/* use hotplug firmeare loader? */ 390/* use hotplug firmeare loader? */
391#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE) 391#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
392#ifndef HDSP_USE_HWDEP_LOADER 392#if !defined(HDSP_USE_HWDEP_LOADER) && !defined(CONFIG_SND_HDSP)
393#define HDSP_FW_LOADER 393#define HDSP_FW_LOADER
394#endif 394#endif
395#endif 395#endif
@@ -3169,9 +3169,10 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
3169 char *clock_source; 3169 char *clock_source;
3170 int x; 3170 int x;
3171 3171
3172 if (hdsp_check_for_iobox (hdsp)) 3172 if (hdsp_check_for_iobox (hdsp)) {
3173 snd_iprintf(buffer, "No I/O box connected.\nPlease connect one and upload firmware.\n"); 3173 snd_iprintf(buffer, "No I/O box connected.\nPlease connect one and upload firmware.\n");
3174 return; 3174 return;
3175 }
3175 3176
3176 if (hdsp_check_for_firmware(hdsp, 0)) { 3177 if (hdsp_check_for_firmware(hdsp, 0)) {
3177 if (hdsp->state & HDSP_FirmwareCached) { 3178 if (hdsp->state & HDSP_FirmwareCached) {
@@ -3470,7 +3471,7 @@ static void __devinit snd_hdsp_proc_init(struct hdsp *hdsp)
3470 struct snd_info_entry *entry; 3471 struct snd_info_entry *entry;
3471 3472
3472 if (! snd_card_proc_new(hdsp->card, "hdsp", &entry)) 3473 if (! snd_card_proc_new(hdsp->card, "hdsp", &entry))
3473 snd_info_set_text_ops(entry, hdsp, 1024, snd_hdsp_proc_read); 3474 snd_info_set_text_ops(entry, hdsp, snd_hdsp_proc_read);
3474} 3475}
3475 3476
3476static void snd_hdsp_free_buffers(struct hdsp *hdsp) 3477static void snd_hdsp_free_buffers(struct hdsp *hdsp)
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index 722b9e6ce54a..bba1615504d3 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -2489,7 +2489,7 @@ static void __devinit snd_hdspm_proc_init(struct hdspm * hdspm)
2489 struct snd_info_entry *entry; 2489 struct snd_info_entry *entry;
2490 2490
2491 if (!snd_card_proc_new(hdspm->card, "hdspm", &entry)) 2491 if (!snd_card_proc_new(hdspm->card, "hdspm", &entry))
2492 snd_info_set_text_ops(entry, hdspm, 1024, 2492 snd_info_set_text_ops(entry, hdspm,
2493 snd_hdspm_proc_read); 2493 snd_hdspm_proc_read);
2494} 2494}
2495 2495
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c
index 75d6406303d3..3b945e8c1b15 100644
--- a/sound/pci/rme9652/rme9652.c
+++ b/sound/pci/rme9652/rme9652.c
@@ -41,7 +41,7 @@
41static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ 41static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
42static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ 42static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
43static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ 43static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
44static int precise_ptr[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0 }; /* Enable precise pointer */ 44static int precise_ptr[SNDRV_CARDS]; /* Enable precise pointer */
45 45
46module_param_array(index, int, NULL, 0444); 46module_param_array(index, int, NULL, 0444);
47MODULE_PARM_DESC(index, "Index value for RME Digi9652 (Hammerfall) soundcard."); 47MODULE_PARM_DESC(index, "Index value for RME Digi9652 (Hammerfall) soundcard.");
@@ -1787,7 +1787,7 @@ static void __devinit snd_rme9652_proc_init(struct snd_rme9652 *rme9652)
1787 struct snd_info_entry *entry; 1787 struct snd_info_entry *entry;
1788 1788
1789 if (! snd_card_proc_new(rme9652->card, "rme9652", &entry)) 1789 if (! snd_card_proc_new(rme9652->card, "rme9652", &entry))
1790 snd_info_set_text_ops(entry, rme9652, 1024, snd_rme9652_proc_read); 1790 snd_info_set_text_ops(entry, rme9652, snd_rme9652_proc_read);
1791} 1791}
1792 1792
1793static void snd_rme9652_free_buffers(struct snd_rme9652 *rme9652) 1793static void snd_rme9652_free_buffers(struct snd_rme9652 *rme9652)
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c
index 91f8bf3ae9fa..dcf402948347 100644
--- a/sound/pci/sonicvibes.c
+++ b/sound/pci/sonicvibes.c
@@ -54,8 +54,8 @@ MODULE_SUPPORTED_DEVICE("{{S3,SonicVibes PCI}}");
54static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ 54static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
55static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ 55static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
56static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ 56static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
57static int reverb[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; 57static int reverb[SNDRV_CARDS];
58static int mge[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; 58static int mge[SNDRV_CARDS];
59static unsigned int dmaio = 0x7a00; /* DDMA i/o address */ 59static unsigned int dmaio = 0x7a00; /* DDMA i/o address */
60 60
61module_param_array(index, int, NULL, 0444); 61module_param_array(index, int, NULL, 0444);
@@ -1144,7 +1144,7 @@ static void __devinit snd_sonicvibes_proc_init(struct sonicvibes * sonic)
1144 struct snd_info_entry *entry; 1144 struct snd_info_entry *entry;
1145 1145
1146 if (! snd_card_proc_new(sonic->card, "sonicvibes", &entry)) 1146 if (! snd_card_proc_new(sonic->card, "sonicvibes", &entry))
1147 snd_info_set_text_ops(entry, sonic, 1024, snd_sonicvibes_proc_read); 1147 snd_info_set_text_ops(entry, sonic, snd_sonicvibes_proc_read);
1148} 1148}
1149 1149
1150/* 1150/*
@@ -1456,7 +1456,7 @@ static int __devinit snd_sonic_probe(struct pci_dev *pci,
1456 return err; 1456 return err;
1457 } 1457 }
1458 if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_SONICVIBES, 1458 if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_SONICVIBES,
1459 sonic->midi_port, 1, 1459 sonic->midi_port, MPU401_INFO_INTEGRATED,
1460 sonic->irq, 0, 1460 sonic->irq, 0,
1461 &midi_uart)) < 0) { 1461 &midi_uart)) < 0) {
1462 snd_card_free(card); 1462 snd_card_free(card);
diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c
index 9624a5f2b875..5629b7eba96d 100644
--- a/sound/pci/trident/trident.c
+++ b/sound/pci/trident/trident.c
@@ -148,7 +148,8 @@ static int __devinit snd_trident_probe(struct pci_dev *pci,
148 } 148 }
149 if (trident->device != TRIDENT_DEVICE_ID_SI7018 && 149 if (trident->device != TRIDENT_DEVICE_ID_SI7018 &&
150 (err = snd_mpu401_uart_new(card, 0, MPU401_HW_TRID4DWAVE, 150 (err = snd_mpu401_uart_new(card, 0, MPU401_HW_TRID4DWAVE,
151 trident->midi_port, 1, 151 trident->midi_port,
152 MPU401_INFO_INTEGRATED,
152 trident->irq, 0, &trident->rmidi)) < 0) { 153 trident->irq, 0, &trident->rmidi)) < 0) {
153 snd_card_free(card); 154 snd_card_free(card);
154 return err; 155 return err;
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
index 52178b8ad49d..d99ed7237750 100644
--- a/sound/pci/trident/trident_main.c
+++ b/sound/pci/trident/trident_main.c
@@ -306,6 +306,8 @@ void snd_trident_start_voice(struct snd_trident * trident, unsigned int voice)
306 outl(mask, TRID_REG(trident, reg)); 306 outl(mask, TRID_REG(trident, reg));
307} 307}
308 308
309EXPORT_SYMBOL(snd_trident_start_voice);
310
309/*--------------------------------------------------------------------------- 311/*---------------------------------------------------------------------------
310 void snd_trident_stop_voice(struct snd_trident * trident, unsigned int voice) 312 void snd_trident_stop_voice(struct snd_trident * trident, unsigned int voice)
311 313
@@ -328,6 +330,8 @@ void snd_trident_stop_voice(struct snd_trident * trident, unsigned int voice)
328 outl(mask, TRID_REG(trident, reg)); 330 outl(mask, TRID_REG(trident, reg));
329} 331}
330 332
333EXPORT_SYMBOL(snd_trident_stop_voice);
334
331/*--------------------------------------------------------------------------- 335/*---------------------------------------------------------------------------
332 int snd_trident_allocate_pcm_channel(struct snd_trident *trident) 336 int snd_trident_allocate_pcm_channel(struct snd_trident *trident)
333 337
@@ -502,6 +506,8 @@ void snd_trident_write_voice_regs(struct snd_trident * trident,
502#endif 506#endif
503} 507}
504 508
509EXPORT_SYMBOL(snd_trident_write_voice_regs);
510
505/*--------------------------------------------------------------------------- 511/*---------------------------------------------------------------------------
506 snd_trident_write_cso_reg 512 snd_trident_write_cso_reg
507 513
@@ -3332,7 +3338,7 @@ static void __devinit snd_trident_proc_init(struct snd_trident * trident)
3332 if (trident->device == TRIDENT_DEVICE_ID_SI7018) 3338 if (trident->device == TRIDENT_DEVICE_ID_SI7018)
3333 s = "sis7018"; 3339 s = "sis7018";
3334 if (! snd_card_proc_new(trident->card, s, &entry)) 3340 if (! snd_card_proc_new(trident->card, s, &entry))
3335 snd_info_set_text_ops(entry, trident, 1024, snd_trident_proc_read); 3341 snd_info_set_text_ops(entry, trident, snd_trident_proc_read);
3336} 3342}
3337 3343
3338static int snd_trident_dev_free(struct snd_device *device) 3344static int snd_trident_dev_free(struct snd_device *device)
@@ -3884,6 +3890,8 @@ struct snd_trident_voice *snd_trident_alloc_voice(struct snd_trident * trident,
3884 return NULL; 3890 return NULL;
3885} 3891}
3886 3892
3893EXPORT_SYMBOL(snd_trident_alloc_voice);
3894
3887void snd_trident_free_voice(struct snd_trident * trident, struct snd_trident_voice *voice) 3895void snd_trident_free_voice(struct snd_trident * trident, struct snd_trident_voice *voice)
3888{ 3896{
3889 unsigned long flags; 3897 unsigned long flags;
@@ -3912,6 +3920,8 @@ void snd_trident_free_voice(struct snd_trident * trident, struct snd_trident_voi
3912 private_free(voice); 3920 private_free(voice);
3913} 3921}
3914 3922
3923EXPORT_SYMBOL(snd_trident_free_voice);
3924
3915static void snd_trident_clear_voices(struct snd_trident * trident, unsigned short v_min, unsigned short v_max) 3925static void snd_trident_clear_voices(struct snd_trident * trident, unsigned short v_min, unsigned short v_max)
3916{ 3926{
3917 unsigned int i, val, mask[2] = { 0, 0 }; 3927 unsigned int i, val, mask[2] = { 0, 0 };
@@ -3993,13 +4003,3 @@ int snd_trident_resume(struct pci_dev *pci)
3993 return 0; 4003 return 0;
3994} 4004}
3995#endif /* CONFIG_PM */ 4005#endif /* CONFIG_PM */
3996
3997EXPORT_SYMBOL(snd_trident_alloc_voice);
3998EXPORT_SYMBOL(snd_trident_free_voice);
3999EXPORT_SYMBOL(snd_trident_start_voice);
4000EXPORT_SYMBOL(snd_trident_stop_voice);
4001EXPORT_SYMBOL(snd_trident_write_voice_regs);
4002/* trident_memory.c symbols */
4003EXPORT_SYMBOL(snd_trident_synth_alloc);
4004EXPORT_SYMBOL(snd_trident_synth_free);
4005EXPORT_SYMBOL(snd_trident_synth_copy_from_user);
diff --git a/sound/pci/trident/trident_memory.c b/sound/pci/trident/trident_memory.c
index 46c6982c9e88..aff3f874131c 100644
--- a/sound/pci/trident/trident_memory.c
+++ b/sound/pci/trident/trident_memory.c
@@ -349,6 +349,7 @@ snd_trident_synth_alloc(struct snd_trident *hw, unsigned int size)
349 return blk; 349 return blk;
350} 350}
351 351
352EXPORT_SYMBOL(snd_trident_synth_alloc);
352 353
353/* 354/*
354 * free a synth sample area 355 * free a synth sample area
@@ -365,6 +366,7 @@ snd_trident_synth_free(struct snd_trident *hw, struct snd_util_memblk *blk)
365 return 0; 366 return 0;
366} 367}
367 368
369EXPORT_SYMBOL(snd_trident_synth_free);
368 370
369/* 371/*
370 * reset TLB entry and free kernel page 372 * reset TLB entry and free kernel page
@@ -486,3 +488,4 @@ int snd_trident_synth_copy_from_user(struct snd_trident *trident,
486 return 0; 488 return 0;
487} 489}
488 490
491EXPORT_SYMBOL(snd_trident_synth_copy_from_user);
diff --git a/sound/pci/trident/trident_synth.c b/sound/pci/trident/trident_synth.c
index cc7af8bc55a0..9b7dee84743b 100644
--- a/sound/pci/trident/trident_synth.c
+++ b/sound/pci/trident/trident_synth.c
@@ -914,7 +914,9 @@ static int snd_trident_synth_create_port(struct snd_trident * trident, int idx)
914 &callbacks, 914 &callbacks,
915 SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE, 915 SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE,
916 SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE | 916 SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE |
917 SNDRV_SEQ_PORT_TYPE_SYNTH, 917 SNDRV_SEQ_PORT_TYPE_SYNTH |
918 SNDRV_SEQ_PORT_TYPE_HARDWARE |
919 SNDRV_SEQ_PORT_TYPE_SYNTHESIZER,
918 16, 0, 920 16, 0,
919 name); 921 name);
920 if (p->chset->port < 0) { 922 if (p->chset->port < 0) {
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index 39daf62d2bad..2527bbd958c5 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -1775,6 +1775,12 @@ static struct ac97_quirk ac97_quirks[] = {
1775 .name = "Targa Traveller 811", 1775 .name = "Targa Traveller 811",
1776 .type = AC97_TUNE_HP_ONLY, 1776 .type = AC97_TUNE_HP_ONLY,
1777 }, 1777 },
1778 {
1779 .subvendor = 0x161f,
1780 .subdevice = 0x2032,
1781 .name = "m680x",
1782 .type = AC97_TUNE_HP_ONLY, /* http://launchpad.net/bugs/38546 */
1783 },
1778 { } /* terminator */ 1784 { } /* terminator */
1779}; 1785};
1780 1786
@@ -1973,7 +1979,7 @@ static int __devinit snd_via686_init_misc(struct via82xx *chip)
1973 pci_write_config_byte(chip->pci, VIA_PNP_CONTROL, legacy_cfg); 1979 pci_write_config_byte(chip->pci, VIA_PNP_CONTROL, legacy_cfg);
1974 if (chip->mpu_res) { 1980 if (chip->mpu_res) {
1975 if (snd_mpu401_uart_new(chip->card, 0, MPU401_HW_VIA686A, 1981 if (snd_mpu401_uart_new(chip->card, 0, MPU401_HW_VIA686A,
1976 mpu_port, 1, 1982 mpu_port, MPU401_INFO_INTEGRATED,
1977 chip->irq, 0, &chip->rmidi) < 0) { 1983 chip->irq, 0, &chip->rmidi) < 0) {
1978 printk(KERN_WARNING "unable to initialize MPU-401" 1984 printk(KERN_WARNING "unable to initialize MPU-401"
1979 " at 0x%lx, skipping\n", mpu_port); 1985 " at 0x%lx, skipping\n", mpu_port);
@@ -2015,7 +2021,7 @@ static void __devinit snd_via82xx_proc_init(struct via82xx *chip)
2015 struct snd_info_entry *entry; 2021 struct snd_info_entry *entry;
2016 2022
2017 if (! snd_card_proc_new(chip->card, "via82xx", &entry)) 2023 if (! snd_card_proc_new(chip->card, "via82xx", &entry))
2018 snd_info_set_text_ops(entry, chip, 1024, snd_via82xx_proc_read); 2024 snd_info_set_text_ops(entry, chip, snd_via82xx_proc_read);
2019} 2025}
2020 2026
2021/* 2027/*
@@ -2365,7 +2371,7 @@ static int __devinit check_dxs_list(struct pci_dev *pci, int revision)
2365 { .subvendor = 0x1462, .subdevice = 0x0470, .action = VIA_DXS_SRC }, /* MSI KT880 Delta-FSR */ 2371 { .subvendor = 0x1462, .subdevice = 0x0470, .action = VIA_DXS_SRC }, /* MSI KT880 Delta-FSR */
2366 { .subvendor = 0x1462, .subdevice = 0x3800, .action = VIA_DXS_ENABLE }, /* MSI KT266 */ 2372 { .subvendor = 0x1462, .subdevice = 0x3800, .action = VIA_DXS_ENABLE }, /* MSI KT266 */
2367 { .subvendor = 0x1462, .subdevice = 0x5901, .action = VIA_DXS_NO_VRA }, /* MSI KT6 Delta-SR */ 2373 { .subvendor = 0x1462, .subdevice = 0x5901, .action = VIA_DXS_NO_VRA }, /* MSI KT6 Delta-SR */
2368 { .subvendor = 0x1462, .subdevice = 0x7023, .action = VIA_DXS_NO_VRA }, /* MSI K8T Neo2-FI */ 2374 { .subvendor = 0x1462, .subdevice = 0x7023, .action = VIA_DXS_SRC }, /* MSI K8T Neo2-FI */
2369 { .subvendor = 0x1462, .subdevice = 0x7120, .action = VIA_DXS_ENABLE }, /* MSI KT4V */ 2375 { .subvendor = 0x1462, .subdevice = 0x7120, .action = VIA_DXS_ENABLE }, /* MSI KT4V */
2370 { .subvendor = 0x1462, .subdevice = 0x7142, .action = VIA_DXS_ENABLE }, /* MSI K8MM-V */ 2376 { .subvendor = 0x1462, .subdevice = 0x7142, .action = VIA_DXS_ENABLE }, /* MSI K8MM-V */
2371 { .subvendor = 0x1462, .subdevice = 0xb012, .action = VIA_DXS_SRC }, /* P4M800/VIA8237R */ 2377 { .subvendor = 0x1462, .subdevice = 0xb012, .action = VIA_DXS_SRC }, /* P4M800/VIA8237R */
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c
index ef97e50cd6c2..577a2b03759f 100644
--- a/sound/pci/via82xx_modem.c
+++ b/sound/pci/via82xx_modem.c
@@ -929,7 +929,7 @@ static void __devinit snd_via82xx_proc_init(struct via82xx_modem *chip)
929 struct snd_info_entry *entry; 929 struct snd_info_entry *entry;
930 930
931 if (! snd_card_proc_new(chip->card, "via82xx", &entry)) 931 if (! snd_card_proc_new(chip->card, "via82xx", &entry))
932 snd_info_set_text_ops(entry, chip, 1024, snd_via82xx_proc_read); 932 snd_info_set_text_ops(entry, chip, snd_via82xx_proc_read);
933} 933}
934 934
935/* 935/*
diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c
index 65ebf5f1933a..26aa775b7b69 100644
--- a/sound/pci/ymfpci/ymfpci.c
+++ b/sound/pci/ymfpci/ymfpci.c
@@ -308,7 +308,8 @@ static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci,
308 } 308 }
309 if (chip->mpu_res) { 309 if (chip->mpu_res) {
310 if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_YMFPCI, 310 if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_YMFPCI,
311 mpu_port[dev], 1, 311 mpu_port[dev],
312 MPU401_INFO_INTEGRATED,
312 pci->irq, 0, &chip->rawmidi)) < 0) { 313 pci->irq, 0, &chip->rawmidi)) < 0) {
313 printk(KERN_WARNING "ymfpci: cannot initialize MPU401 at 0x%lx, skipping...\n", mpu_port[dev]); 314 printk(KERN_WARNING "ymfpci: cannot initialize MPU401 at 0x%lx, skipping...\n", mpu_port[dev]);
314 legacy_ctrl &= ~YMFPCI_LEGACY_MIEN; /* disable MPU401 irq */ 315 legacy_ctrl &= ~YMFPCI_LEGACY_MIEN; /* disable MPU401 irq */
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
index 8ac5ab50b5c7..f894752523bb 100644
--- a/sound/pci/ymfpci/ymfpci_main.c
+++ b/sound/pci/ymfpci/ymfpci_main.c
@@ -1919,7 +1919,7 @@ static int __devinit snd_ymfpci_proc_init(struct snd_card *card, struct snd_ymfp
1919 struct snd_info_entry *entry; 1919 struct snd_info_entry *entry;
1920 1920
1921 if (! snd_card_proc_new(card, "ymfpci", &entry)) 1921 if (! snd_card_proc_new(card, "ymfpci", &entry))
1922 snd_info_set_text_ops(entry, chip, 1024, snd_ymfpci_proc_read); 1922 snd_info_set_text_ops(entry, chip, snd_ymfpci_proc_read);
1923 return 0; 1923 return 0;
1924} 1924}
1925 1925
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
index bd0d70ff3019..1dfe29b863d3 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
@@ -144,7 +144,7 @@ static void pdacf_proc_init(struct snd_pdacf *chip)
144 struct snd_info_entry *entry; 144 struct snd_info_entry *entry;
145 145
146 if (! snd_card_proc_new(chip->card, "pdaudiocf", &entry)) 146 if (! snd_card_proc_new(chip->card, "pdaudiocf", &entry))
147 snd_info_set_text_ops(entry, chip, 1024, pdacf_proc_read); 147 snd_info_set_text_ops(entry, chip, pdacf_proc_read);
148} 148}
149 149
150struct snd_pdacf *snd_pdacf_create(struct snd_card *card) 150struct snd_pdacf *snd_pdacf_create(struct snd_card *card)
diff --git a/sound/pcmcia/vx/vxp_ops.c b/sound/pcmcia/vx/vxp_ops.c
index 7f82f619f9f4..1ee0918c3b9f 100644
--- a/sound/pcmcia/vx/vxp_ops.c
+++ b/sound/pcmcia/vx/vxp_ops.c
@@ -202,7 +202,7 @@ static int vxp_load_xilinx_binary(struct vx_core *_chip, const struct firmware *
202 c |= (int)vx_inb(chip, RXM) << 8; 202 c |= (int)vx_inb(chip, RXM) << 8;
203 c |= vx_inb(chip, RXL); 203 c |= vx_inb(chip, RXL);
204 204
205 snd_printdd(KERN_DEBUG "xilinx: dsp size received 0x%x, orig 0x%x\n", c, fw->size); 205 snd_printdd(KERN_DEBUG "xilinx: dsp size received 0x%x, orig 0x%Zx\n", c, fw->size);
206 206
207 vx_outb(chip, ICR, ICR_HF0); 207 vx_outb(chip, ICR, ICR_HF0);
208 208
diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c
index 7e0cda2b6ef9..cafe6640cc1a 100644
--- a/sound/pcmcia/vx/vxpocket.c
+++ b/sound/pcmcia/vx/vxpocket.c
@@ -261,7 +261,7 @@ static int vxpocket_config(struct pcmcia_device *link)
261 261
262 link->dev_node = &vxp->node; 262 link->dev_node = &vxp->node;
263 kfree(parse); 263 kfree(parse);
264 return 9; 264 return 0;
265 265
266cs_failed: 266cs_failed:
267 cs_error(link, last_fn, last_ret); 267 cs_error(link, last_fn, last_ret);
diff --git a/sound/ppc/Makefile b/sound/ppc/Makefile
index d6ba9959097b..4d95c652c8ca 100644
--- a/sound/ppc/Makefile
+++ b/sound/ppc/Makefile
@@ -3,7 +3,7 @@
3# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> 3# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
4# 4#
5 5
6snd-powermac-objs := powermac.o pmac.o awacs.o burgundy.o daca.o tumbler.o toonie.o keywest.o beep.o 6snd-powermac-objs := powermac.o pmac.o awacs.o burgundy.o daca.o tumbler.o keywest.o beep.o
7 7
8# Toplevel Module Dependency 8# Toplevel Module Dependency
9obj-$(CONFIG_SND_POWERMAC) += snd-powermac.o 9obj-$(CONFIG_SND_POWERMAC) += snd-powermac.o
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c
index f0794ef9d1ac..b678814975c9 100644
--- a/sound/ppc/pmac.c
+++ b/sound/ppc/pmac.c
@@ -867,8 +867,6 @@ static int __init snd_pmac_detect(struct snd_pmac *chip)
867 unsigned int *prop, l; 867 unsigned int *prop, l;
868 struct macio_chip* macio; 868 struct macio_chip* macio;
869 869
870 u32 layout_id = 0;
871
872 if (!machine_is(powermac)) 870 if (!machine_is(powermac))
873 return -ENODEV; 871 return -ENODEV;
874 872
@@ -929,8 +927,14 @@ static int __init snd_pmac_detect(struct snd_pmac *chip)
929 if (prop && *prop < 16) 927 if (prop && *prop < 16)
930 chip->subframe = *prop; 928 chip->subframe = *prop;
931 prop = (unsigned int *) get_property(sound, "layout-id", NULL); 929 prop = (unsigned int *) get_property(sound, "layout-id", NULL);
932 if (prop) 930 if (prop) {
933 layout_id = *prop; 931 /* partly deprecate snd-powermac, for those machines
932 * that have a layout-id property for now */
933 printk(KERN_INFO "snd-powermac no longer handles any "
934 "machines with a layout-id property "
935 "in the device-tree, use snd-aoa.\n");
936 return -ENODEV;
937 }
934 /* This should be verified on older screamers */ 938 /* This should be verified on older screamers */
935 if (device_is_compatible(sound, "screamer")) { 939 if (device_is_compatible(sound, "screamer")) {
936 chip->model = PMAC_SCREAMER; 940 chip->model = PMAC_SCREAMER;
@@ -963,38 +967,6 @@ static int __init snd_pmac_detect(struct snd_pmac *chip)
963 chip->freq_table = tumbler_freqs; 967 chip->freq_table = tumbler_freqs;
964 chip->control_mask = MASK_IEPC | 0x11; /* disable IEE */ 968 chip->control_mask = MASK_IEPC | 0x11; /* disable IEE */
965 } 969 }
966 if (device_is_compatible(sound, "AOAKeylargo") ||
967 device_is_compatible(sound, "AOAbase") ||
968 device_is_compatible(sound, "AOAK2")) {
969 /* For now, only support very basic TAS3004 based machines with
970 * single frequency until proper i2s control is implemented
971 */
972 switch(layout_id) {
973 case 0x24:
974 case 0x29:
975 case 0x33:
976 case 0x46:
977 case 0x48:
978 case 0x50:
979 case 0x5c:
980 chip->num_freqs = ARRAY_SIZE(tumbler_freqs);
981 chip->model = PMAC_SNAPPER;
982 chip->can_byte_swap = 0; /* FIXME: check this */
983 chip->control_mask = MASK_IEPC | 0x11;/* disable IEE */
984 break;
985 case 0x3a:
986 chip->num_freqs = ARRAY_SIZE(tumbler_freqs);
987 chip->model = PMAC_TOONIE;
988 chip->can_byte_swap = 0; /* FIXME: check this */
989 chip->control_mask = MASK_IEPC | 0x11;/* disable IEE */
990 break;
991 default:
992 printk(KERN_ERR "snd: Unknown layout ID 0x%x\n",
993 layout_id);
994 return -ENODEV;
995
996 }
997 }
998 prop = (unsigned int *)get_property(sound, "device-id", NULL); 970 prop = (unsigned int *)get_property(sound, "device-id", NULL);
999 if (prop) 971 if (prop)
1000 chip->device_id = *prop; 972 chip->device_id = *prop;
diff --git a/sound/ppc/pmac.h b/sound/ppc/pmac.h
index 3a9bd4dbb9a6..8394e66ceb00 100644
--- a/sound/ppc/pmac.h
+++ b/sound/ppc/pmac.h
@@ -85,7 +85,7 @@ struct pmac_stream {
85 85
86enum snd_pmac_model { 86enum snd_pmac_model {
87 PMAC_AWACS, PMAC_SCREAMER, PMAC_BURGUNDY, PMAC_DACA, PMAC_TUMBLER, 87 PMAC_AWACS, PMAC_SCREAMER, PMAC_BURGUNDY, PMAC_DACA, PMAC_TUMBLER,
88 PMAC_SNAPPER, PMAC_TOONIE 88 PMAC_SNAPPER
89}; 89};
90 90
91struct snd_pmac { 91struct snd_pmac {
@@ -188,7 +188,6 @@ int snd_pmac_burgundy_init(struct snd_pmac *chip);
188int snd_pmac_daca_init(struct snd_pmac *chip); 188int snd_pmac_daca_init(struct snd_pmac *chip);
189int snd_pmac_tumbler_init(struct snd_pmac *chip); 189int snd_pmac_tumbler_init(struct snd_pmac *chip);
190int snd_pmac_tumbler_post_init(void); 190int snd_pmac_tumbler_post_init(void);
191int snd_pmac_toonie_init(struct snd_pmac *chip);
192 191
193/* i2c functions */ 192/* i2c functions */
194struct pmac_keywest { 193struct pmac_keywest {
diff --git a/sound/ppc/powermac.c b/sound/ppc/powermac.c
index f4902a219e50..fa9a44ab487e 100644
--- a/sound/ppc/powermac.c
+++ b/sound/ppc/powermac.c
@@ -94,13 +94,6 @@ static int __init snd_pmac_probe(struct platform_device *devptr)
94 if ( snd_pmac_tumbler_init(chip) < 0 || snd_pmac_tumbler_post_init() < 0) 94 if ( snd_pmac_tumbler_init(chip) < 0 || snd_pmac_tumbler_post_init() < 0)
95 goto __error; 95 goto __error;
96 break; 96 break;
97 case PMAC_TOONIE:
98 strcpy(card->driver, "PMac Toonie");
99 strcpy(card->shortname, "PowerMac Toonie");
100 strcpy(card->longname, card->shortname);
101 if ((err = snd_pmac_toonie_init(chip)) < 0)
102 goto __error;
103 break;
104 case PMAC_AWACS: 97 case PMAC_AWACS:
105 case PMAC_SCREAMER: 98 case PMAC_SCREAMER:
106 name_ext = chip->model == PMAC_SCREAMER ? "Screamer" : "AWACS"; 99 name_ext = chip->model == PMAC_SCREAMER ? "Screamer" : "AWACS";
@@ -188,11 +181,15 @@ static int __init alsa_card_pmac_init(void)
188 if ((err = platform_driver_register(&snd_pmac_driver)) < 0) 181 if ((err = platform_driver_register(&snd_pmac_driver)) < 0)
189 return err; 182 return err;
190 device = platform_device_register_simple(SND_PMAC_DRIVER, -1, NULL, 0); 183 device = platform_device_register_simple(SND_PMAC_DRIVER, -1, NULL, 0);
191 if (IS_ERR(device)) { 184 if (!IS_ERR(device)) {
192 platform_driver_unregister(&snd_pmac_driver); 185 if (platform_get_drvdata(device))
193 return PTR_ERR(device); 186 return 0;
194 } 187 platform_device_unregister(device);
195 return 0; 188 err = -ENODEV;
189 } else
190 err = PTR_ERR(device);
191 platform_driver_unregister(&snd_pmac_driver);
192 return err;
196 193
197} 194}
198 195
diff --git a/sound/ppc/toonie.c b/sound/ppc/toonie.c
index 1ac7c8552f50..e69de29bb2d1 100644
--- a/sound/ppc/toonie.c
+++ b/sound/ppc/toonie.c
@@ -1,378 +0,0 @@
1/*
2 * Mac Mini "toonie" mixer control
3 *
4 * Copyright (c) 2005 by Benjamin Herrenschmidt <benh@kernel.crashing.org>
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
21#include <sound/driver.h>
22#include <linux/init.h>
23#include <linux/delay.h>
24#include <linux/i2c.h>
25#include <linux/kmod.h>
26#include <linux/slab.h>
27#include <linux/interrupt.h>
28#include <sound/core.h>
29#include <asm/io.h>
30#include <asm/irq.h>
31#include <asm/machdep.h>
32#include <asm/pmac_feature.h>
33#include "pmac.h"
34
35#undef DEBUG
36
37#ifdef DEBUG
38#define DBG(fmt...) printk(fmt)
39#else
40#define DBG(fmt...)
41#endif
42
43struct pmac_gpio {
44 unsigned int addr;
45 u8 active_val;
46 u8 inactive_val;
47 u8 active_state;
48};
49
50struct pmac_toonie
51{
52 struct pmac_gpio hp_detect_gpio;
53 struct pmac_gpio hp_mute_gpio;
54 struct pmac_gpio amp_mute_gpio;
55 int hp_detect_irq;
56 int auto_mute_notify;
57 struct work_struct detect_work;
58};
59
60
61/*
62 * gpio access
63 */
64#define do_gpio_write(gp, val) \
65 pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, (gp)->addr, val)
66#define do_gpio_read(gp) \
67 pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, (gp)->addr, 0)
68#define tumbler_gpio_free(gp) /* NOP */
69
70static void write_audio_gpio(struct pmac_gpio *gp, int active)
71{
72 if (! gp->addr)
73 return;
74 active = active ? gp->active_val : gp->inactive_val;
75 do_gpio_write(gp, active);
76 DBG("(I) gpio %x write %d\n", gp->addr, active);
77}
78
79static int check_audio_gpio(struct pmac_gpio *gp)
80{
81 int ret;
82
83 if (! gp->addr)
84 return 0;
85
86 ret = do_gpio_read(gp);
87
88 return (ret & 0xd) == (gp->active_val & 0xd);
89}
90
91static int read_audio_gpio(struct pmac_gpio *gp)
92{
93 int ret;
94 if (! gp->addr)
95 return 0;
96 ret = ((do_gpio_read(gp) & 0x02) !=0);
97 return ret == gp->active_state;
98}
99
100
101enum { TOONIE_MUTE_HP, TOONIE_MUTE_AMP };
102
103static int toonie_get_mute_switch(struct snd_kcontrol *kcontrol,
104 struct snd_ctl_elem_value *ucontrol)
105{
106 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
107 struct pmac_toonie *mix = chip->mixer_data;
108 struct pmac_gpio *gp;
109
110 if (mix == NULL)
111 return -ENODEV;
112 switch(kcontrol->private_value) {
113 case TOONIE_MUTE_HP:
114 gp = &mix->hp_mute_gpio;
115 break;
116 case TOONIE_MUTE_AMP:
117 gp = &mix->amp_mute_gpio;
118 break;
119 default:
120 return -EINVAL;
121 }
122 ucontrol->value.integer.value[0] = !check_audio_gpio(gp);
123 return 0;
124}
125
126static int toonie_put_mute_switch(struct snd_kcontrol *kcontrol,
127 struct snd_ctl_elem_value *ucontrol)
128{
129 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
130 struct pmac_toonie *mix = chip->mixer_data;
131 struct pmac_gpio *gp;
132 int val;
133
134 if (chip->update_automute && chip->auto_mute)
135 return 0; /* don't touch in the auto-mute mode */
136
137 if (mix == NULL)
138 return -ENODEV;
139
140 switch(kcontrol->private_value) {
141 case TOONIE_MUTE_HP:
142 gp = &mix->hp_mute_gpio;
143 break;
144 case TOONIE_MUTE_AMP:
145 gp = &mix->amp_mute_gpio;
146 break;
147 default:
148 return -EINVAL;
149 }
150 val = ! check_audio_gpio(gp);
151 if (val != ucontrol->value.integer.value[0]) {
152 write_audio_gpio(gp, ! ucontrol->value.integer.value[0]);
153 return 1;
154 }
155 return 0;
156}
157
158static struct snd_kcontrol_new toonie_hp_sw __initdata = {
159 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
160 .name = "Headphone Playback Switch",
161 .info = snd_pmac_boolean_mono_info,
162 .get = toonie_get_mute_switch,
163 .put = toonie_put_mute_switch,
164 .private_value = TOONIE_MUTE_HP,
165};
166static struct snd_kcontrol_new toonie_speaker_sw __initdata = {
167 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
168 .name = "PC Speaker Playback Switch",
169 .info = snd_pmac_boolean_mono_info,
170 .get = toonie_get_mute_switch,
171 .put = toonie_put_mute_switch,
172 .private_value = TOONIE_MUTE_AMP,
173};
174
175/*
176 * auto-mute stuffs
177 */
178static int toonie_detect_headphone(struct snd_pmac *chip)
179{
180 struct pmac_toonie *mix = chip->mixer_data;
181 int detect = 0;
182
183 if (mix->hp_detect_gpio.addr)
184 detect |= read_audio_gpio(&mix->hp_detect_gpio);
185 return detect;
186}
187
188static void toonie_check_mute(struct snd_pmac *chip, struct pmac_gpio *gp, int val,
189 int do_notify, struct snd_kcontrol *sw)
190{
191 if (check_audio_gpio(gp) != val) {
192 write_audio_gpio(gp, val);
193 if (do_notify)
194 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
195 &sw->id);
196 }
197}
198
199static void toonie_detect_handler(void *self)
200{
201 struct snd_pmac *chip = (struct snd_pmac *) self;
202 struct pmac_toonie *mix;
203 int headphone;
204
205 if (!chip)
206 return;
207
208 mix = chip->mixer_data;
209 snd_assert(mix, return);
210
211 headphone = toonie_detect_headphone(chip);
212
213 DBG("headphone: %d, lineout: %d\n", headphone, lineout);
214
215 if (headphone) {
216 /* unmute headphone/lineout & mute speaker */
217 toonie_check_mute(chip, &mix->hp_mute_gpio, 0,
218 mix->auto_mute_notify, chip->master_sw_ctl);
219 toonie_check_mute(chip, &mix->amp_mute_gpio, 1,
220 mix->auto_mute_notify, chip->speaker_sw_ctl);
221 } else {
222 /* unmute speaker, mute others */
223 toonie_check_mute(chip, &mix->amp_mute_gpio, 0,
224 mix->auto_mute_notify, chip->speaker_sw_ctl);
225 toonie_check_mute(chip, &mix->hp_mute_gpio, 1,
226 mix->auto_mute_notify, chip->master_sw_ctl);
227 }
228 if (mix->auto_mute_notify) {
229 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
230 &chip->hp_detect_ctl->id);
231 }
232}
233
234static void toonie_update_automute(struct snd_pmac *chip, int do_notify)
235{
236 if (chip->auto_mute) {
237 struct pmac_toonie *mix;
238 mix = chip->mixer_data;
239 snd_assert(mix, return);
240 mix->auto_mute_notify = do_notify;
241 schedule_work(&mix->detect_work);
242 }
243}
244
245/* interrupt - headphone plug changed */
246static irqreturn_t toonie_hp_intr(int irq, void *devid, struct pt_regs *regs)
247{
248 struct snd_pmac *chip = devid;
249
250 if (chip->update_automute && chip->initialized) {
251 chip->update_automute(chip, 1);
252 return IRQ_HANDLED;
253 }
254 return IRQ_NONE;
255}
256
257/* look for audio gpio device */
258static int find_audio_gpio(const char *name, const char *platform,
259 struct pmac_gpio *gp)
260{
261 struct device_node *np;
262 u32 *base, addr;
263
264 if (! (np = find_devices("gpio")))
265 return -ENODEV;
266
267 for (np = np->child; np; np = np->sibling) {
268 char *property = get_property(np, "audio-gpio", NULL);
269 if (property && strcmp(property, name) == 0)
270 break;
271 if (device_is_compatible(np, name))
272 break;
273 }
274 if (np == NULL)
275 return -ENODEV;
276
277 base = (u32 *)get_property(np, "AAPL,address", NULL);
278 if (! base) {
279 base = (u32 *)get_property(np, "reg", NULL);
280 if (!base) {
281 DBG("(E) cannot find address for device %s !\n", name);
282 return -ENODEV;
283 }
284 addr = *base;
285 if (addr < 0x50)
286 addr += 0x50;
287 } else
288 addr = *base;
289
290 gp->addr = addr & 0x0000ffff;
291
292 /* Try to find the active state, default to 0 ! */
293 base = (u32 *)get_property(np, "audio-gpio-active-state", NULL);
294 if (base) {
295 gp->active_state = *base;
296 gp->active_val = (*base) ? 0x5 : 0x4;
297 gp->inactive_val = (*base) ? 0x4 : 0x5;
298 } else {
299 u32 *prop = NULL;
300 gp->active_state = 0;
301 gp->active_val = 0x4;
302 gp->inactive_val = 0x5;
303 /* Here are some crude hacks to extract the GPIO polarity and
304 * open collector informations out of the do-platform script
305 * as we don't yet have an interpreter for these things
306 */
307 if (platform)
308 prop = (u32 *)get_property(np, platform, NULL);
309 if (prop) {
310 if (prop[3] == 0x9 && prop[4] == 0x9) {
311 gp->active_val = 0xd;
312 gp->inactive_val = 0xc;
313 }
314 if (prop[3] == 0x1 && prop[4] == 0x1) {
315 gp->active_val = 0x5;
316 gp->inactive_val = 0x4;
317 }
318 }
319 }
320
321 DBG("(I) GPIO device %s found, offset: %x, active state: %d !\n",
322 name, gp->addr, gp->active_state);
323
324 return (np->n_intrs > 0) ? np->intrs[0].line : 0;
325}
326
327static void toonie_cleanup(struct snd_pmac *chip)
328{
329 struct pmac_toonie *mix = chip->mixer_data;
330 if (! mix)
331 return;
332 if (mix->hp_detect_irq >= 0)
333 free_irq(mix->hp_detect_irq, chip);
334 kfree(mix);
335 chip->mixer_data = NULL;
336}
337
338int __init snd_pmac_toonie_init(struct snd_pmac *chip)
339{
340 struct pmac_toonie *mix;
341
342 mix = kmalloc(sizeof(*mix), GFP_KERNEL);
343 if (! mix)
344 return -ENOMEM;
345
346 chip->mixer_data = mix;
347 chip->mixer_free = toonie_cleanup;
348
349 find_audio_gpio("headphone-mute", NULL, &mix->hp_mute_gpio);
350 find_audio_gpio("amp-mute", NULL, &mix->amp_mute_gpio);
351 mix->hp_detect_irq = find_audio_gpio("headphone-detect",
352 NULL, &mix->hp_detect_gpio);
353
354 strcpy(chip->card->mixername, "PowerMac Toonie");
355
356 chip->master_sw_ctl = snd_ctl_new1(&toonie_hp_sw, chip);
357 snd_ctl_add(chip->card, chip->master_sw_ctl);
358
359 chip->speaker_sw_ctl = snd_ctl_new1(&toonie_speaker_sw, chip);
360 snd_ctl_add(chip->card, chip->speaker_sw_ctl);
361
362 INIT_WORK(&mix->detect_work, toonie_detect_handler, (void *)chip);
363
364 if (mix->hp_detect_irq >= 0) {
365 snd_pmac_add_automute(chip);
366
367 chip->detect_headphone = toonie_detect_headphone;
368 chip->update_automute = toonie_update_automute;
369 toonie_update_automute(chip, 0);
370
371 if (request_irq(mix->hp_detect_irq, toonie_hp_intr, 0,
372 "Sound Headphone Detection", chip) < 0)
373 mix->hp_detect_irq = -1;
374 }
375
376 return 0;
377}
378
diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c
index 55493340f467..dfe9bac7fa32 100644
--- a/sound/sparc/amd7930.c
+++ b/sound/sparc/amd7930.c
@@ -977,9 +977,9 @@ static int __init snd_amd7930_create(struct snd_card *card,
977 977
978 if (request_irq(irq_prop->pri, snd_amd7930_interrupt, 978 if (request_irq(irq_prop->pri, snd_amd7930_interrupt,
979 SA_INTERRUPT | SA_SHIRQ, "amd7930", amd)) { 979 SA_INTERRUPT | SA_SHIRQ, "amd7930", amd)) {
980 snd_printk("amd7930-%d: Unable to grab IRQ %s\n", 980 snd_printk("amd7930-%d: Unable to grab IRQ %d\n",
981 dev, 981 dev,
982 __irq_itoa(irq_prop->pri)); 982 irq_prop->pri);
983 snd_amd7930_free(amd); 983 snd_amd7930_free(amd);
984 return -EBUSY; 984 return -EBUSY;
985 } 985 }
@@ -1063,11 +1063,11 @@ static int __init amd7930_attach(int prom_node, struct sbus_dev *sdev)
1063 1063
1064 strcpy(card->driver, "AMD7930"); 1064 strcpy(card->driver, "AMD7930");
1065 strcpy(card->shortname, "Sun AMD7930"); 1065 strcpy(card->shortname, "Sun AMD7930");
1066 sprintf(card->longname, "%s at 0x%02lx:0x%08lx, irq %s", 1066 sprintf(card->longname, "%s at 0x%02lx:0x%08lx, irq %d",
1067 card->shortname, 1067 card->shortname,
1068 rp->flags & 0xffL, 1068 rp->flags & 0xffL,
1069 rp->start, 1069 rp->start,
1070 __irq_itoa(irq_prop.pri)); 1070 irq_prop.pri);
1071 1071
1072 if ((err = snd_amd7930_create(card, sdev, rp, reg_prop.reg_size, 1072 if ((err = snd_amd7930_create(card, sdev, rp, reg_prop.reg_size,
1073 &irq_prop, dev, &amd)) < 0) 1073 &irq_prop, dev, &amd)) < 0)
diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c
index 8804f26ddb3a..b3efc9aa2916 100644
--- a/sound/sparc/cs4231.c
+++ b/sound/sparc/cs4231.c
@@ -2003,9 +2003,8 @@ static int __init snd_cs4231_sbus_create(struct snd_card *card,
2003 2003
2004 if (request_irq(sdev->irqs[0], snd_cs4231_sbus_interrupt, 2004 if (request_irq(sdev->irqs[0], snd_cs4231_sbus_interrupt,
2005 SA_SHIRQ, "cs4231", chip)) { 2005 SA_SHIRQ, "cs4231", chip)) {
2006 snd_printdd("cs4231-%d: Unable to grab SBUS IRQ %s\n", 2006 snd_printdd("cs4231-%d: Unable to grab SBUS IRQ %d\n",
2007 dev, 2007 dev, sdev->irqs[0]);
2008 __irq_itoa(sdev->irqs[0]));
2009 snd_cs4231_sbus_free(chip); 2008 snd_cs4231_sbus_free(chip);
2010 return -EBUSY; 2009 return -EBUSY;
2011 } 2010 }
@@ -2038,11 +2037,11 @@ static int __init cs4231_sbus_attach(struct sbus_dev *sdev)
2038 if (err) 2037 if (err)
2039 return err; 2038 return err;
2040 2039
2041 sprintf(card->longname, "%s at 0x%02lx:0x%08lx, irq %s", 2040 sprintf(card->longname, "%s at 0x%02lx:0x%08lx, irq %d",
2042 card->shortname, 2041 card->shortname,
2043 rp->flags & 0xffL, 2042 rp->flags & 0xffL,
2044 rp->start, 2043 rp->start,
2045 __irq_itoa(sdev->irqs[0])); 2044 sdev->irqs[0]);
2046 2045
2047 if ((err = snd_cs4231_sbus_create(card, sdev, dev, &cp)) < 0) { 2046 if ((err = snd_cs4231_sbus_create(card, sdev, dev, &cp)) < 0) {
2048 snd_card_free(card); 2047 snd_card_free(card);
@@ -2244,10 +2243,10 @@ static int __init cs4231_ebus_attach(struct linux_ebus_device *edev)
2244 if (err) 2243 if (err)
2245 return err; 2244 return err;
2246 2245
2247 sprintf(card->longname, "%s at 0x%lx, irq %s", 2246 sprintf(card->longname, "%s at 0x%lx, irq %d",
2248 card->shortname, 2247 card->shortname,
2249 edev->resource[0].start, 2248 edev->resource[0].start,
2250 __irq_itoa(edev->irqs[0])); 2249 edev->irqs[0]);
2251 2250
2252 if ((err = snd_cs4231_ebus_create(card, edev, dev, &chip)) < 0) { 2251 if ((err = snd_cs4231_ebus_create(card, edev, dev, &chip)) < 0) {
2253 snd_card_free(card); 2252 snd_card_free(card);
diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c
index 2164b7d290c7..5eecdd09a79d 100644
--- a/sound/sparc/dbri.c
+++ b/sound/sparc/dbri.c
@@ -92,7 +92,7 @@ MODULE_PARM_DESC(enable, "Enable Sun DBRI soundcard.");
92#define D_USR (1<<4) 92#define D_USR (1<<4)
93#define D_DESC (1<<5) 93#define D_DESC (1<<5)
94 94
95static int dbri_debug = 0; 95static int dbri_debug;
96module_param(dbri_debug, int, 0644); 96module_param(dbri_debug, int, 0644);
97MODULE_PARM_DESC(dbri_debug, "Debug value for Sun DBRI soundcard."); 97MODULE_PARM_DESC(dbri_debug, "Debug value for Sun DBRI soundcard.");
98 98
@@ -593,7 +593,7 @@ struct snd_dbri {
593/* Return a pointer to dbri_streaminfo */ 593/* Return a pointer to dbri_streaminfo */
594#define DBRI_STREAM(dbri, substream) &dbri->stream_info[DBRI_STREAMNO(substream)] 594#define DBRI_STREAM(dbri, substream) &dbri->stream_info[DBRI_STREAMNO(substream)]
595 595
596static struct snd_dbri *dbri_list = NULL; /* All DBRI devices */ 596static struct snd_dbri *dbri_list; /* All DBRI devices */
597 597
598/* 598/*
599 * Short data pipes transmit LSB first. The CS4215 receives MSB first. Grrr. 599 * Short data pipes transmit LSB first. The CS4215 receives MSB first. Grrr.
@@ -2521,11 +2521,11 @@ void snd_dbri_proc(struct snd_dbri * dbri)
2521 struct snd_info_entry *entry; 2521 struct snd_info_entry *entry;
2522 2522
2523 if (! snd_card_proc_new(dbri->card, "regs", &entry)) 2523 if (! snd_card_proc_new(dbri->card, "regs", &entry))
2524 snd_info_set_text_ops(entry, dbri, 1024, dbri_regs_read); 2524 snd_info_set_text_ops(entry, dbri, dbri_regs_read);
2525 2525
2526#ifdef DBRI_DEBUG 2526#ifdef DBRI_DEBUG
2527 if (! snd_card_proc_new(dbri->card, "debug", &entry)) { 2527 if (! snd_card_proc_new(dbri->card, "debug", &entry)) {
2528 snd_info_set_text_ops(entry, dbri, 4096, dbri_debug_read); 2528 snd_info_set_text_ops(entry, dbri, dbri_debug_read);
2529 entry->mode = S_IFREG | S_IRUGO; /* Readable only. */ 2529 entry->mode = S_IFREG | S_IRUGO; /* Readable only. */
2530 } 2530 }
2531#endif 2531#endif
@@ -2645,9 +2645,9 @@ static int __init dbri_attach(int prom_node, struct sbus_dev *sdev)
2645 strcpy(card->driver, "DBRI"); 2645 strcpy(card->driver, "DBRI");
2646 strcpy(card->shortname, "Sun DBRI"); 2646 strcpy(card->shortname, "Sun DBRI");
2647 rp = &sdev->resource[0]; 2647 rp = &sdev->resource[0];
2648 sprintf(card->longname, "%s at 0x%02lx:0x%08lx, irq %s", 2648 sprintf(card->longname, "%s at 0x%02lx:0x%08lx, irq %d",
2649 card->shortname, 2649 card->shortname,
2650 rp->flags & 0xffL, rp->start, __irq_itoa(irq.pri)); 2650 rp->flags & 0xffL, rp->start, irq.pri);
2651 2651
2652 if ((err = snd_dbri_create(card, sdev, &irq, dev)) < 0) { 2652 if ((err = snd_dbri_create(card, sdev, &irq, dev)) < 0) {
2653 snd_card_free(card); 2653 snd_card_free(card);
diff --git a/sound/synth/emux/emux.c b/sound/synth/emux/emux.c
index fc733bbf4487..573e3701c14f 100644
--- a/sound/synth/emux/emux.c
+++ b/sound/synth/emux/emux.c
@@ -63,6 +63,7 @@ int snd_emux_new(struct snd_emux **remu)
63 return 0; 63 return 0;
64} 64}
65 65
66EXPORT_SYMBOL(snd_emux_new);
66 67
67/* 68/*
68 */ 69 */
@@ -136,6 +137,7 @@ int snd_emux_register(struct snd_emux *emu, struct snd_card *card, int index, ch
136 return 0; 137 return 0;
137} 138}
138 139
140EXPORT_SYMBOL(snd_emux_register);
139 141
140/* 142/*
141 */ 143 */
@@ -171,18 +173,8 @@ int snd_emux_free(struct snd_emux *emu)
171 return 0; 173 return 0;
172} 174}
173 175
174
175EXPORT_SYMBOL(snd_emux_new);
176EXPORT_SYMBOL(snd_emux_register);
177EXPORT_SYMBOL(snd_emux_free); 176EXPORT_SYMBOL(snd_emux_free);
178 177
179EXPORT_SYMBOL(snd_emux_terminate_all);
180EXPORT_SYMBOL(snd_emux_lock_voice);
181EXPORT_SYMBOL(snd_emux_unlock_voice);
182
183/* soundfont.c */
184EXPORT_SYMBOL(snd_sf_linear_to_log);
185
186 178
187/* 179/*
188 * INIT part 180 * INIT part
diff --git a/sound/synth/emux/emux_proc.c b/sound/synth/emux/emux_proc.c
index 1ba68ce30279..58b9601f3ad0 100644
--- a/sound/synth/emux/emux_proc.c
+++ b/sound/synth/emux/emux_proc.c
@@ -119,7 +119,6 @@ void snd_emux_proc_init(struct snd_emux *emu, struct snd_card *card, int device)
119 119
120 entry->content = SNDRV_INFO_CONTENT_TEXT; 120 entry->content = SNDRV_INFO_CONTENT_TEXT;
121 entry->private_data = emu; 121 entry->private_data = emu;
122 entry->c.text.read_size = 1024;
123 entry->c.text.read = snd_emux_proc_info_read; 122 entry->c.text.read = snd_emux_proc_info_read;
124 if (snd_info_register(entry) < 0) 123 if (snd_info_register(entry) < 0)
125 snd_info_free_entry(entry); 124 snd_info_free_entry(entry);
diff --git a/sound/synth/emux/emux_seq.c b/sound/synth/emux/emux_seq.c
index 8f00f07701c4..d176cc01742d 100644
--- a/sound/synth/emux/emux_seq.c
+++ b/sound/synth/emux/emux_seq.c
@@ -55,7 +55,8 @@ static struct snd_midi_op emux_ops = {
55 SNDRV_SEQ_PORT_TYPE_MIDI_GM |\ 55 SNDRV_SEQ_PORT_TYPE_MIDI_GM |\
56 SNDRV_SEQ_PORT_TYPE_MIDI_GS |\ 56 SNDRV_SEQ_PORT_TYPE_MIDI_GS |\
57 SNDRV_SEQ_PORT_TYPE_MIDI_XG |\ 57 SNDRV_SEQ_PORT_TYPE_MIDI_XG |\
58 SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE) 58 SNDRV_SEQ_PORT_TYPE_HARDWARE |\
59 SNDRV_SEQ_PORT_TYPE_SYNTHESIZER)
59 60
60/* 61/*
61 * Initialise the EMUX Synth by creating a client and registering 62 * Initialise the EMUX Synth by creating a client and registering
diff --git a/sound/synth/emux/emux_synth.c b/sound/synth/emux/emux_synth.c
index 24705d15ebd8..3733118d39bb 100644
--- a/sound/synth/emux/emux_synth.c
+++ b/sound/synth/emux/emux_synth.c
@@ -434,6 +434,7 @@ snd_emux_terminate_all(struct snd_emux *emu)
434 spin_unlock_irqrestore(&emu->voice_lock, flags); 434 spin_unlock_irqrestore(&emu->voice_lock, flags);
435} 435}
436 436
437EXPORT_SYMBOL(snd_emux_terminate_all);
437 438
438/* 439/*
439 * Terminate all voices associated with the given port 440 * Terminate all voices associated with the given port
@@ -951,6 +952,8 @@ void snd_emux_lock_voice(struct snd_emux *emu, int voice)
951 spin_unlock_irqrestore(&emu->voice_lock, flags); 952 spin_unlock_irqrestore(&emu->voice_lock, flags);
952} 953}
953 954
955EXPORT_SYMBOL(snd_emux_lock_voice);
956
954/* 957/*
955 */ 958 */
956void snd_emux_unlock_voice(struct snd_emux *emu, int voice) 959void snd_emux_unlock_voice(struct snd_emux *emu, int voice)
@@ -965,3 +968,5 @@ void snd_emux_unlock_voice(struct snd_emux *emu, int voice)
965 voice, emu->voices[voice].state); 968 voice, emu->voices[voice].state);
966 spin_unlock_irqrestore(&emu->voice_lock, flags); 969 spin_unlock_irqrestore(&emu->voice_lock, flags);
967} 970}
971
972EXPORT_SYMBOL(snd_emux_unlock_voice);
diff --git a/sound/synth/emux/soundfont.c b/sound/synth/emux/soundfont.c
index 32c27162dfb6..455e535933ec 100644
--- a/sound/synth/emux/soundfont.c
+++ b/sound/synth/emux/soundfont.c
@@ -195,7 +195,7 @@ snd_soundfont_load(struct snd_sf_list *sflist, const void __user *data,
195 break; 195 break;
196 case SNDRV_SFNT_REMOVE_INFO: 196 case SNDRV_SFNT_REMOVE_INFO:
197 /* patch must be opened */ 197 /* patch must be opened */
198 if (sflist->currsf) { 198 if (!sflist->currsf) {
199 snd_printk("soundfont: remove_info: patch not opened\n"); 199 snd_printk("soundfont: remove_info: patch not opened\n");
200 rc = -EINVAL; 200 rc = -EINVAL;
201 } else { 201 } else {
@@ -810,6 +810,9 @@ snd_sf_linear_to_log(unsigned int amount, int offset, int ratio)
810 return v; 810 return v;
811} 811}
812 812
813EXPORT_SYMBOL(snd_sf_linear_to_log);
814
815
813#define OFFSET_MSEC 653117 /* base = 1000 */ 816#define OFFSET_MSEC 653117 /* base = 1000 */
814#define OFFSET_ABSCENT 851781 /* base = 8176 */ 817#define OFFSET_ABSCENT 851781 /* base = 8176 */
815#define OFFSET_SAMPLERATE 1011119 /* base = 44100 */ 818#define OFFSET_SAMPLERATE 1011119 /* base = 44100 */
@@ -1485,4 +1488,3 @@ snd_soundfont_remove_unlocked(struct snd_sf_list *sflist)
1485 unlock_preset(sflist); 1488 unlock_preset(sflist);
1486 return 0; 1489 return 0;
1487} 1490}
1488
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 4e614ac39f21..627de9525a32 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -2138,7 +2138,7 @@ static void proc_pcm_format_add(struct snd_usb_stream *stream)
2138 2138
2139 sprintf(name, "stream%d", stream->pcm_index); 2139 sprintf(name, "stream%d", stream->pcm_index);
2140 if (! snd_card_proc_new(card, name, &entry)) 2140 if (! snd_card_proc_new(card, name, &entry))
2141 snd_info_set_text_ops(entry, stream, 1024, proc_pcm_format_read); 2141 snd_info_set_text_ops(entry, stream, proc_pcm_format_read);
2142} 2142}
2143 2143
2144#else 2144#else
@@ -2627,9 +2627,10 @@ static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
2627 if (!csep && altsd->bNumEndpoints >= 2) 2627 if (!csep && altsd->bNumEndpoints >= 2)
2628 csep = snd_usb_find_desc(alts->endpoint[1].extra, alts->endpoint[1].extralen, NULL, USB_DT_CS_ENDPOINT); 2628 csep = snd_usb_find_desc(alts->endpoint[1].extra, alts->endpoint[1].extralen, NULL, USB_DT_CS_ENDPOINT);
2629 if (!csep || csep[0] < 7 || csep[2] != EP_GENERAL) { 2629 if (!csep || csep[0] < 7 || csep[2] != EP_GENERAL) {
2630 snd_printk(KERN_ERR "%d:%u:%d : no or invalid class specific endpoint descriptor\n", 2630 snd_printk(KERN_WARNING "%d:%u:%d : no or invalid"
2631 " class specific endpoint descriptor\n",
2631 dev->devnum, iface_no, altno); 2632 dev->devnum, iface_no, altno);
2632 continue; 2633 csep = NULL;
2633 } 2634 }
2634 2635
2635 fp = kmalloc(sizeof(*fp), GFP_KERNEL); 2636 fp = kmalloc(sizeof(*fp), GFP_KERNEL);
@@ -2648,7 +2649,7 @@ static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
2648 if (snd_usb_get_speed(dev) == USB_SPEED_HIGH) 2649 if (snd_usb_get_speed(dev) == USB_SPEED_HIGH)
2649 fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1) 2650 fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1)
2650 * (fp->maxpacksize & 0x7ff); 2651 * (fp->maxpacksize & 0x7ff);
2651 fp->attributes = csep[3]; 2652 fp->attributes = csep ? csep[3] : 0;
2652 2653
2653 /* some quirks for attributes here */ 2654 /* some quirks for attributes here */
2654 2655
@@ -2980,7 +2981,7 @@ static int create_ua1000_quirk(struct snd_usb_audio *chip,
2980 return -ENXIO; 2981 return -ENXIO;
2981 alts = &iface->altsetting[1]; 2982 alts = &iface->altsetting[1];
2982 altsd = get_iface_desc(alts); 2983 altsd = get_iface_desc(alts);
2983 if (alts->extralen != 11 || alts->extra[1] != CS_AUDIO_INTERFACE || 2984 if (alts->extralen != 11 || alts->extra[1] != USB_DT_CS_INTERFACE ||
2984 altsd->bNumEndpoints != 1) 2985 altsd->bNumEndpoints != 1)
2985 return -ENXIO; 2986 return -ENXIO;
2986 2987
@@ -3197,9 +3198,9 @@ static void snd_usb_audio_create_proc(struct snd_usb_audio *chip)
3197{ 3198{
3198 struct snd_info_entry *entry; 3199 struct snd_info_entry *entry;
3199 if (! snd_card_proc_new(chip->card, "usbbus", &entry)) 3200 if (! snd_card_proc_new(chip->card, "usbbus", &entry))
3200 snd_info_set_text_ops(entry, chip, 1024, proc_audio_usbbus_read); 3201 snd_info_set_text_ops(entry, chip, proc_audio_usbbus_read);
3201 if (! snd_card_proc_new(chip->card, "usbid", &entry)) 3202 if (! snd_card_proc_new(chip->card, "usbid", &entry))
3202 snd_info_set_text_ops(entry, chip, 1024, proc_audio_usbid_read); 3203 snd_info_set_text_ops(entry, chip, proc_audio_usbid_read);
3203} 3204}
3204 3205
3205/* 3206/*
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 88733524d0fb..0f4b2b8541d6 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -30,13 +30,6 @@
30#define USB_SUBCLASS_MIDI_STREAMING 0x03 30#define USB_SUBCLASS_MIDI_STREAMING 0x03
31#define USB_SUBCLASS_VENDOR_SPEC 0xff 31#define USB_SUBCLASS_VENDOR_SPEC 0xff
32 32
33#define CS_AUDIO_UNDEFINED 0x20
34#define CS_AUDIO_DEVICE 0x21
35#define CS_AUDIO_CONFIGURATION 0x22
36#define CS_AUDIO_STRING 0x23
37#define CS_AUDIO_INTERFACE 0x24
38#define CS_AUDIO_ENDPOINT 0x25
39
40#define HEADER 0x01 33#define HEADER 0x01
41#define INPUT_TERMINAL 0x02 34#define INPUT_TERMINAL 0x02
42#define OUTPUT_TERMINAL 0x03 35#define OUTPUT_TERMINAL 0x03
diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c
index 2b9d940c8064..5105b6b05748 100644
--- a/sound/usb/usbmidi.c
+++ b/sound/usb/usbmidi.c
@@ -48,6 +48,7 @@
48#include <linux/usb.h> 48#include <linux/usb.h>
49#include <sound/core.h> 49#include <sound/core.h>
50#include <sound/rawmidi.h> 50#include <sound/rawmidi.h>
51#include <sound/asequencer.h>
51#include "usbaudio.h" 52#include "usbaudio.h"
52 53
53 54
@@ -1010,97 +1011,157 @@ static struct snd_rawmidi_substream *snd_usbmidi_find_substream(struct snd_usb_m
1010 * "(product) MIDI (n)" schema because they aren't external MIDI ports, 1011 * "(product) MIDI (n)" schema because they aren't external MIDI ports,
1011 * such as internal control or synthesizer ports. 1012 * such as internal control or synthesizer ports.
1012 */ 1013 */
1013static struct { 1014static struct port_info {
1014 u32 id; 1015 u32 id;
1015 int port; 1016 short int port;
1016 const char *name_format; 1017 short int voices;
1017} snd_usbmidi_port_names[] = { 1018 const char *name;
1019 unsigned int seq_flags;
1020} snd_usbmidi_port_info[] = {
1021#define PORT_INFO(vendor, product, num, name_, voices_, flags) \
1022 { .id = USB_ID(vendor, product), \
1023 .port = num, .voices = voices_, \
1024 .name = name_, .seq_flags = flags }
1025#define EXTERNAL_PORT(vendor, product, num, name) \
1026 PORT_INFO(vendor, product, num, name, 0, \
1027 SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | \
1028 SNDRV_SEQ_PORT_TYPE_HARDWARE | \
1029 SNDRV_SEQ_PORT_TYPE_PORT)
1030#define CONTROL_PORT(vendor, product, num, name) \
1031 PORT_INFO(vendor, product, num, name, 0, \
1032 SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | \
1033 SNDRV_SEQ_PORT_TYPE_HARDWARE)
1034#define ROLAND_SYNTH_PORT(vendor, product, num, name, voices) \
1035 PORT_INFO(vendor, product, num, name, voices, \
1036 SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | \
1037 SNDRV_SEQ_PORT_TYPE_MIDI_GM | \
1038 SNDRV_SEQ_PORT_TYPE_MIDI_GM2 | \
1039 SNDRV_SEQ_PORT_TYPE_MIDI_GS | \
1040 SNDRV_SEQ_PORT_TYPE_MIDI_XG | \
1041 SNDRV_SEQ_PORT_TYPE_HARDWARE | \
1042 SNDRV_SEQ_PORT_TYPE_SYNTHESIZER)
1043#define SOUNDCANVAS_PORT(vendor, product, num, name, voices) \
1044 PORT_INFO(vendor, product, num, name, voices, \
1045 SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | \
1046 SNDRV_SEQ_PORT_TYPE_MIDI_GM | \
1047 SNDRV_SEQ_PORT_TYPE_MIDI_GM2 | \
1048 SNDRV_SEQ_PORT_TYPE_MIDI_GS | \
1049 SNDRV_SEQ_PORT_TYPE_MIDI_XG | \
1050 SNDRV_SEQ_PORT_TYPE_MIDI_MT32 | \
1051 SNDRV_SEQ_PORT_TYPE_HARDWARE | \
1052 SNDRV_SEQ_PORT_TYPE_SYNTHESIZER)
1018 /* Roland UA-100 */ 1053 /* Roland UA-100 */
1019 { USB_ID(0x0582, 0x0000), 2, "%s Control" }, 1054 CONTROL_PORT(0x0582, 0x0000, 2, "%s Control"),
1020 /* Roland SC-8850 */ 1055 /* Roland SC-8850 */
1021 { USB_ID(0x0582, 0x0003), 0, "%s Part A" }, 1056 SOUNDCANVAS_PORT(0x0582, 0x0003, 0, "%s Part A", 128),
1022 { USB_ID(0x0582, 0x0003), 1, "%s Part B" }, 1057 SOUNDCANVAS_PORT(0x0582, 0x0003, 1, "%s Part B", 128),
1023 { USB_ID(0x0582, 0x0003), 2, "%s Part C" }, 1058 SOUNDCANVAS_PORT(0x0582, 0x0003, 2, "%s Part C", 128),
1024 { USB_ID(0x0582, 0x0003), 3, "%s Part D" }, 1059 SOUNDCANVAS_PORT(0x0582, 0x0003, 3, "%s Part D", 128),
1025 { USB_ID(0x0582, 0x0003), 4, "%s MIDI 1" }, 1060 EXTERNAL_PORT(0x0582, 0x0003, 4, "%s MIDI 1"),
1026 { USB_ID(0x0582, 0x0003), 5, "%s MIDI 2" }, 1061 EXTERNAL_PORT(0x0582, 0x0003, 5, "%s MIDI 2"),
1027 /* Roland U-8 */ 1062 /* Roland U-8 */
1028 { USB_ID(0x0582, 0x0004), 0, "%s MIDI" }, 1063 EXTERNAL_PORT(0x0582, 0x0004, 0, "%s MIDI"),
1029 { USB_ID(0x0582, 0x0004), 1, "%s Control" }, 1064 CONTROL_PORT(0x0582, 0x0004, 1, "%s Control"),
1030 /* Roland SC-8820 */ 1065 /* Roland SC-8820 */
1031 { USB_ID(0x0582, 0x0007), 0, "%s Part A" }, 1066 SOUNDCANVAS_PORT(0x0582, 0x0007, 0, "%s Part A", 64),
1032 { USB_ID(0x0582, 0x0007), 1, "%s Part B" }, 1067 SOUNDCANVAS_PORT(0x0582, 0x0007, 1, "%s Part B", 64),
1033 { USB_ID(0x0582, 0x0007), 2, "%s MIDI" }, 1068 EXTERNAL_PORT(0x0582, 0x0007, 2, "%s MIDI"),
1034 /* Roland SK-500 */ 1069 /* Roland SK-500 */
1035 { USB_ID(0x0582, 0x000b), 0, "%s Part A" }, 1070 SOUNDCANVAS_PORT(0x0582, 0x000b, 0, "%s Part A", 64),
1036 { USB_ID(0x0582, 0x000b), 1, "%s Part B" }, 1071 SOUNDCANVAS_PORT(0x0582, 0x000b, 1, "%s Part B", 64),
1037 { USB_ID(0x0582, 0x000b), 2, "%s MIDI" }, 1072 EXTERNAL_PORT(0x0582, 0x000b, 2, "%s MIDI"),
1038 /* Roland SC-D70 */ 1073 /* Roland SC-D70 */
1039 { USB_ID(0x0582, 0x000c), 0, "%s Part A" }, 1074 SOUNDCANVAS_PORT(0x0582, 0x000c, 0, "%s Part A", 64),
1040 { USB_ID(0x0582, 0x000c), 1, "%s Part B" }, 1075 SOUNDCANVAS_PORT(0x0582, 0x000c, 1, "%s Part B", 64),
1041 { USB_ID(0x0582, 0x000c), 2, "%s MIDI" }, 1076 EXTERNAL_PORT(0x0582, 0x000c, 2, "%s MIDI"),
1042 /* Edirol UM-880 */ 1077 /* Edirol UM-880 */
1043 { USB_ID(0x0582, 0x0014), 8, "%s Control" }, 1078 CONTROL_PORT(0x0582, 0x0014, 8, "%s Control"),
1044 /* Edirol SD-90 */ 1079 /* Edirol SD-90 */
1045 { USB_ID(0x0582, 0x0016), 0, "%s Part A" }, 1080 ROLAND_SYNTH_PORT(0x0582, 0x0016, 0, "%s Part A", 128),
1046 { USB_ID(0x0582, 0x0016), 1, "%s Part B" }, 1081 ROLAND_SYNTH_PORT(0x0582, 0x0016, 1, "%s Part B", 128),
1047 { USB_ID(0x0582, 0x0016), 2, "%s MIDI 1" }, 1082 EXTERNAL_PORT(0x0582, 0x0016, 2, "%s MIDI 1"),
1048 { USB_ID(0x0582, 0x0016), 3, "%s MIDI 2" }, 1083 EXTERNAL_PORT(0x0582, 0x0016, 3, "%s MIDI 2"),
1049 /* Edirol UM-550 */ 1084 /* Edirol UM-550 */
1050 { USB_ID(0x0582, 0x0023), 5, "%s Control" }, 1085 CONTROL_PORT(0x0582, 0x0023, 5, "%s Control"),
1051 /* Edirol SD-20 */ 1086 /* Edirol SD-20 */
1052 { USB_ID(0x0582, 0x0027), 0, "%s Part A" }, 1087 ROLAND_SYNTH_PORT(0x0582, 0x0027, 0, "%s Part A", 64),
1053 { USB_ID(0x0582, 0x0027), 1, "%s Part B" }, 1088 ROLAND_SYNTH_PORT(0x0582, 0x0027, 1, "%s Part B", 64),
1054 { USB_ID(0x0582, 0x0027), 2, "%s MIDI" }, 1089 EXTERNAL_PORT(0x0582, 0x0027, 2, "%s MIDI"),
1055 /* Edirol SD-80 */ 1090 /* Edirol SD-80 */
1056 { USB_ID(0x0582, 0x0029), 0, "%s Part A" }, 1091 ROLAND_SYNTH_PORT(0x0582, 0x0029, 0, "%s Part A", 128),
1057 { USB_ID(0x0582, 0x0029), 1, "%s Part B" }, 1092 ROLAND_SYNTH_PORT(0x0582, 0x0029, 1, "%s Part B", 128),
1058 { USB_ID(0x0582, 0x0029), 2, "%s MIDI 1" }, 1093 EXTERNAL_PORT(0x0582, 0x0029, 2, "%s MIDI 1"),
1059 { USB_ID(0x0582, 0x0029), 3, "%s MIDI 2" }, 1094 EXTERNAL_PORT(0x0582, 0x0029, 3, "%s MIDI 2"),
1060 /* Edirol UA-700 */ 1095 /* Edirol UA-700 */
1061 { USB_ID(0x0582, 0x002b), 0, "%s MIDI" }, 1096 EXTERNAL_PORT(0x0582, 0x002b, 0, "%s MIDI"),
1062 { USB_ID(0x0582, 0x002b), 1, "%s Control" }, 1097 CONTROL_PORT(0x0582, 0x002b, 1, "%s Control"),
1063 /* Roland VariOS */ 1098 /* Roland VariOS */
1064 { USB_ID(0x0582, 0x002f), 0, "%s MIDI" }, 1099 EXTERNAL_PORT(0x0582, 0x002f, 0, "%s MIDI"),
1065 { USB_ID(0x0582, 0x002f), 1, "%s External MIDI" }, 1100 EXTERNAL_PORT(0x0582, 0x002f, 1, "%s External MIDI"),
1066 { USB_ID(0x0582, 0x002f), 2, "%s Sync" }, 1101 EXTERNAL_PORT(0x0582, 0x002f, 2, "%s Sync"),
1067 /* Edirol PCR */ 1102 /* Edirol PCR */
1068 { USB_ID(0x0582, 0x0033), 0, "%s MIDI" }, 1103 EXTERNAL_PORT(0x0582, 0x0033, 0, "%s MIDI"),
1069 { USB_ID(0x0582, 0x0033), 1, "%s 1" }, 1104 EXTERNAL_PORT(0x0582, 0x0033, 1, "%s 1"),
1070 { USB_ID(0x0582, 0x0033), 2, "%s 2" }, 1105 EXTERNAL_PORT(0x0582, 0x0033, 2, "%s 2"),
1071 /* BOSS GS-10 */ 1106 /* BOSS GS-10 */
1072 { USB_ID(0x0582, 0x003b), 0, "%s MIDI" }, 1107 EXTERNAL_PORT(0x0582, 0x003b, 0, "%s MIDI"),
1073 { USB_ID(0x0582, 0x003b), 1, "%s Control" }, 1108 CONTROL_PORT(0x0582, 0x003b, 1, "%s Control"),
1074 /* Edirol UA-1000 */ 1109 /* Edirol UA-1000 */
1075 { USB_ID(0x0582, 0x0044), 0, "%s MIDI" }, 1110 EXTERNAL_PORT(0x0582, 0x0044, 0, "%s MIDI"),
1076 { USB_ID(0x0582, 0x0044), 1, "%s Control" }, 1111 CONTROL_PORT(0x0582, 0x0044, 1, "%s Control"),
1077 /* Edirol UR-80 */ 1112 /* Edirol UR-80 */
1078 { USB_ID(0x0582, 0x0048), 0, "%s MIDI" }, 1113 EXTERNAL_PORT(0x0582, 0x0048, 0, "%s MIDI"),
1079 { USB_ID(0x0582, 0x0048), 1, "%s 1" }, 1114 EXTERNAL_PORT(0x0582, 0x0048, 1, "%s 1"),
1080 { USB_ID(0x0582, 0x0048), 2, "%s 2" }, 1115 EXTERNAL_PORT(0x0582, 0x0048, 2, "%s 2"),
1081 /* Edirol PCR-A */ 1116 /* Edirol PCR-A */
1082 { USB_ID(0x0582, 0x004d), 0, "%s MIDI" }, 1117 EXTERNAL_PORT(0x0582, 0x004d, 0, "%s MIDI"),
1083 { USB_ID(0x0582, 0x004d), 1, "%s 1" }, 1118 EXTERNAL_PORT(0x0582, 0x004d, 1, "%s 1"),
1084 { USB_ID(0x0582, 0x004d), 2, "%s 2" }, 1119 EXTERNAL_PORT(0x0582, 0x004d, 2, "%s 2"),
1085 /* Edirol UM-3EX */ 1120 /* Edirol UM-3EX */
1086 { USB_ID(0x0582, 0x009a), 3, "%s Control" }, 1121 CONTROL_PORT(0x0582, 0x009a, 3, "%s Control"),
1087 /* M-Audio MidiSport 8x8 */ 1122 /* M-Audio MidiSport 8x8 */
1088 { USB_ID(0x0763, 0x1031), 8, "%s Control" }, 1123 CONTROL_PORT(0x0763, 0x1031, 8, "%s Control"),
1089 { USB_ID(0x0763, 0x1033), 8, "%s Control" }, 1124 CONTROL_PORT(0x0763, 0x1033, 8, "%s Control"),
1090 /* MOTU Fastlane */ 1125 /* MOTU Fastlane */
1091 { USB_ID(0x07fd, 0x0001), 0, "%s MIDI A" }, 1126 EXTERNAL_PORT(0x07fd, 0x0001, 0, "%s MIDI A"),
1092 { USB_ID(0x07fd, 0x0001), 1, "%s MIDI B" }, 1127 EXTERNAL_PORT(0x07fd, 0x0001, 1, "%s MIDI B"),
1093 /* Emagic Unitor8/AMT8/MT4 */ 1128 /* Emagic Unitor8/AMT8/MT4 */
1094 { USB_ID(0x086a, 0x0001), 8, "%s Broadcast" }, 1129 EXTERNAL_PORT(0x086a, 0x0001, 8, "%s Broadcast"),
1095 { USB_ID(0x086a, 0x0002), 8, "%s Broadcast" }, 1130 EXTERNAL_PORT(0x086a, 0x0002, 8, "%s Broadcast"),
1096 { USB_ID(0x086a, 0x0003), 4, "%s Broadcast" }, 1131 EXTERNAL_PORT(0x086a, 0x0003, 4, "%s Broadcast"),
1097}; 1132};
1098 1133
1134static struct port_info *find_port_info(struct snd_usb_midi* umidi, int number)
1135{
1136 int i;
1137
1138 for (i = 0; i < ARRAY_SIZE(snd_usbmidi_port_info); ++i) {
1139 if (snd_usbmidi_port_info[i].id == umidi->chip->usb_id &&
1140 snd_usbmidi_port_info[i].port == number)
1141 return &snd_usbmidi_port_info[i];
1142 }
1143 return NULL;
1144}
1145
1146static void snd_usbmidi_get_port_info(struct snd_rawmidi *rmidi, int number,
1147 struct snd_seq_port_info *seq_port_info)
1148{
1149 struct snd_usb_midi *umidi = rmidi->private_data;
1150 struct port_info *port_info;
1151
1152 /* TODO: read port flags from descriptors */
1153 port_info = find_port_info(umidi, number);
1154 if (port_info) {
1155 seq_port_info->type = port_info->seq_flags;
1156 seq_port_info->midi_voices = port_info->voices;
1157 }
1158}
1159
1099static void snd_usbmidi_init_substream(struct snd_usb_midi* umidi, 1160static void snd_usbmidi_init_substream(struct snd_usb_midi* umidi,
1100 int stream, int number, 1161 int stream, int number,
1101 struct snd_rawmidi_substream ** rsubstream) 1162 struct snd_rawmidi_substream ** rsubstream)
1102{ 1163{
1103 int i; 1164 struct port_info *port_info;
1104 const char *name_format; 1165 const char *name_format;
1105 1166
1106 struct snd_rawmidi_substream *substream = snd_usbmidi_find_substream(umidi, stream, number); 1167 struct snd_rawmidi_substream *substream = snd_usbmidi_find_substream(umidi, stream, number);
@@ -1110,14 +1171,8 @@ static void snd_usbmidi_init_substream(struct snd_usb_midi* umidi,
1110 } 1171 }
1111 1172
1112 /* TODO: read port name from jack descriptor */ 1173 /* TODO: read port name from jack descriptor */
1113 name_format = "%s MIDI %d"; 1174 port_info = find_port_info(umidi, number);
1114 for (i = 0; i < ARRAY_SIZE(snd_usbmidi_port_names); ++i) { 1175 name_format = port_info ? port_info->name : "%s MIDI %d";
1115 if (snd_usbmidi_port_names[i].id == umidi->chip->usb_id &&
1116 snd_usbmidi_port_names[i].port == number) {
1117 name_format = snd_usbmidi_port_names[i].name_format;
1118 break;
1119 }
1120 }
1121 snprintf(substream->name, sizeof(substream->name), 1176 snprintf(substream->name, sizeof(substream->name),
1122 name_format, umidi->chip->card->shortname, number + 1); 1177 name_format, umidi->chip->card->shortname, number + 1);
1123 1178
@@ -1358,7 +1413,7 @@ static int snd_usbmidi_detect_yamaha(struct snd_usb_midi* umidi,
1358 for (cs_desc = hostif->extra; 1413 for (cs_desc = hostif->extra;
1359 cs_desc < hostif->extra + hostif->extralen && cs_desc[0] >= 2; 1414 cs_desc < hostif->extra + hostif->extralen && cs_desc[0] >= 2;
1360 cs_desc += cs_desc[0]) { 1415 cs_desc += cs_desc[0]) {
1361 if (cs_desc[1] == CS_AUDIO_INTERFACE) { 1416 if (cs_desc[1] == USB_DT_CS_INTERFACE) {
1362 if (cs_desc[2] == MIDI_IN_JACK) 1417 if (cs_desc[2] == MIDI_IN_JACK)
1363 endpoint->in_cables = (endpoint->in_cables << 1) | 1; 1418 endpoint->in_cables = (endpoint->in_cables << 1) | 1;
1364 else if (cs_desc[2] == MIDI_OUT_JACK) 1419 else if (cs_desc[2] == MIDI_OUT_JACK)
@@ -1457,6 +1512,10 @@ static int snd_usbmidi_create_endpoints_midiman(struct snd_usb_midi* umidi,
1457 return 0; 1512 return 0;
1458} 1513}
1459 1514
1515static struct snd_rawmidi_global_ops snd_usbmidi_ops = {
1516 .get_port_info = snd_usbmidi_get_port_info,
1517};
1518
1460static int snd_usbmidi_create_rawmidi(struct snd_usb_midi* umidi, 1519static int snd_usbmidi_create_rawmidi(struct snd_usb_midi* umidi,
1461 int out_ports, int in_ports) 1520 int out_ports, int in_ports)
1462{ 1521{
@@ -1472,6 +1531,7 @@ static int snd_usbmidi_create_rawmidi(struct snd_usb_midi* umidi,
1472 rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT | 1531 rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
1473 SNDRV_RAWMIDI_INFO_INPUT | 1532 SNDRV_RAWMIDI_INFO_INPUT |
1474 SNDRV_RAWMIDI_INFO_DUPLEX; 1533 SNDRV_RAWMIDI_INFO_DUPLEX;
1534 rmidi->ops = &snd_usbmidi_ops;
1475 rmidi->private_data = umidi; 1535 rmidi->private_data = umidi;
1476 rmidi->private_free = snd_usbmidi_rawmidi_free; 1536 rmidi->private_free = snd_usbmidi_rawmidi_free;
1477 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_usbmidi_output_ops); 1537 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_usbmidi_output_ops);
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c
index ce86283ee0fa..491e975a0c87 100644
--- a/sound/usb/usbmixer.c
+++ b/sound/usb/usbmixer.c
@@ -46,6 +46,27 @@
46/* ignore error from controls - for debugging */ 46/* ignore error from controls - for debugging */
47/* #define IGNORE_CTL_ERROR */ 47/* #define IGNORE_CTL_ERROR */
48 48
49/*
50 * Sound Blaster remote control configuration
51 *
52 * format of remote control data:
53 * Extigy: xx 00
54 * Audigy 2 NX: 06 80 xx 00 00 00
55 * Live! 24-bit: 06 80 xx yy 22 83
56 */
57static const struct rc_config {
58 u32 usb_id;
59 u8 offset;
60 u8 length;
61 u8 packet_length;
62 u8 mute_mixer_id;
63 u32 mute_code;
64} rc_configs[] = {
65 { USB_ID(0x041e, 0x3000), 0, 1, 2, 18, 0x0013 }, /* Extigy */
66 { USB_ID(0x041e, 0x3020), 2, 1, 6, 18, 0x0013 }, /* Audigy 2 NX */
67 { USB_ID(0x041e, 0x3040), 2, 2, 6, 2, 0x6e91 }, /* Live! 24-bit */
68};
69
49struct usb_mixer_interface { 70struct usb_mixer_interface {
50 struct snd_usb_audio *chip; 71 struct snd_usb_audio *chip;
51 unsigned int ctrlif; 72 unsigned int ctrlif;
@@ -55,11 +76,7 @@ struct usb_mixer_interface {
55 struct usb_mixer_elem_info **id_elems; /* array[256], indexed by unit id */ 76 struct usb_mixer_elem_info **id_elems; /* array[256], indexed by unit id */
56 77
57 /* Sound Blaster remote control stuff */ 78 /* Sound Blaster remote control stuff */
58 enum { 79 const struct rc_config *rc_cfg;
59 RC_NONE,
60 RC_EXTIGY,
61 RC_AUDIGY2NX,
62 } rc_type;
63 unsigned long rc_hwdep_open; 80 unsigned long rc_hwdep_open;
64 u32 rc_code; 81 u32 rc_code;
65 wait_queue_head_t rc_waitq; 82 wait_queue_head_t rc_waitq;
@@ -1647,7 +1664,7 @@ static void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer,
1647static void snd_usb_mixer_memory_change(struct usb_mixer_interface *mixer, 1664static void snd_usb_mixer_memory_change(struct usb_mixer_interface *mixer,
1648 int unitid) 1665 int unitid)
1649{ 1666{
1650 if (mixer->rc_type == RC_NONE) 1667 if (!mixer->rc_cfg)
1651 return; 1668 return;
1652 /* unit ids specific to Extigy/Audigy 2 NX: */ 1669 /* unit ids specific to Extigy/Audigy 2 NX: */
1653 switch (unitid) { 1670 switch (unitid) {
@@ -1732,20 +1749,19 @@ static void snd_usb_soundblaster_remote_complete(struct urb *urb,
1732 struct pt_regs *regs) 1749 struct pt_regs *regs)
1733{ 1750{
1734 struct usb_mixer_interface *mixer = urb->context; 1751 struct usb_mixer_interface *mixer = urb->context;
1735 /* 1752 const struct rc_config *rc = mixer->rc_cfg;
1736 * format of remote control data:
1737 * Extigy: xx 00
1738 * Audigy 2 NX: 06 80 xx 00 00 00
1739 */
1740 int offset = mixer->rc_type == RC_EXTIGY ? 0 : 2;
1741 u32 code; 1753 u32 code;
1742 1754
1743 if (urb->status < 0 || urb->actual_length <= offset) 1755 if (urb->status < 0 || urb->actual_length < rc->packet_length)
1744 return; 1756 return;
1745 code = mixer->rc_buffer[offset]; 1757
1758 code = mixer->rc_buffer[rc->offset];
1759 if (rc->length == 2)
1760 code |= mixer->rc_buffer[rc->offset + 1] << 8;
1761
1746 /* the Mute button actually changes the mixer control */ 1762 /* the Mute button actually changes the mixer control */
1747 if (code == 13) 1763 if (code == rc->mute_code)
1748 snd_usb_mixer_notify_id(mixer, 18); 1764 snd_usb_mixer_notify_id(mixer, rc->mute_mixer_id);
1749 mixer->rc_code = code; 1765 mixer->rc_code = code;
1750 wmb(); 1766 wmb();
1751 wake_up(&mixer->rc_waitq); 1767 wake_up(&mixer->rc_waitq);
@@ -1801,21 +1817,17 @@ static unsigned int snd_usb_sbrc_hwdep_poll(struct snd_hwdep *hw, struct file *f
1801static int snd_usb_soundblaster_remote_init(struct usb_mixer_interface *mixer) 1817static int snd_usb_soundblaster_remote_init(struct usb_mixer_interface *mixer)
1802{ 1818{
1803 struct snd_hwdep *hwdep; 1819 struct snd_hwdep *hwdep;
1804 int err, len; 1820 int err, len, i;
1805 1821
1806 switch (mixer->chip->usb_id) { 1822 for (i = 0; i < ARRAY_SIZE(rc_configs); ++i)
1807 case USB_ID(0x041e, 0x3000): 1823 if (rc_configs[i].usb_id == mixer->chip->usb_id)
1808 mixer->rc_type = RC_EXTIGY; 1824 break;
1809 len = 2; 1825 if (i >= ARRAY_SIZE(rc_configs))
1810 break;
1811 case USB_ID(0x041e, 0x3020):
1812 mixer->rc_type = RC_AUDIGY2NX;
1813 len = 6;
1814 break;
1815 default:
1816 return 0; 1826 return 0;
1817 } 1827 mixer->rc_cfg = &rc_configs[i];
1818 1828
1829 len = mixer->rc_cfg->packet_length;
1830
1819 init_waitqueue_head(&mixer->rc_waitq); 1831 init_waitqueue_head(&mixer->rc_waitq);
1820 err = snd_hwdep_new(mixer->chip->card, "SB remote control", 0, &hwdep); 1832 err = snd_hwdep_new(mixer->chip->card, "SB remote control", 0, &hwdep);
1821 if (err < 0) 1833 if (err < 0)
@@ -1998,7 +2010,7 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif)
1998 if ((err = snd_audigy2nx_controls_create(mixer)) < 0) 2010 if ((err = snd_audigy2nx_controls_create(mixer)) < 0)
1999 goto _error; 2011 goto _error;
2000 if (!snd_card_proc_new(chip->card, "audigy2nx", &entry)) 2012 if (!snd_card_proc_new(chip->card, "audigy2nx", &entry))
2001 snd_info_set_text_ops(entry, mixer, 1024, 2013 snd_info_set_text_ops(entry, mixer,
2002 snd_audigy2nx_proc_read); 2014 snd_audigy2nx_proc_read);
2003 } 2015 }
2004 2016
diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c
index fe67a92e2a1a..88b72b52590f 100644
--- a/sound/usb/usx2y/usx2yhwdeppcm.c
+++ b/sound/usb/usx2y/usx2yhwdeppcm.c
@@ -632,7 +632,7 @@ static int usX2Y_pcms_lock_check(struct snd_card *card)
632 for (s = 0; s < 2; ++s) { 632 for (s = 0; s < 2; ++s) {
633 struct snd_pcm_substream *substream; 633 struct snd_pcm_substream *substream;
634 substream = pcm->streams[s].substream; 634 substream = pcm->streams[s].substream;
635 if (substream && substream->ffile != NULL) 635 if (SUBSTREAM_BUSY(substream))
636 err = -EBUSY; 636 err = -EBUSY;
637 } 637 }
638 } 638 }