diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2009-03-28 16:29:51 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2009-03-28 16:29:51 -0400 |
commit | ed40d0c472b136682b2fcba05f89762859c7374f (patch) | |
tree | 076b83a26bcd63d6158463735dd34c10bbc591dc /sound | |
parent | 9e495834e59ca9b29f1a1f63b9f5533bb022ac49 (diff) | |
parent | 5d80f8e5a9dc9c9a94d4aeaa567e219a808b8a4a (diff) |
Merge branch 'origin' into devel
Conflicts:
sound/soc/pxa/pxa2xx-i2s.c
Diffstat (limited to 'sound')
374 files changed, 19781 insertions, 9311 deletions
diff --git a/sound/Kconfig b/sound/Kconfig index 200aca1faa71..1eceb85287c5 100644 --- a/sound/Kconfig +++ b/sound/Kconfig | |||
@@ -60,6 +60,8 @@ source "sound/aoa/Kconfig" | |||
60 | 60 | ||
61 | source "sound/arm/Kconfig" | 61 | source "sound/arm/Kconfig" |
62 | 62 | ||
63 | source "sound/atmel/Kconfig" | ||
64 | |||
63 | source "sound/spi/Kconfig" | 65 | source "sound/spi/Kconfig" |
64 | 66 | ||
65 | source "sound/mips/Kconfig" | 67 | source "sound/mips/Kconfig" |
diff --git a/sound/Makefile b/sound/Makefile index c76d70716fa5..ec467decfa79 100644 --- a/sound/Makefile +++ b/sound/Makefile | |||
@@ -6,7 +6,7 @@ obj-$(CONFIG_SOUND_PRIME) += sound_firmware.o | |||
6 | obj-$(CONFIG_SOUND_PRIME) += oss/ | 6 | obj-$(CONFIG_SOUND_PRIME) += oss/ |
7 | obj-$(CONFIG_DMASOUND) += oss/ | 7 | obj-$(CONFIG_DMASOUND) += oss/ |
8 | obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ sh/ synth/ usb/ \ | 8 | obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ sh/ synth/ usb/ \ |
9 | sparc/ spi/ parisc/ pcmcia/ mips/ soc/ | 9 | sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/ |
10 | obj-$(CONFIG_SND_AOA) += aoa/ | 10 | obj-$(CONFIG_SND_AOA) += aoa/ |
11 | 11 | ||
12 | # This one must be compilable even if sound is configured out | 12 | # This one must be compilable even if sound is configured out |
diff --git a/sound/aoa/aoa-gpio.h b/sound/aoa/aoa-gpio.h index ee64f5de8966..6065b0344e23 100644 --- a/sound/aoa/aoa-gpio.h +++ b/sound/aoa/aoa-gpio.h | |||
@@ -34,10 +34,12 @@ struct gpio_methods { | |||
34 | void (*set_headphone)(struct gpio_runtime *rt, int on); | 34 | void (*set_headphone)(struct gpio_runtime *rt, int on); |
35 | void (*set_speakers)(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); | 36 | void (*set_lineout)(struct gpio_runtime *rt, int on); |
37 | void (*set_master)(struct gpio_runtime *rt, int on); | ||
37 | 38 | ||
38 | int (*get_headphone)(struct gpio_runtime *rt); | 39 | int (*get_headphone)(struct gpio_runtime *rt); |
39 | int (*get_speakers)(struct gpio_runtime *rt); | 40 | int (*get_speakers)(struct gpio_runtime *rt); |
40 | int (*get_lineout)(struct gpio_runtime *rt); | 41 | int (*get_lineout)(struct gpio_runtime *rt); |
42 | int (*get_master)(struct gpio_runtime *rt); | ||
41 | 43 | ||
42 | void (*set_hw_reset)(struct gpio_runtime *rt, int on); | 44 | void (*set_hw_reset)(struct gpio_runtime *rt, int on); |
43 | 45 | ||
diff --git a/sound/aoa/core/alsa.c b/sound/aoa/core/alsa.c index 617850463582..0fa3855b4790 100644 --- a/sound/aoa/core/alsa.c +++ b/sound/aoa/core/alsa.c | |||
@@ -23,9 +23,10 @@ int aoa_alsa_init(char *name, struct module *mod, struct device *dev) | |||
23 | /* cannot be EEXIST due to usage in aoa_fabric_register */ | 23 | /* cannot be EEXIST due to usage in aoa_fabric_register */ |
24 | return -EBUSY; | 24 | return -EBUSY; |
25 | 25 | ||
26 | alsa_card = snd_card_new(index, name, mod, sizeof(struct aoa_card)); | 26 | err = snd_card_create(index, name, mod, sizeof(struct aoa_card), |
27 | if (!alsa_card) | 27 | &alsa_card); |
28 | return -ENOMEM; | 28 | if (err < 0) |
29 | return err; | ||
29 | aoa_card = alsa_card->private_data; | 30 | aoa_card = alsa_card->private_data; |
30 | aoa_card->alsa_card = alsa_card; | 31 | aoa_card->alsa_card = alsa_card; |
31 | alsa_card->dev = dev; | 32 | alsa_card->dev = dev; |
diff --git a/sound/aoa/core/gpio-feature.c b/sound/aoa/core/gpio-feature.c index c93ad5dec66b..de8e03afa97b 100644 --- a/sound/aoa/core/gpio-feature.c +++ b/sound/aoa/core/gpio-feature.c | |||
@@ -14,7 +14,7 @@ | |||
14 | #include <linux/interrupt.h> | 14 | #include <linux/interrupt.h> |
15 | #include "../aoa.h" | 15 | #include "../aoa.h" |
16 | 16 | ||
17 | /* TODO: these are 20 global variables | 17 | /* TODO: these are lots of global variables |
18 | * that aren't used on most machines... | 18 | * that aren't used on most machines... |
19 | * Move them into a dynamically allocated | 19 | * Move them into a dynamically allocated |
20 | * structure and use that. | 20 | * structure and use that. |
@@ -23,6 +23,7 @@ | |||
23 | /* these are the GPIO numbers (register addresses as offsets into | 23 | /* these are the GPIO numbers (register addresses as offsets into |
24 | * the GPIO space) */ | 24 | * the GPIO space) */ |
25 | static int headphone_mute_gpio; | 25 | static int headphone_mute_gpio; |
26 | static int master_mute_gpio; | ||
26 | static int amp_mute_gpio; | 27 | static int amp_mute_gpio; |
27 | static int lineout_mute_gpio; | 28 | static int lineout_mute_gpio; |
28 | static int hw_reset_gpio; | 29 | static int hw_reset_gpio; |
@@ -32,6 +33,7 @@ static int linein_detect_gpio; | |||
32 | 33 | ||
33 | /* see the SWITCH_GPIO macro */ | 34 | /* see the SWITCH_GPIO macro */ |
34 | static int headphone_mute_gpio_activestate; | 35 | static int headphone_mute_gpio_activestate; |
36 | static int master_mute_gpio_activestate; | ||
35 | static int amp_mute_gpio_activestate; | 37 | static int amp_mute_gpio_activestate; |
36 | static int lineout_mute_gpio_activestate; | 38 | static int lineout_mute_gpio_activestate; |
37 | static int hw_reset_gpio_activestate; | 39 | static int hw_reset_gpio_activestate; |
@@ -156,6 +158,7 @@ static int ftr_gpio_get_##name(struct gpio_runtime *rt) \ | |||
156 | FTR_GPIO(headphone, 0); | 158 | FTR_GPIO(headphone, 0); |
157 | FTR_GPIO(amp, 1); | 159 | FTR_GPIO(amp, 1); |
158 | FTR_GPIO(lineout, 2); | 160 | FTR_GPIO(lineout, 2); |
161 | FTR_GPIO(master, 3); | ||
159 | 162 | ||
160 | static void ftr_gpio_set_hw_reset(struct gpio_runtime *rt, int on) | 163 | static void ftr_gpio_set_hw_reset(struct gpio_runtime *rt, int on) |
161 | { | 164 | { |
@@ -172,6 +175,8 @@ static void ftr_gpio_set_hw_reset(struct gpio_runtime *rt, int on) | |||
172 | hw_reset_gpio, v); | 175 | hw_reset_gpio, v); |
173 | } | 176 | } |
174 | 177 | ||
178 | static struct gpio_methods methods; | ||
179 | |||
175 | static void ftr_gpio_all_amps_off(struct gpio_runtime *rt) | 180 | static void ftr_gpio_all_amps_off(struct gpio_runtime *rt) |
176 | { | 181 | { |
177 | int saved; | 182 | int saved; |
@@ -181,6 +186,8 @@ static void ftr_gpio_all_amps_off(struct gpio_runtime *rt) | |||
181 | ftr_gpio_set_headphone(rt, 0); | 186 | ftr_gpio_set_headphone(rt, 0); |
182 | ftr_gpio_set_amp(rt, 0); | 187 | ftr_gpio_set_amp(rt, 0); |
183 | ftr_gpio_set_lineout(rt, 0); | 188 | ftr_gpio_set_lineout(rt, 0); |
189 | if (methods.set_master) | ||
190 | ftr_gpio_set_master(rt, 0); | ||
184 | rt->implementation_private = saved; | 191 | rt->implementation_private = saved; |
185 | } | 192 | } |
186 | 193 | ||
@@ -193,6 +200,8 @@ static void ftr_gpio_all_amps_restore(struct gpio_runtime *rt) | |||
193 | ftr_gpio_set_headphone(rt, (s>>0)&1); | 200 | ftr_gpio_set_headphone(rt, (s>>0)&1); |
194 | ftr_gpio_set_amp(rt, (s>>1)&1); | 201 | ftr_gpio_set_amp(rt, (s>>1)&1); |
195 | ftr_gpio_set_lineout(rt, (s>>2)&1); | 202 | ftr_gpio_set_lineout(rt, (s>>2)&1); |
203 | if (methods.set_master) | ||
204 | ftr_gpio_set_master(rt, (s>>3)&1); | ||
196 | } | 205 | } |
197 | 206 | ||
198 | static void ftr_handle_notify(struct work_struct *work) | 207 | static void ftr_handle_notify(struct work_struct *work) |
@@ -231,6 +240,12 @@ static void ftr_gpio_init(struct gpio_runtime *rt) | |||
231 | get_gpio("hw-reset", "audio-hw-reset", | 240 | get_gpio("hw-reset", "audio-hw-reset", |
232 | &hw_reset_gpio, | 241 | &hw_reset_gpio, |
233 | &hw_reset_gpio_activestate); | 242 | &hw_reset_gpio_activestate); |
243 | if (get_gpio("master-mute", NULL, | ||
244 | &master_mute_gpio, | ||
245 | &master_mute_gpio_activestate)) { | ||
246 | methods.set_master = ftr_gpio_set_master; | ||
247 | methods.get_master = ftr_gpio_get_master; | ||
248 | } | ||
234 | 249 | ||
235 | headphone_detect_node = get_gpio("headphone-detect", NULL, | 250 | headphone_detect_node = get_gpio("headphone-detect", NULL, |
236 | &headphone_detect_gpio, | 251 | &headphone_detect_gpio, |
diff --git a/sound/aoa/fabrics/layout.c b/sound/aoa/fabrics/layout.c index ad60f5d10e82..fbf5c933baa4 100644 --- a/sound/aoa/fabrics/layout.c +++ b/sound/aoa/fabrics/layout.c | |||
@@ -1,16 +1,14 @@ | |||
1 | /* | 1 | /* |
2 | * Apple Onboard Audio driver -- layout fabric | 2 | * Apple Onboard Audio driver -- layout/machine id fabric |
3 | * | 3 | * |
4 | * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> | 4 | * Copyright 2006-2008 Johannes Berg <johannes@sipsolutions.net> |
5 | * | 5 | * |
6 | * GPL v2, can be found in COPYING. | 6 | * GPL v2, can be found in COPYING. |
7 | * | 7 | * |
8 | * | 8 | * |
9 | * This fabric module looks for sound codecs | 9 | * This fabric module looks for sound codecs based on the |
10 | * based on the layout-id property in the device tree. | 10 | * layout-id or device-id property in the device tree. |
11 | * | ||
12 | */ | 11 | */ |
13 | |||
14 | #include <asm/prom.h> | 12 | #include <asm/prom.h> |
15 | #include <linux/list.h> | 13 | #include <linux/list.h> |
16 | #include <linux/module.h> | 14 | #include <linux/module.h> |
@@ -63,7 +61,7 @@ struct codec_connect_info { | |||
63 | #define LAYOUT_FLAG_COMBO_LINEOUT_SPDIF (1<<0) | 61 | #define LAYOUT_FLAG_COMBO_LINEOUT_SPDIF (1<<0) |
64 | 62 | ||
65 | struct layout { | 63 | struct layout { |
66 | unsigned int layout_id; | 64 | unsigned int layout_id, device_id; |
67 | struct codec_connect_info codecs[MAX_CODECS_PER_BUS]; | 65 | struct codec_connect_info codecs[MAX_CODECS_PER_BUS]; |
68 | int flags; | 66 | int flags; |
69 | 67 | ||
@@ -111,6 +109,10 @@ MODULE_ALIAS("sound-layout-96"); | |||
111 | MODULE_ALIAS("sound-layout-98"); | 109 | MODULE_ALIAS("sound-layout-98"); |
112 | MODULE_ALIAS("sound-layout-100"); | 110 | MODULE_ALIAS("sound-layout-100"); |
113 | 111 | ||
112 | MODULE_ALIAS("aoa-device-id-14"); | ||
113 | MODULE_ALIAS("aoa-device-id-22"); | ||
114 | MODULE_ALIAS("aoa-device-id-35"); | ||
115 | |||
114 | /* onyx with all but microphone connected */ | 116 | /* onyx with all but microphone connected */ |
115 | static struct codec_connection onyx_connections_nomic[] = { | 117 | static struct codec_connection onyx_connections_nomic[] = { |
116 | { | 118 | { |
@@ -518,6 +520,27 @@ static struct layout layouts[] = { | |||
518 | .connections = onyx_connections_noheadphones, | 520 | .connections = onyx_connections_noheadphones, |
519 | }, | 521 | }, |
520 | }, | 522 | }, |
523 | /* PowerMac3,4 */ | ||
524 | { .device_id = 14, | ||
525 | .codecs[0] = { | ||
526 | .name = "tas", | ||
527 | .connections = tas_connections_noline, | ||
528 | }, | ||
529 | }, | ||
530 | /* PowerMac3,6 */ | ||
531 | { .device_id = 22, | ||
532 | .codecs[0] = { | ||
533 | .name = "tas", | ||
534 | .connections = tas_connections_all, | ||
535 | }, | ||
536 | }, | ||
537 | /* PowerBook5,2 */ | ||
538 | { .device_id = 35, | ||
539 | .codecs[0] = { | ||
540 | .name = "tas", | ||
541 | .connections = tas_connections_all, | ||
542 | }, | ||
543 | }, | ||
521 | {} | 544 | {} |
522 | }; | 545 | }; |
523 | 546 | ||
@@ -526,7 +549,7 @@ static struct layout *find_layout_by_id(unsigned int id) | |||
526 | struct layout *l; | 549 | struct layout *l; |
527 | 550 | ||
528 | l = layouts; | 551 | l = layouts; |
529 | while (l->layout_id) { | 552 | while (l->codecs[0].name) { |
530 | if (l->layout_id == id) | 553 | if (l->layout_id == id) |
531 | return l; | 554 | return l; |
532 | l++; | 555 | l++; |
@@ -534,6 +557,19 @@ static struct layout *find_layout_by_id(unsigned int id) | |||
534 | return NULL; | 557 | return NULL; |
535 | } | 558 | } |
536 | 559 | ||
560 | static struct layout *find_layout_by_device(unsigned int id) | ||
561 | { | ||
562 | struct layout *l; | ||
563 | |||
564 | l = layouts; | ||
565 | while (l->codecs[0].name) { | ||
566 | if (l->device_id == id) | ||
567 | return l; | ||
568 | l++; | ||
569 | } | ||
570 | return NULL; | ||
571 | } | ||
572 | |||
537 | static void use_layout(struct layout *l) | 573 | static void use_layout(struct layout *l) |
538 | { | 574 | { |
539 | int i; | 575 | int i; |
@@ -564,6 +600,7 @@ struct layout_dev { | |||
564 | struct snd_kcontrol *headphone_ctrl; | 600 | struct snd_kcontrol *headphone_ctrl; |
565 | struct snd_kcontrol *lineout_ctrl; | 601 | struct snd_kcontrol *lineout_ctrl; |
566 | struct snd_kcontrol *speaker_ctrl; | 602 | struct snd_kcontrol *speaker_ctrl; |
603 | struct snd_kcontrol *master_ctrl; | ||
567 | struct snd_kcontrol *headphone_detected_ctrl; | 604 | struct snd_kcontrol *headphone_detected_ctrl; |
568 | struct snd_kcontrol *lineout_detected_ctrl; | 605 | struct snd_kcontrol *lineout_detected_ctrl; |
569 | 606 | ||
@@ -615,6 +652,7 @@ static struct snd_kcontrol_new n##_ctl = { \ | |||
615 | AMP_CONTROL(headphone, "Headphone Switch"); | 652 | AMP_CONTROL(headphone, "Headphone Switch"); |
616 | AMP_CONTROL(speakers, "Speakers Switch"); | 653 | AMP_CONTROL(speakers, "Speakers Switch"); |
617 | AMP_CONTROL(lineout, "Line-Out Switch"); | 654 | AMP_CONTROL(lineout, "Line-Out Switch"); |
655 | AMP_CONTROL(master, "Master Switch"); | ||
618 | 656 | ||
619 | static int detect_choice_get(struct snd_kcontrol *kcontrol, | 657 | static int detect_choice_get(struct snd_kcontrol *kcontrol, |
620 | struct snd_ctl_elem_value *ucontrol) | 658 | struct snd_ctl_elem_value *ucontrol) |
@@ -855,6 +893,11 @@ static void layout_attached_codec(struct aoa_codec *codec) | |||
855 | lineout = codec->gpio->methods->get_detect(codec->gpio, | 893 | lineout = codec->gpio->methods->get_detect(codec->gpio, |
856 | AOA_NOTIFY_LINE_OUT); | 894 | AOA_NOTIFY_LINE_OUT); |
857 | 895 | ||
896 | if (codec->gpio->methods->set_master) { | ||
897 | ctl = snd_ctl_new1(&master_ctl, codec->gpio); | ||
898 | ldev->master_ctrl = ctl; | ||
899 | aoa_snd_ctl_add(ctl); | ||
900 | } | ||
858 | while (cc->connected) { | 901 | while (cc->connected) { |
859 | if (cc->connected & CC_SPEAKERS) { | 902 | if (cc->connected & CC_SPEAKERS) { |
860 | if (headphones <= 0 && lineout <= 0) | 903 | if (headphones <= 0 && lineout <= 0) |
@@ -938,8 +981,8 @@ static struct aoa_fabric layout_fabric = { | |||
938 | static int aoa_fabric_layout_probe(struct soundbus_dev *sdev) | 981 | static int aoa_fabric_layout_probe(struct soundbus_dev *sdev) |
939 | { | 982 | { |
940 | struct device_node *sound = NULL; | 983 | struct device_node *sound = NULL; |
941 | const unsigned int *layout_id; | 984 | const unsigned int *id; |
942 | struct layout *layout; | 985 | struct layout *layout = NULL; |
943 | struct layout_dev *ldev = NULL; | 986 | struct layout_dev *ldev = NULL; |
944 | int err; | 987 | int err; |
945 | 988 | ||
@@ -952,15 +995,18 @@ static int aoa_fabric_layout_probe(struct soundbus_dev *sdev) | |||
952 | if (sound->type && strcasecmp(sound->type, "soundchip") == 0) | 995 | if (sound->type && strcasecmp(sound->type, "soundchip") == 0) |
953 | break; | 996 | break; |
954 | } | 997 | } |
955 | if (!sound) return -ENODEV; | 998 | if (!sound) |
999 | return -ENODEV; | ||
956 | 1000 | ||
957 | layout_id = of_get_property(sound, "layout-id", NULL); | 1001 | id = of_get_property(sound, "layout-id", NULL); |
958 | if (!layout_id) | 1002 | if (id) { |
959 | goto outnodev; | 1003 | layout = find_layout_by_id(*id); |
960 | printk(KERN_INFO "snd-aoa-fabric-layout: found bus with layout %d\n", | 1004 | } else { |
961 | *layout_id); | 1005 | id = of_get_property(sound, "device-id", NULL); |
1006 | if (id) | ||
1007 | layout = find_layout_by_device(*id); | ||
1008 | } | ||
962 | 1009 | ||
963 | layout = find_layout_by_id(*layout_id); | ||
964 | if (!layout) { | 1010 | if (!layout) { |
965 | printk(KERN_ERR "snd-aoa-fabric-layout: unknown layout\n"); | 1011 | printk(KERN_ERR "snd-aoa-fabric-layout: unknown layout\n"); |
966 | goto outnodev; | 1012 | goto outnodev; |
@@ -976,6 +1022,7 @@ static int aoa_fabric_layout_probe(struct soundbus_dev *sdev) | |||
976 | ldev->layout = layout; | 1022 | ldev->layout = layout; |
977 | ldev->gpio.node = sound->parent; | 1023 | ldev->gpio.node = sound->parent; |
978 | switch (layout->layout_id) { | 1024 | switch (layout->layout_id) { |
1025 | case 0: /* anything with device_id, not layout_id */ | ||
979 | case 41: /* that unknown machine no one seems to have */ | 1026 | case 41: /* that unknown machine no one seems to have */ |
980 | case 51: /* PowerBook5,4 */ | 1027 | case 51: /* PowerBook5,4 */ |
981 | case 58: /* Mac Mini */ | 1028 | case 58: /* Mac Mini */ |
diff --git a/sound/aoa/soundbus/i2sbus/core.c b/sound/aoa/soundbus/i2sbus/core.c index be468edf3ecb..418c84c99d69 100644 --- a/sound/aoa/soundbus/i2sbus/core.c +++ b/sound/aoa/soundbus/i2sbus/core.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * i2sbus driver | 2 | * i2sbus driver |
3 | * | 3 | * |
4 | * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> | 4 | * Copyright 2006-2008 Johannes Berg <johannes@sipsolutions.net> |
5 | * | 5 | * |
6 | * GPL v2, can be found in COPYING. | 6 | * GPL v2, can be found in COPYING. |
7 | */ | 7 | */ |
@@ -186,13 +186,25 @@ static int i2sbus_add_dev(struct macio_dev *macio, | |||
186 | } | 186 | } |
187 | } | 187 | } |
188 | if (i == 1) { | 188 | if (i == 1) { |
189 | const u32 *layout_id = | 189 | const u32 *id = of_get_property(sound, "layout-id", NULL); |
190 | of_get_property(sound, "layout-id", NULL); | 190 | |
191 | if (layout_id) { | 191 | if (id) { |
192 | layout = *layout_id; | 192 | layout = *id; |
193 | snprintf(dev->sound.modalias, 32, | 193 | snprintf(dev->sound.modalias, 32, |
194 | "sound-layout-%d", layout); | 194 | "sound-layout-%d", layout); |
195 | ok = 1; | 195 | ok = 1; |
196 | } else { | ||
197 | id = of_get_property(sound, "device-id", NULL); | ||
198 | /* | ||
199 | * We probably cannot handle all device-id machines, | ||
200 | * so restrict to those we do handle for now. | ||
201 | */ | ||
202 | if (id && (*id == 22 || *id == 14 || *id == 35)) { | ||
203 | snprintf(dev->sound.modalias, 32, | ||
204 | "aoa-device-id-%d", *id); | ||
205 | ok = 1; | ||
206 | layout = -1; | ||
207 | } | ||
196 | } | 208 | } |
197 | } | 209 | } |
198 | /* for the time being, until we can handle non-layout-id | 210 | /* for the time being, until we can handle non-layout-id |
diff --git a/sound/arm/Kconfig b/sound/arm/Kconfig index f8e6de48d816..885683a3b0bd 100644 --- a/sound/arm/Kconfig +++ b/sound/arm/Kconfig | |||
@@ -11,17 +11,6 @@ menuconfig SND_ARM | |||
11 | 11 | ||
12 | if SND_ARM | 12 | if SND_ARM |
13 | 13 | ||
14 | config SND_SA11XX_UDA1341 | ||
15 | tristate "SA11xx UDA1341TS driver (iPaq H3600)" | ||
16 | depends on ARCH_SA1100 && L3 | ||
17 | select SND_PCM | ||
18 | help | ||
19 | Say Y here if you have a Compaq iPaq H3x00 handheld computer | ||
20 | and want to use its Philips UDA 1341 audio chip. | ||
21 | |||
22 | To compile this driver as a module, choose M here: the module | ||
23 | will be called snd-sa11xx-uda1341. | ||
24 | |||
25 | config SND_ARMAACI | 14 | config SND_ARMAACI |
26 | tristate "ARM PrimeCell PL041 AC Link support" | 15 | tristate "ARM PrimeCell PL041 AC Link support" |
27 | depends on ARM_AMBA | 16 | depends on ARM_AMBA |
diff --git a/sound/arm/Makefile b/sound/arm/Makefile index 2054de11de8a..5a549ed6c8aa 100644 --- a/sound/arm/Makefile +++ b/sound/arm/Makefile | |||
@@ -2,9 +2,6 @@ | |||
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_SND_SA11XX_UDA1341) += snd-sa11xx-uda1341.o | ||
6 | snd-sa11xx-uda1341-objs := sa11xx-uda1341.o | ||
7 | |||
8 | obj-$(CONFIG_SND_ARMAACI) += snd-aaci.o | 5 | obj-$(CONFIG_SND_ARMAACI) += snd-aaci.o |
9 | snd-aaci-objs := aaci.o devdma.o | 6 | snd-aaci-objs := aaci.o devdma.o |
10 | 7 | ||
diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c index 772901e41ecb..7fbd68fab944 100644 --- a/sound/arm/aaci.c +++ b/sound/arm/aaci.c | |||
@@ -995,10 +995,11 @@ static struct aaci * __devinit aaci_init_card(struct amba_device *dev) | |||
995 | { | 995 | { |
996 | struct aaci *aaci; | 996 | struct aaci *aaci; |
997 | struct snd_card *card; | 997 | struct snd_card *card; |
998 | int err; | ||
998 | 999 | ||
999 | card = snd_card_new(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, | 1000 | err = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, |
1000 | THIS_MODULE, sizeof(struct aaci)); | 1001 | THIS_MODULE, sizeof(struct aaci), &card); |
1001 | if (card == NULL) | 1002 | if (err < 0) |
1002 | return NULL; | 1003 | return NULL; |
1003 | 1004 | ||
1004 | card->private_free = aaci_free_card; | 1005 | card->private_free = aaci_free_card; |
diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c index 718d06640dd4..7793d2a511ce 100644 --- a/sound/arm/pxa2xx-ac97-lib.c +++ b/sound/arm/pxa2xx-ac97-lib.c | |||
@@ -30,6 +30,7 @@ static DECLARE_WAIT_QUEUE_HEAD(gsr_wq); | |||
30 | static volatile long gsr_bits; | 30 | static volatile long gsr_bits; |
31 | static struct clk *ac97_clk; | 31 | static struct clk *ac97_clk; |
32 | static struct clk *ac97conf_clk; | 32 | static struct clk *ac97conf_clk; |
33 | static int reset_gpio; | ||
33 | 34 | ||
34 | /* | 35 | /* |
35 | * Beware PXA27x bugs: | 36 | * Beware PXA27x bugs: |
@@ -41,6 +42,45 @@ static struct clk *ac97conf_clk; | |||
41 | * 1 jiffy timeout if interrupt never comes). | 42 | * 1 jiffy timeout if interrupt never comes). |
42 | */ | 43 | */ |
43 | 44 | ||
45 | enum { | ||
46 | RESETGPIO_FORCE_HIGH, | ||
47 | RESETGPIO_FORCE_LOW, | ||
48 | RESETGPIO_NORMAL_ALTFUNC | ||
49 | }; | ||
50 | |||
51 | /** | ||
52 | * set_resetgpio_mode - computes and sets the AC97_RESET gpio mode on PXA | ||
53 | * @mode: chosen action | ||
54 | * | ||
55 | * As the PXA27x CPUs suffer from a AC97 bug, a manual control of the reset line | ||
56 | * must be done to insure proper work of AC97 reset line. This function | ||
57 | * computes the correct gpio_mode for further use by reset functions, and | ||
58 | * applied the change through pxa_gpio_mode. | ||
59 | */ | ||
60 | static void set_resetgpio_mode(int resetgpio_action) | ||
61 | { | ||
62 | int mode = 0; | ||
63 | |||
64 | if (reset_gpio) | ||
65 | switch (resetgpio_action) { | ||
66 | case RESETGPIO_NORMAL_ALTFUNC: | ||
67 | if (reset_gpio == 113) | ||
68 | mode = 113 | GPIO_OUT | GPIO_DFLT_LOW; | ||
69 | if (reset_gpio == 95) | ||
70 | mode = 95 | GPIO_ALT_FN_1_OUT; | ||
71 | break; | ||
72 | case RESETGPIO_FORCE_LOW: | ||
73 | mode = reset_gpio | GPIO_OUT | GPIO_DFLT_LOW; | ||
74 | break; | ||
75 | case RESETGPIO_FORCE_HIGH: | ||
76 | mode = reset_gpio | GPIO_OUT | GPIO_DFLT_HIGH; | ||
77 | break; | ||
78 | }; | ||
79 | |||
80 | if (mode) | ||
81 | pxa_gpio_mode(mode); | ||
82 | } | ||
83 | |||
44 | unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg) | 84 | unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg) |
45 | { | 85 | { |
46 | unsigned short val = -1; | 86 | unsigned short val = -1; |
@@ -136,10 +176,10 @@ static inline void pxa_ac97_warm_pxa27x(void) | |||
136 | 176 | ||
137 | /* warm reset broken on Bulverde, | 177 | /* warm reset broken on Bulverde, |
138 | so manually keep AC97 reset high */ | 178 | so manually keep AC97 reset high */ |
139 | pxa_gpio_mode(113 | GPIO_OUT | GPIO_DFLT_HIGH); | 179 | set_resetgpio_mode(RESETGPIO_FORCE_HIGH); |
140 | udelay(10); | 180 | udelay(10); |
141 | GCR |= GCR_WARM_RST; | 181 | GCR |= GCR_WARM_RST; |
142 | pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT); | 182 | set_resetgpio_mode(RESETGPIO_NORMAL_ALTFUNC); |
143 | udelay(500); | 183 | udelay(500); |
144 | } | 184 | } |
145 | 185 | ||
@@ -307,8 +347,8 @@ int pxa2xx_ac97_hw_resume(void) | |||
307 | pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD); | 347 | pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD); |
308 | } | 348 | } |
309 | if (cpu_is_pxa27x()) { | 349 | if (cpu_is_pxa27x()) { |
310 | /* Use GPIO 113 as AC97 Reset on Bulverde */ | 350 | /* Use GPIO 113 or 95 as AC97 Reset on Bulverde */ |
311 | pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT); | 351 | set_resetgpio_mode(RESETGPIO_NORMAL_ALTFUNC); |
312 | } | 352 | } |
313 | clk_enable(ac97_clk); | 353 | clk_enable(ac97_clk); |
314 | return 0; | 354 | return 0; |
@@ -319,6 +359,27 @@ EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_resume); | |||
319 | int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev) | 359 | int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev) |
320 | { | 360 | { |
321 | int ret; | 361 | int ret; |
362 | struct pxa2xx_ac97_platform_data *pdata = dev->dev.platform_data; | ||
363 | |||
364 | if (pdata) { | ||
365 | switch (pdata->reset_gpio) { | ||
366 | case 95: | ||
367 | case 113: | ||
368 | reset_gpio = pdata->reset_gpio; | ||
369 | break; | ||
370 | case 0: | ||
371 | reset_gpio = 113; | ||
372 | break; | ||
373 | case -1: | ||
374 | break; | ||
375 | default: | ||
376 | dev_err(&dev->dev, "Invalid reset GPIO %d\n", | ||
377 | pdata->reset_gpio); | ||
378 | } | ||
379 | } else { | ||
380 | if (cpu_is_pxa27x()) | ||
381 | reset_gpio = 113; | ||
382 | } | ||
322 | 383 | ||
323 | if (cpu_is_pxa25x() || cpu_is_pxa27x()) { | 384 | if (cpu_is_pxa25x() || cpu_is_pxa27x()) { |
324 | pxa_gpio_mode(GPIO31_SYNC_AC97_MD); | 385 | pxa_gpio_mode(GPIO31_SYNC_AC97_MD); |
@@ -329,7 +390,7 @@ int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev) | |||
329 | 390 | ||
330 | if (cpu_is_pxa27x()) { | 391 | if (cpu_is_pxa27x()) { |
331 | /* Use GPIO 113 as AC97 Reset on Bulverde */ | 392 | /* Use GPIO 113 as AC97 Reset on Bulverde */ |
332 | pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT); | 393 | set_resetgpio_mode(RESETGPIO_NORMAL_ALTFUNC); |
333 | ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK"); | 394 | ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK"); |
334 | if (IS_ERR(ac97conf_clk)) { | 395 | if (IS_ERR(ac97conf_clk)) { |
335 | ret = PTR_ERR(ac97conf_clk); | 396 | ret = PTR_ERR(ac97conf_clk); |
diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c index ccec48fc8e3f..c570ebd9d177 100644 --- a/sound/arm/pxa2xx-ac97.c +++ b/sound/arm/pxa2xx-ac97.c | |||
@@ -171,10 +171,9 @@ static int __devinit pxa2xx_ac97_probe(struct platform_device *dev) | |||
171 | struct snd_ac97_template ac97_template; | 171 | struct snd_ac97_template ac97_template; |
172 | int ret; | 172 | int ret; |
173 | 173 | ||
174 | ret = -ENOMEM; | 174 | ret = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, |
175 | card = snd_card_new(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, | 175 | THIS_MODULE, 0, &card); |
176 | THIS_MODULE, 0); | 176 | if (ret < 0) |
177 | if (!card) | ||
178 | goto err; | 177 | goto err; |
179 | 178 | ||
180 | card->dev = &dev->dev; | 179 | card->dev = &dev->dev; |
diff --git a/sound/arm/sa11xx-uda1341.c b/sound/arm/sa11xx-uda1341.c deleted file mode 100644 index 1dcd51d81d10..000000000000 --- a/sound/arm/sa11xx-uda1341.c +++ /dev/null | |||
@@ -1,983 +0,0 @@ | |||
1 | /* | ||
2 | * Driver for Philips UDA1341TS on Compaq iPAQ H3600 soundcard | ||
3 | * Copyright (C) 2002 Tomas Kasparek <tomas.kasparek@seznam.cz> | ||
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. | ||
7 | * | ||
8 | * History: | ||
9 | * | ||
10 | * 2002-03-13 Tomas Kasparek initial release - based on h3600-uda1341.c from OSS | ||
11 | * 2002-03-20 Tomas Kasparek playback over ALSA is working | ||
12 | * 2002-03-28 Tomas Kasparek playback over OSS emulation is working | ||
13 | * 2002-03-29 Tomas Kasparek basic capture is working (native ALSA) | ||
14 | * 2002-03-29 Tomas Kasparek capture is working (OSS emulation) | ||
15 | * 2002-04-04 Tomas Kasparek better rates handling (allow non-standard rates) | ||
16 | * 2003-02-14 Brian Avery fixed full duplex mode, other updates | ||
17 | * 2003-02-20 Tomas Kasparek merged updates by Brian (except HAL) | ||
18 | * 2003-04-19 Jaroslav Kysela recoded DMA stuff to follow 2.4.18rmk3-hh24 kernel | ||
19 | * working suspend and resume | ||
20 | * 2003-04-28 Tomas Kasparek updated work by Jaroslav to compile it under 2.5.x again | ||
21 | * merged HAL layer (patches from Brian) | ||
22 | */ | ||
23 | |||
24 | /*************************************************************************************************** | ||
25 | * | ||
26 | * To understand what Alsa Drivers should be doing look at "Writing an Alsa Driver" by Takashi Iwai | ||
27 | * available in the Alsa doc section on the website | ||
28 | * | ||
29 | * A few notes to make things clearer. The UDA1341 is hooked up to Serial port 4 on the SA1100. | ||
30 | * We are using SSP mode to talk to the UDA1341. The UDA1341 bit & wordselect clocks are generated | ||
31 | * by this UART. Unfortunately, the clock only runs if the transmit buffer has something in it. | ||
32 | * So, if we are just recording, we feed the transmit DMA stream a bunch of 0x0000 so that the | ||
33 | * transmit buffer is full and the clock keeps going. The zeroes come from FLUSH_BASE_PHYS which | ||
34 | * is a mem loc that always decodes to 0's w/ no off chip access. | ||
35 | * | ||
36 | * Some alsa terminology: | ||
37 | * frame => num_channels * sample_size e.g stereo 16 bit is 2 * 16 = 32 bytes | ||
38 | * period => the least number of bytes that will generate an interrupt e.g. we have a 1024 byte | ||
39 | * buffer and 4 periods in the runtime structure this means we'll get an int every 256 | ||
40 | * bytes or 4 times per buffer. | ||
41 | * A number of the sizes are in frames rather than bytes, use frames_to_bytes and | ||
42 | * bytes_to_frames to convert. The easiest way to tell the units is to look at the | ||
43 | * type i.e. runtime-> buffer_size is in frames and its type is snd_pcm_uframes_t | ||
44 | * | ||
45 | * Notes about the pointer fxn: | ||
46 | * The pointer fxn needs to return the offset into the dma buffer in frames. | ||
47 | * Interrupts must be blocked before calling the dma_get_pos fxn to avoid race with interrupts. | ||
48 | * | ||
49 | * Notes about pause/resume | ||
50 | * Implementing this would be complicated so it's skipped. The problem case is: | ||
51 | * A full duplex connection is going, then play is paused. At this point you need to start xmitting | ||
52 | * 0's to keep the record active which means you cant just freeze the dma and resume it later you'd | ||
53 | * need to save off the dma info, and restore it properly on a resume. Yeach! | ||
54 | * | ||
55 | * Notes about transfer methods: | ||
56 | * The async write calls fail. I probably need to implement something else to support them? | ||
57 | * | ||
58 | ***************************************************************************************************/ | ||
59 | |||
60 | #include <linux/module.h> | ||
61 | #include <linux/moduleparam.h> | ||
62 | #include <linux/init.h> | ||
63 | #include <linux/err.h> | ||
64 | #include <linux/platform_device.h> | ||
65 | #include <linux/errno.h> | ||
66 | #include <linux/ioctl.h> | ||
67 | #include <linux/delay.h> | ||
68 | #include <linux/slab.h> | ||
69 | |||
70 | #ifdef CONFIG_PM | ||
71 | #include <linux/pm.h> | ||
72 | #endif | ||
73 | |||
74 | #include <mach/hardware.h> | ||
75 | #include <mach/h3600.h> | ||
76 | #include <asm/mach-types.h> | ||
77 | #include <asm/dma.h> | ||
78 | |||
79 | #include <sound/core.h> | ||
80 | #include <sound/pcm.h> | ||
81 | #include <sound/initval.h> | ||
82 | |||
83 | #include <linux/l3/l3.h> | ||
84 | |||
85 | #undef DEBUG_MODE | ||
86 | #undef DEBUG_FUNCTION_NAMES | ||
87 | #include <sound/uda1341.h> | ||
88 | |||
89 | /* | ||
90 | * FIXME: Is this enough as autodetection of 2.4.X-rmkY-hhZ kernels? | ||
91 | * We use DMA stuff from 2.4.18-rmk3-hh24 here to be able to compile this | ||
92 | * module for Familiar 0.6.1 | ||
93 | */ | ||
94 | |||
95 | /* {{{ Type definitions */ | ||
96 | |||
97 | MODULE_AUTHOR("Tomas Kasparek <tomas.kasparek@seznam.cz>"); | ||
98 | MODULE_LICENSE("GPL"); | ||
99 | MODULE_DESCRIPTION("SA1100/SA1111 + UDA1341TS driver for ALSA"); | ||
100 | MODULE_SUPPORTED_DEVICE("{{UDA1341,iPAQ H3600 UDA1341TS}}"); | ||
101 | |||
102 | static char *id; /* ID for this card */ | ||
103 | |||
104 | module_param(id, charp, 0444); | ||
105 | MODULE_PARM_DESC(id, "ID string for SA1100/SA1111 + UDA1341TS soundcard."); | ||
106 | |||
107 | struct audio_stream { | ||
108 | char *id; /* identification string */ | ||
109 | int stream_id; /* numeric identification */ | ||
110 | dma_device_t dma_dev; /* device identifier for DMA */ | ||
111 | #ifdef HH_VERSION | ||
112 | dmach_t dmach; /* dma channel identification */ | ||
113 | #else | ||
114 | dma_regs_t *dma_regs; /* points to our DMA registers */ | ||
115 | #endif | ||
116 | unsigned int active:1; /* we are using this stream for transfer now */ | ||
117 | int period; /* current transfer period */ | ||
118 | int periods; /* current count of periods registerd in the DMA engine */ | ||
119 | int tx_spin; /* are we recoding - flag used to do DMA trans. for sync */ | ||
120 | unsigned int old_offset; | ||
121 | spinlock_t dma_lock; /* for locking in DMA operations (see dma-sa1100.c in the kernel) */ | ||
122 | struct snd_pcm_substream *stream; | ||
123 | }; | ||
124 | |||
125 | struct sa11xx_uda1341 { | ||
126 | struct snd_card *card; | ||
127 | struct l3_client *uda1341; | ||
128 | struct snd_pcm *pcm; | ||
129 | long samplerate; | ||
130 | struct audio_stream s[2]; /* playback & capture */ | ||
131 | }; | ||
132 | |||
133 | static unsigned int rates[] = { | ||
134 | 8000, 10666, 10985, 14647, | ||
135 | 16000, 21970, 22050, 24000, | ||
136 | 29400, 32000, 44100, 48000, | ||
137 | }; | ||
138 | |||
139 | static struct snd_pcm_hw_constraint_list hw_constraints_rates = { | ||
140 | .count = ARRAY_SIZE(rates), | ||
141 | .list = rates, | ||
142 | .mask = 0, | ||
143 | }; | ||
144 | |||
145 | static struct platform_device *device; | ||
146 | |||
147 | /* }}} */ | ||
148 | |||
149 | /* {{{ Clock and sample rate stuff */ | ||
150 | |||
151 | /* | ||
152 | * Stop-gap solution until rest of hh.org HAL stuff is merged. | ||
153 | */ | ||
154 | #define GPIO_H3600_CLK_SET0 GPIO_GPIO (12) | ||
155 | #define GPIO_H3600_CLK_SET1 GPIO_GPIO (13) | ||
156 | |||
157 | #ifdef CONFIG_SA1100_H3XXX | ||
158 | #define clr_sa11xx_uda1341_egpio(x) clr_h3600_egpio(x) | ||
159 | #define set_sa11xx_uda1341_egpio(x) set_h3600_egpio(x) | ||
160 | #else | ||
161 | #error This driver could serve H3x00 handhelds only! | ||
162 | #endif | ||
163 | |||
164 | static void sa11xx_uda1341_set_audio_clock(long val) | ||
165 | { | ||
166 | switch (val) { | ||
167 | case 24000: case 32000: case 48000: /* 00: 12.288 MHz */ | ||
168 | GPCR = GPIO_H3600_CLK_SET0 | GPIO_H3600_CLK_SET1; | ||
169 | break; | ||
170 | |||
171 | case 22050: case 29400: case 44100: /* 01: 11.2896 MHz */ | ||
172 | GPSR = GPIO_H3600_CLK_SET0; | ||
173 | GPCR = GPIO_H3600_CLK_SET1; | ||
174 | break; | ||
175 | |||
176 | case 8000: case 10666: case 16000: /* 10: 4.096 MHz */ | ||
177 | GPCR = GPIO_H3600_CLK_SET0; | ||
178 | GPSR = GPIO_H3600_CLK_SET1; | ||
179 | break; | ||
180 | |||
181 | case 10985: case 14647: case 21970: /* 11: 5.6245 MHz */ | ||
182 | GPSR = GPIO_H3600_CLK_SET0 | GPIO_H3600_CLK_SET1; | ||
183 | break; | ||
184 | } | ||
185 | } | ||
186 | |||
187 | static void sa11xx_uda1341_set_samplerate(struct sa11xx_uda1341 *sa11xx_uda1341, long rate) | ||
188 | { | ||
189 | int clk_div = 0; | ||
190 | int clk=0; | ||
191 | |||
192 | /* We don't want to mess with clocks when frames are in flight */ | ||
193 | Ser4SSCR0 &= ~SSCR0_SSE; | ||
194 | /* wait for any frame to complete */ | ||
195 | udelay(125); | ||
196 | |||
197 | /* | ||
198 | * We have the following clock sources: | ||
199 | * 4.096 MHz, 5.6245 MHz, 11.2896 MHz, 12.288 MHz | ||
200 | * Those can be divided either by 256, 384 or 512. | ||
201 | * This makes up 12 combinations for the following samplerates... | ||
202 | */ | ||
203 | if (rate >= 48000) | ||
204 | rate = 48000; | ||
205 | else if (rate >= 44100) | ||
206 | rate = 44100; | ||
207 | else if (rate >= 32000) | ||
208 | rate = 32000; | ||
209 | else if (rate >= 29400) | ||
210 | rate = 29400; | ||
211 | else if (rate >= 24000) | ||
212 | rate = 24000; | ||
213 | else if (rate >= 22050) | ||
214 | rate = 22050; | ||
215 | else if (rate >= 21970) | ||
216 | rate = 21970; | ||
217 | else if (rate >= 16000) | ||
218 | rate = 16000; | ||
219 | else if (rate >= 14647) | ||
220 | rate = 14647; | ||
221 | else if (rate >= 10985) | ||
222 | rate = 10985; | ||
223 | else if (rate >= 10666) | ||
224 | rate = 10666; | ||
225 | else | ||
226 | rate = 8000; | ||
227 | |||
228 | /* Set the external clock generator */ | ||
229 | |||
230 | sa11xx_uda1341_set_audio_clock(rate); | ||
231 | |||
232 | /* Select the clock divisor */ | ||
233 | switch (rate) { | ||
234 | case 8000: | ||
235 | case 10985: | ||
236 | case 22050: | ||
237 | case 24000: | ||
238 | clk = F512; | ||
239 | clk_div = SSCR0_SerClkDiv(16); | ||
240 | break; | ||
241 | case 16000: | ||
242 | case 21970: | ||
243 | case 44100: | ||
244 | case 48000: | ||
245 | clk = F256; | ||
246 | clk_div = SSCR0_SerClkDiv(8); | ||
247 | break; | ||
248 | case 10666: | ||
249 | case 14647: | ||
250 | case 29400: | ||
251 | case 32000: | ||
252 | clk = F384; | ||
253 | clk_div = SSCR0_SerClkDiv(12); | ||
254 | break; | ||
255 | } | ||
256 | |||
257 | /* FMT setting should be moved away when other FMTs are added (FIXME) */ | ||
258 | l3_command(sa11xx_uda1341->uda1341, CMD_FORMAT, (void *)LSB16); | ||
259 | |||
260 | l3_command(sa11xx_uda1341->uda1341, CMD_FS, (void *)clk); | ||
261 | Ser4SSCR0 = (Ser4SSCR0 & ~0xff00) + clk_div + SSCR0_SSE; | ||
262 | sa11xx_uda1341->samplerate = rate; | ||
263 | } | ||
264 | |||
265 | /* }}} */ | ||
266 | |||
267 | /* {{{ HW init and shutdown */ | ||
268 | |||
269 | static void sa11xx_uda1341_audio_init(struct sa11xx_uda1341 *sa11xx_uda1341) | ||
270 | { | ||
271 | unsigned long flags; | ||
272 | |||
273 | /* Setup DMA stuff */ | ||
274 | sa11xx_uda1341->s[SNDRV_PCM_STREAM_PLAYBACK].id = "UDA1341 out"; | ||
275 | sa11xx_uda1341->s[SNDRV_PCM_STREAM_PLAYBACK].stream_id = SNDRV_PCM_STREAM_PLAYBACK; | ||
276 | sa11xx_uda1341->s[SNDRV_PCM_STREAM_PLAYBACK].dma_dev = DMA_Ser4SSPWr; | ||
277 | |||
278 | sa11xx_uda1341->s[SNDRV_PCM_STREAM_CAPTURE].id = "UDA1341 in"; | ||
279 | sa11xx_uda1341->s[SNDRV_PCM_STREAM_CAPTURE].stream_id = SNDRV_PCM_STREAM_CAPTURE; | ||
280 | sa11xx_uda1341->s[SNDRV_PCM_STREAM_CAPTURE].dma_dev = DMA_Ser4SSPRd; | ||
281 | |||
282 | /* Initialize the UDA1341 internal state */ | ||
283 | |||
284 | /* Setup the uarts */ | ||
285 | local_irq_save(flags); | ||
286 | GAFR |= (GPIO_SSP_CLK); | ||
287 | GPDR &= ~(GPIO_SSP_CLK); | ||
288 | Ser4SSCR0 = 0; | ||
289 | Ser4SSCR0 = SSCR0_DataSize(16) + SSCR0_TI + SSCR0_SerClkDiv(8); | ||
290 | Ser4SSCR1 = SSCR1_SClkIactL + SSCR1_SClk1P + SSCR1_ExtClk; | ||
291 | Ser4SSCR0 |= SSCR0_SSE; | ||
292 | local_irq_restore(flags); | ||
293 | |||
294 | /* Enable the audio power */ | ||
295 | |||
296 | clr_sa11xx_uda1341_egpio(IPAQ_EGPIO_CODEC_NRESET); | ||
297 | set_sa11xx_uda1341_egpio(IPAQ_EGPIO_AUDIO_ON); | ||
298 | set_sa11xx_uda1341_egpio(IPAQ_EGPIO_QMUTE); | ||
299 | |||
300 | /* Wait for the UDA1341 to wake up */ | ||
301 | mdelay(1); //FIXME - was removed by Perex - Why? | ||
302 | |||
303 | /* Initialize the UDA1341 internal state */ | ||
304 | l3_open(sa11xx_uda1341->uda1341); | ||
305 | |||
306 | /* external clock configuration (after l3_open - regs must be initialized */ | ||
307 | sa11xx_uda1341_set_samplerate(sa11xx_uda1341, sa11xx_uda1341->samplerate); | ||
308 | |||
309 | /* Wait for the UDA1341 to wake up */ | ||
310 | set_sa11xx_uda1341_egpio(IPAQ_EGPIO_CODEC_NRESET); | ||
311 | mdelay(1); | ||
312 | |||
313 | /* make the left and right channels unswapped (flip the WS latch) */ | ||
314 | Ser4SSDR = 0; | ||
315 | |||
316 | clr_sa11xx_uda1341_egpio(IPAQ_EGPIO_QMUTE); | ||
317 | } | ||
318 | |||
319 | static void sa11xx_uda1341_audio_shutdown(struct sa11xx_uda1341 *sa11xx_uda1341) | ||
320 | { | ||
321 | /* mute on */ | ||
322 | set_sa11xx_uda1341_egpio(IPAQ_EGPIO_QMUTE); | ||
323 | |||
324 | /* disable the audio power and all signals leading to the audio chip */ | ||
325 | l3_close(sa11xx_uda1341->uda1341); | ||
326 | Ser4SSCR0 = 0; | ||
327 | clr_sa11xx_uda1341_egpio(IPAQ_EGPIO_CODEC_NRESET); | ||
328 | |||
329 | /* power off and mute off */ | ||
330 | /* FIXME - is muting off necesary??? */ | ||
331 | |||
332 | clr_sa11xx_uda1341_egpio(IPAQ_EGPIO_AUDIO_ON); | ||
333 | clr_sa11xx_uda1341_egpio(IPAQ_EGPIO_QMUTE); | ||
334 | } | ||
335 | |||
336 | /* }}} */ | ||
337 | |||
338 | /* {{{ DMA staff */ | ||
339 | |||
340 | /* | ||
341 | * these are the address and sizes used to fill the xmit buffer | ||
342 | * so we can get a clock in record only mode | ||
343 | */ | ||
344 | #define FORCE_CLOCK_ADDR (dma_addr_t)FLUSH_BASE_PHYS | ||
345 | #define FORCE_CLOCK_SIZE 4096 // was 2048 | ||
346 | |||
347 | // FIXME Why this value exactly - wrote comment | ||
348 | #define DMA_BUF_SIZE 8176 /* <= MAX_DMA_SIZE from asm/arch-sa1100/dma.h */ | ||
349 | |||
350 | #ifdef HH_VERSION | ||
351 | |||
352 | static int audio_dma_request(struct audio_stream *s, void (*callback)(void *, int)) | ||
353 | { | ||
354 | int ret; | ||
355 | |||
356 | ret = sa1100_request_dma(&s->dmach, s->id, s->dma_dev); | ||
357 | if (ret < 0) { | ||
358 | printk(KERN_ERR "unable to grab audio dma 0x%x\n", s->dma_dev); | ||
359 | return ret; | ||
360 | } | ||
361 | sa1100_dma_set_callback(s->dmach, callback); | ||
362 | return 0; | ||
363 | } | ||
364 | |||
365 | static inline void audio_dma_free(struct audio_stream *s) | ||
366 | { | ||
367 | sa1100_free_dma(s->dmach); | ||
368 | s->dmach = -1; | ||
369 | } | ||
370 | |||
371 | #else | ||
372 | |||
373 | static int audio_dma_request(struct audio_stream *s, void (*callback)(void *)) | ||
374 | { | ||
375 | int ret; | ||
376 | |||
377 | ret = sa1100_request_dma(s->dma_dev, s->id, callback, s, &s->dma_regs); | ||
378 | if (ret < 0) | ||
379 | printk(KERN_ERR "unable to grab audio dma 0x%x\n", s->dma_dev); | ||
380 | return ret; | ||
381 | } | ||
382 | |||
383 | static void audio_dma_free(struct audio_stream *s) | ||
384 | { | ||
385 | sa1100_free_dma(s->dma_regs); | ||
386 | s->dma_regs = 0; | ||
387 | } | ||
388 | |||
389 | #endif | ||
390 | |||
391 | static u_int audio_get_dma_pos(struct audio_stream *s) | ||
392 | { | ||
393 | struct snd_pcm_substream *substream = s->stream; | ||
394 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
395 | unsigned int offset; | ||
396 | unsigned long flags; | ||
397 | dma_addr_t addr; | ||
398 | |||
399 | // this must be called w/ interrupts locked out see dma-sa1100.c in the kernel | ||
400 | spin_lock_irqsave(&s->dma_lock, flags); | ||
401 | #ifdef HH_VERSION | ||
402 | sa1100_dma_get_current(s->dmach, NULL, &addr); | ||
403 | #else | ||
404 | addr = sa1100_get_dma_pos((s)->dma_regs); | ||
405 | #endif | ||
406 | offset = addr - runtime->dma_addr; | ||
407 | spin_unlock_irqrestore(&s->dma_lock, flags); | ||
408 | |||
409 | offset = bytes_to_frames(runtime,offset); | ||
410 | if (offset >= runtime->buffer_size) | ||
411 | offset = 0; | ||
412 | |||
413 | return offset; | ||
414 | } | ||
415 | |||
416 | /* | ||
417 | * this stops the dma and clears the dma ptrs | ||
418 | */ | ||
419 | static void audio_stop_dma(struct audio_stream *s) | ||
420 | { | ||
421 | unsigned long flags; | ||
422 | |||
423 | spin_lock_irqsave(&s->dma_lock, flags); | ||
424 | s->active = 0; | ||
425 | s->period = 0; | ||
426 | /* this stops the dma channel and clears the buffer ptrs */ | ||
427 | #ifdef HH_VERSION | ||
428 | sa1100_dma_flush_all(s->dmach); | ||
429 | #else | ||
430 | sa1100_clear_dma(s->dma_regs); | ||
431 | #endif | ||
432 | spin_unlock_irqrestore(&s->dma_lock, flags); | ||
433 | } | ||
434 | |||
435 | static void audio_process_dma(struct audio_stream *s) | ||
436 | { | ||
437 | struct snd_pcm_substream *substream = s->stream; | ||
438 | struct snd_pcm_runtime *runtime; | ||
439 | unsigned int dma_size; | ||
440 | unsigned int offset; | ||
441 | int ret; | ||
442 | |||
443 | /* we are requested to process synchronization DMA transfer */ | ||
444 | if (s->tx_spin) { | ||
445 | if (snd_BUG_ON(s->stream_id != SNDRV_PCM_STREAM_PLAYBACK)) | ||
446 | return; | ||
447 | /* fill the xmit dma buffers and return */ | ||
448 | #ifdef HH_VERSION | ||
449 | sa1100_dma_set_spin(s->dmach, FORCE_CLOCK_ADDR, FORCE_CLOCK_SIZE); | ||
450 | #else | ||
451 | while (1) { | ||
452 | ret = sa1100_start_dma(s->dma_regs, FORCE_CLOCK_ADDR, FORCE_CLOCK_SIZE); | ||
453 | if (ret) | ||
454 | return; | ||
455 | } | ||
456 | #endif | ||
457 | return; | ||
458 | } | ||
459 | |||
460 | /* must be set here - only valid for running streams, not for forced_clock dma fills */ | ||
461 | runtime = substream->runtime; | ||
462 | while (s->active && s->periods < runtime->periods) { | ||
463 | dma_size = frames_to_bytes(runtime, runtime->period_size); | ||
464 | if (s->old_offset) { | ||
465 | /* a little trick, we need resume from old position */ | ||
466 | offset = frames_to_bytes(runtime, s->old_offset - 1); | ||
467 | s->old_offset = 0; | ||
468 | s->periods = 0; | ||
469 | s->period = offset / dma_size; | ||
470 | offset %= dma_size; | ||
471 | dma_size = dma_size - offset; | ||
472 | if (!dma_size) | ||
473 | continue; /* special case */ | ||
474 | } else { | ||
475 | offset = dma_size * s->period; | ||
476 | snd_BUG_ON(dma_size > DMA_BUF_SIZE); | ||
477 | } | ||
478 | #ifdef HH_VERSION | ||
479 | ret = sa1100_dma_queue_buffer(s->dmach, s, runtime->dma_addr + offset, dma_size); | ||
480 | if (ret) | ||
481 | return; //FIXME | ||
482 | #else | ||
483 | ret = sa1100_start_dma((s)->dma_regs, runtime->dma_addr + offset, dma_size); | ||
484 | if (ret) { | ||
485 | printk(KERN_ERR "audio_process_dma: cannot queue DMA buffer (%i)\n", ret); | ||
486 | return; | ||
487 | } | ||
488 | #endif | ||
489 | |||
490 | s->period++; | ||
491 | s->period %= runtime->periods; | ||
492 | s->periods++; | ||
493 | } | ||
494 | } | ||
495 | |||
496 | #ifdef HH_VERSION | ||
497 | static void audio_dma_callback(void *data, int size) | ||
498 | #else | ||
499 | static void audio_dma_callback(void *data) | ||
500 | #endif | ||
501 | { | ||
502 | struct audio_stream *s = data; | ||
503 | |||
504 | /* | ||
505 | * If we are getting a callback for an active stream then we inform | ||
506 | * the PCM middle layer we've finished a period | ||
507 | */ | ||
508 | if (s->active) | ||
509 | snd_pcm_period_elapsed(s->stream); | ||
510 | |||
511 | spin_lock(&s->dma_lock); | ||
512 | if (!s->tx_spin && s->periods > 0) | ||
513 | s->periods--; | ||
514 | audio_process_dma(s); | ||
515 | spin_unlock(&s->dma_lock); | ||
516 | } | ||
517 | |||
518 | /* }}} */ | ||
519 | |||
520 | /* {{{ PCM setting */ | ||
521 | |||
522 | /* {{{ trigger & timer */ | ||
523 | |||
524 | static int snd_sa11xx_uda1341_trigger(struct snd_pcm_substream *substream, int cmd) | ||
525 | { | ||
526 | struct sa11xx_uda1341 *chip = snd_pcm_substream_chip(substream); | ||
527 | int stream_id = substream->pstr->stream; | ||
528 | struct audio_stream *s = &chip->s[stream_id]; | ||
529 | struct audio_stream *s1 = &chip->s[stream_id ^ 1]; | ||
530 | int err = 0; | ||
531 | |||
532 | /* note local interrupts are already disabled in the midlevel code */ | ||
533 | spin_lock(&s->dma_lock); | ||
534 | switch (cmd) { | ||
535 | case SNDRV_PCM_TRIGGER_START: | ||
536 | /* now we need to make sure a record only stream has a clock */ | ||
537 | if (stream_id == SNDRV_PCM_STREAM_CAPTURE && !s1->active) { | ||
538 | /* we need to force fill the xmit DMA with zeros */ | ||
539 | s1->tx_spin = 1; | ||
540 | audio_process_dma(s1); | ||
541 | } | ||
542 | /* this case is when you were recording then you turn on a | ||
543 | * playback stream so we stop (also clears it) the dma first, | ||
544 | * clear the sync flag and then we let it turned on | ||
545 | */ | ||
546 | else { | ||
547 | s->tx_spin = 0; | ||
548 | } | ||
549 | |||
550 | /* requested stream startup */ | ||
551 | s->active = 1; | ||
552 | audio_process_dma(s); | ||
553 | break; | ||
554 | case SNDRV_PCM_TRIGGER_STOP: | ||
555 | /* requested stream shutdown */ | ||
556 | audio_stop_dma(s); | ||
557 | |||
558 | /* | ||
559 | * now we need to make sure a record only stream has a clock | ||
560 | * so if we're stopping a playback with an active capture | ||
561 | * we need to turn the 0 fill dma on for the xmit side | ||
562 | */ | ||
563 | if (stream_id == SNDRV_PCM_STREAM_PLAYBACK && s1->active) { | ||
564 | /* we need to force fill the xmit DMA with zeros */ | ||
565 | s->tx_spin = 1; | ||
566 | audio_process_dma(s); | ||
567 | } | ||
568 | /* | ||
569 | * we killed a capture only stream, so we should also kill | ||
570 | * the zero fill transmit | ||
571 | */ | ||
572 | else { | ||
573 | if (s1->tx_spin) { | ||
574 | s1->tx_spin = 0; | ||
575 | audio_stop_dma(s1); | ||
576 | } | ||
577 | } | ||
578 | |||
579 | break; | ||
580 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
581 | s->active = 0; | ||
582 | #ifdef HH_VERSION | ||
583 | sa1100_dma_stop(s->dmach); | ||
584 | #else | ||
585 | //FIXME - DMA API | ||
586 | #endif | ||
587 | s->old_offset = audio_get_dma_pos(s) + 1; | ||
588 | #ifdef HH_VERSION | ||
589 | sa1100_dma_flush_all(s->dmach); | ||
590 | #else | ||
591 | //FIXME - DMA API | ||
592 | #endif | ||
593 | s->periods = 0; | ||
594 | break; | ||
595 | case SNDRV_PCM_TRIGGER_RESUME: | ||
596 | s->active = 1; | ||
597 | s->tx_spin = 0; | ||
598 | audio_process_dma(s); | ||
599 | if (stream_id == SNDRV_PCM_STREAM_CAPTURE && !s1->active) { | ||
600 | s1->tx_spin = 1; | ||
601 | audio_process_dma(s1); | ||
602 | } | ||
603 | break; | ||
604 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
605 | #ifdef HH_VERSION | ||
606 | sa1100_dma_stop(s->dmach); | ||
607 | #else | ||
608 | //FIXME - DMA API | ||
609 | #endif | ||
610 | s->active = 0; | ||
611 | if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) { | ||
612 | if (s1->active) { | ||
613 | s->tx_spin = 1; | ||
614 | s->old_offset = audio_get_dma_pos(s) + 1; | ||
615 | #ifdef HH_VERSION | ||
616 | sa1100_dma_flush_all(s->dmach); | ||
617 | #else | ||
618 | //FIXME - DMA API | ||
619 | #endif | ||
620 | audio_process_dma(s); | ||
621 | } | ||
622 | } else { | ||
623 | if (s1->tx_spin) { | ||
624 | s1->tx_spin = 0; | ||
625 | #ifdef HH_VERSION | ||
626 | sa1100_dma_flush_all(s1->dmach); | ||
627 | #else | ||
628 | //FIXME - DMA API | ||
629 | #endif | ||
630 | } | ||
631 | } | ||
632 | break; | ||
633 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
634 | s->active = 1; | ||
635 | if (s->old_offset) { | ||
636 | s->tx_spin = 0; | ||
637 | audio_process_dma(s); | ||
638 | break; | ||
639 | } | ||
640 | if (stream_id == SNDRV_PCM_STREAM_CAPTURE && !s1->active) { | ||
641 | s1->tx_spin = 1; | ||
642 | audio_process_dma(s1); | ||
643 | } | ||
644 | #ifdef HH_VERSION | ||
645 | sa1100_dma_resume(s->dmach); | ||
646 | #else | ||
647 | //FIXME - DMA API | ||
648 | #endif | ||
649 | break; | ||
650 | default: | ||
651 | err = -EINVAL; | ||
652 | break; | ||
653 | } | ||
654 | spin_unlock(&s->dma_lock); | ||
655 | return err; | ||
656 | } | ||
657 | |||
658 | static int snd_sa11xx_uda1341_prepare(struct snd_pcm_substream *substream) | ||
659 | { | ||
660 | struct sa11xx_uda1341 *chip = snd_pcm_substream_chip(substream); | ||
661 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
662 | struct audio_stream *s = &chip->s[substream->pstr->stream]; | ||
663 | |||
664 | /* set requested samplerate */ | ||
665 | sa11xx_uda1341_set_samplerate(chip, runtime->rate); | ||
666 | |||
667 | /* set requestd format when available */ | ||
668 | /* set FMT here !!! FIXME */ | ||
669 | |||
670 | s->period = 0; | ||
671 | s->periods = 0; | ||
672 | |||
673 | return 0; | ||
674 | } | ||
675 | |||
676 | static snd_pcm_uframes_t snd_sa11xx_uda1341_pointer(struct snd_pcm_substream *substream) | ||
677 | { | ||
678 | struct sa11xx_uda1341 *chip = snd_pcm_substream_chip(substream); | ||
679 | return audio_get_dma_pos(&chip->s[substream->pstr->stream]); | ||
680 | } | ||
681 | |||
682 | /* }}} */ | ||
683 | |||
684 | static struct snd_pcm_hardware snd_sa11xx_uda1341_capture = | ||
685 | { | ||
686 | .info = (SNDRV_PCM_INFO_INTERLEAVED | | ||
687 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
688 | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | | ||
689 | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), | ||
690 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
691 | .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ | ||
692 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |\ | ||
693 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ | ||
694 | SNDRV_PCM_RATE_KNOT), | ||
695 | .rate_min = 8000, | ||
696 | .rate_max = 48000, | ||
697 | .channels_min = 2, | ||
698 | .channels_max = 2, | ||
699 | .buffer_bytes_max = 64*1024, | ||
700 | .period_bytes_min = 64, | ||
701 | .period_bytes_max = DMA_BUF_SIZE, | ||
702 | .periods_min = 2, | ||
703 | .periods_max = 255, | ||
704 | .fifo_size = 0, | ||
705 | }; | ||
706 | |||
707 | static struct snd_pcm_hardware snd_sa11xx_uda1341_playback = | ||
708 | { | ||
709 | .info = (SNDRV_PCM_INFO_INTERLEAVED | | ||
710 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
711 | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | | ||
712 | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), | ||
713 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
714 | .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ | ||
715 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |\ | ||
716 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ | ||
717 | SNDRV_PCM_RATE_KNOT), | ||
718 | .rate_min = 8000, | ||
719 | .rate_max = 48000, | ||
720 | .channels_min = 2, | ||
721 | .channels_max = 2, | ||
722 | .buffer_bytes_max = 64*1024, | ||
723 | .period_bytes_min = 64, | ||
724 | .period_bytes_max = DMA_BUF_SIZE, | ||
725 | .periods_min = 2, | ||
726 | .periods_max = 255, | ||
727 | .fifo_size = 0, | ||
728 | }; | ||
729 | |||
730 | static int snd_card_sa11xx_uda1341_open(struct snd_pcm_substream *substream) | ||
731 | { | ||
732 | struct sa11xx_uda1341 *chip = snd_pcm_substream_chip(substream); | ||
733 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
734 | int stream_id = substream->pstr->stream; | ||
735 | int err; | ||
736 | |||
737 | chip->s[stream_id].stream = substream; | ||
738 | |||
739 | if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) | ||
740 | runtime->hw = snd_sa11xx_uda1341_playback; | ||
741 | else | ||
742 | runtime->hw = snd_sa11xx_uda1341_capture; | ||
743 | if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) | ||
744 | return err; | ||
745 | if ((err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates)) < 0) | ||
746 | return err; | ||
747 | |||
748 | return 0; | ||
749 | } | ||
750 | |||
751 | static int snd_card_sa11xx_uda1341_close(struct snd_pcm_substream *substream) | ||
752 | { | ||
753 | struct sa11xx_uda1341 *chip = snd_pcm_substream_chip(substream); | ||
754 | |||
755 | chip->s[substream->pstr->stream].stream = NULL; | ||
756 | return 0; | ||
757 | } | ||
758 | |||
759 | /* {{{ HW params & free */ | ||
760 | |||
761 | static int snd_sa11xx_uda1341_hw_params(struct snd_pcm_substream *substream, | ||
762 | struct snd_pcm_hw_params *hw_params) | ||
763 | { | ||
764 | |||
765 | return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); | ||
766 | } | ||
767 | |||
768 | static int snd_sa11xx_uda1341_hw_free(struct snd_pcm_substream *substream) | ||
769 | { | ||
770 | return snd_pcm_lib_free_pages(substream); | ||
771 | } | ||
772 | |||
773 | /* }}} */ | ||
774 | |||
775 | static struct snd_pcm_ops snd_card_sa11xx_uda1341_playback_ops = { | ||
776 | .open = snd_card_sa11xx_uda1341_open, | ||
777 | .close = snd_card_sa11xx_uda1341_close, | ||
778 | .ioctl = snd_pcm_lib_ioctl, | ||
779 | .hw_params = snd_sa11xx_uda1341_hw_params, | ||
780 | .hw_free = snd_sa11xx_uda1341_hw_free, | ||
781 | .prepare = snd_sa11xx_uda1341_prepare, | ||
782 | .trigger = snd_sa11xx_uda1341_trigger, | ||
783 | .pointer = snd_sa11xx_uda1341_pointer, | ||
784 | }; | ||
785 | |||
786 | static struct snd_pcm_ops snd_card_sa11xx_uda1341_capture_ops = { | ||
787 | .open = snd_card_sa11xx_uda1341_open, | ||
788 | .close = snd_card_sa11xx_uda1341_close, | ||
789 | .ioctl = snd_pcm_lib_ioctl, | ||
790 | .hw_params = snd_sa11xx_uda1341_hw_params, | ||
791 | .hw_free = snd_sa11xx_uda1341_hw_free, | ||
792 | .prepare = snd_sa11xx_uda1341_prepare, | ||
793 | .trigger = snd_sa11xx_uda1341_trigger, | ||
794 | .pointer = snd_sa11xx_uda1341_pointer, | ||
795 | }; | ||
796 | |||
797 | static int __init snd_card_sa11xx_uda1341_pcm(struct sa11xx_uda1341 *sa11xx_uda1341, int device) | ||
798 | { | ||
799 | struct snd_pcm *pcm; | ||
800 | int err; | ||
801 | |||
802 | if ((err = snd_pcm_new(sa11xx_uda1341->card, "UDA1341 PCM", device, 1, 1, &pcm)) < 0) | ||
803 | return err; | ||
804 | |||
805 | /* | ||
806 | * this sets up our initial buffers and sets the dma_type to isa. | ||
807 | * isa works but I'm not sure why (or if) it's the right choice | ||
808 | * this may be too large, trying it for now | ||
809 | */ | ||
810 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | ||
811 | snd_dma_isa_data(), | ||
812 | 64*1024, 64*1024); | ||
813 | |||
814 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_card_sa11xx_uda1341_playback_ops); | ||
815 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_card_sa11xx_uda1341_capture_ops); | ||
816 | pcm->private_data = sa11xx_uda1341; | ||
817 | pcm->info_flags = 0; | ||
818 | strcpy(pcm->name, "UDA1341 PCM"); | ||
819 | |||
820 | sa11xx_uda1341_audio_init(sa11xx_uda1341); | ||
821 | |||
822 | /* setup DMA controller */ | ||
823 | audio_dma_request(&sa11xx_uda1341->s[SNDRV_PCM_STREAM_PLAYBACK], audio_dma_callback); | ||
824 | audio_dma_request(&sa11xx_uda1341->s[SNDRV_PCM_STREAM_CAPTURE], audio_dma_callback); | ||
825 | |||
826 | sa11xx_uda1341->pcm = pcm; | ||
827 | |||
828 | return 0; | ||
829 | } | ||
830 | |||
831 | /* }}} */ | ||
832 | |||
833 | /* {{{ module init & exit */ | ||
834 | |||
835 | #ifdef CONFIG_PM | ||
836 | |||
837 | static int snd_sa11xx_uda1341_suspend(struct platform_device *devptr, | ||
838 | pm_message_t state) | ||
839 | { | ||
840 | struct snd_card *card = platform_get_drvdata(devptr); | ||
841 | struct sa11xx_uda1341 *chip = card->private_data; | ||
842 | |||
843 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | ||
844 | snd_pcm_suspend_all(chip->pcm); | ||
845 | #ifdef HH_VERSION | ||
846 | sa1100_dma_sleep(chip->s[SNDRV_PCM_STREAM_PLAYBACK].dmach); | ||
847 | sa1100_dma_sleep(chip->s[SNDRV_PCM_STREAM_CAPTURE].dmach); | ||
848 | #else | ||
849 | //FIXME | ||
850 | #endif | ||
851 | l3_command(chip->uda1341, CMD_SUSPEND, NULL); | ||
852 | sa11xx_uda1341_audio_shutdown(chip); | ||
853 | |||
854 | return 0; | ||
855 | } | ||
856 | |||
857 | static int snd_sa11xx_uda1341_resume(struct platform_device *devptr) | ||
858 | { | ||
859 | struct snd_card *card = platform_get_drvdata(devptr); | ||
860 | struct sa11xx_uda1341 *chip = card->private_data; | ||
861 | |||
862 | sa11xx_uda1341_audio_init(chip); | ||
863 | l3_command(chip->uda1341, CMD_RESUME, NULL); | ||
864 | #ifdef HH_VERSION | ||
865 | sa1100_dma_wakeup(chip->s[SNDRV_PCM_STREAM_PLAYBACK].dmach); | ||
866 | sa1100_dma_wakeup(chip->s[SNDRV_PCM_STREAM_CAPTURE].dmach); | ||
867 | #else | ||
868 | //FIXME | ||
869 | #endif | ||
870 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | ||
871 | return 0; | ||
872 | } | ||
873 | #endif /* COMFIG_PM */ | ||
874 | |||
875 | void snd_sa11xx_uda1341_free(struct snd_card *card) | ||
876 | { | ||
877 | struct sa11xx_uda1341 *chip = card->private_data; | ||
878 | |||
879 | audio_dma_free(&chip->s[SNDRV_PCM_STREAM_PLAYBACK]); | ||
880 | audio_dma_free(&chip->s[SNDRV_PCM_STREAM_CAPTURE]); | ||
881 | } | ||
882 | |||
883 | static int __devinit sa11xx_uda1341_probe(struct platform_device *devptr) | ||
884 | { | ||
885 | int err; | ||
886 | struct snd_card *card; | ||
887 | struct sa11xx_uda1341 *chip; | ||
888 | |||
889 | /* register the soundcard */ | ||
890 | card = snd_card_new(-1, id, THIS_MODULE, sizeof(struct sa11xx_uda1341)); | ||
891 | if (card == NULL) | ||
892 | return -ENOMEM; | ||
893 | |||
894 | chip = card->private_data; | ||
895 | spin_lock_init(&chip->s[0].dma_lock); | ||
896 | spin_lock_init(&chip->s[1].dma_lock); | ||
897 | |||
898 | card->private_free = snd_sa11xx_uda1341_free; | ||
899 | chip->card = card; | ||
900 | chip->samplerate = AUDIO_RATE_DEFAULT; | ||
901 | |||
902 | // mixer | ||
903 | if ((err = snd_chip_uda1341_mixer_new(card, &chip->uda1341))) | ||
904 | goto nodev; | ||
905 | |||
906 | // PCM | ||
907 | if ((err = snd_card_sa11xx_uda1341_pcm(chip, 0)) < 0) | ||
908 | goto nodev; | ||
909 | |||
910 | strcpy(card->driver, "UDA1341"); | ||
911 | strcpy(card->shortname, "H3600 UDA1341TS"); | ||
912 | sprintf(card->longname, "Compaq iPAQ H3600 with Philips UDA1341TS"); | ||
913 | |||
914 | snd_card_set_dev(card, &devptr->dev); | ||
915 | |||
916 | if ((err = snd_card_register(card)) == 0) { | ||
917 | printk( KERN_INFO "iPAQ audio support initialized\n" ); | ||
918 | platform_set_drvdata(devptr, card); | ||
919 | return 0; | ||
920 | } | ||
921 | |||
922 | nodev: | ||
923 | snd_card_free(card); | ||
924 | return err; | ||
925 | } | ||
926 | |||
927 | static int __devexit sa11xx_uda1341_remove(struct platform_device *devptr) | ||
928 | { | ||
929 | snd_card_free(platform_get_drvdata(devptr)); | ||
930 | platform_set_drvdata(devptr, NULL); | ||
931 | return 0; | ||
932 | } | ||
933 | |||
934 | #define SA11XX_UDA1341_DRIVER "sa11xx_uda1341" | ||
935 | |||
936 | static struct platform_driver sa11xx_uda1341_driver = { | ||
937 | .probe = sa11xx_uda1341_probe, | ||
938 | .remove = __devexit_p(sa11xx_uda1341_remove), | ||
939 | #ifdef CONFIG_PM | ||
940 | .suspend = snd_sa11xx_uda1341_suspend, | ||
941 | .resume = snd_sa11xx_uda1341_resume, | ||
942 | #endif | ||
943 | .driver = { | ||
944 | .name = SA11XX_UDA1341_DRIVER, | ||
945 | }, | ||
946 | }; | ||
947 | |||
948 | static int __init sa11xx_uda1341_init(void) | ||
949 | { | ||
950 | int err; | ||
951 | |||
952 | if (!machine_is_h3xxx()) | ||
953 | return -ENODEV; | ||
954 | if ((err = platform_driver_register(&sa11xx_uda1341_driver)) < 0) | ||
955 | return err; | ||
956 | device = platform_device_register_simple(SA11XX_UDA1341_DRIVER, -1, NULL, 0); | ||
957 | if (!IS_ERR(device)) { | ||
958 | if (platform_get_drvdata(device)) | ||
959 | return 0; | ||
960 | platform_device_unregister(device); | ||
961 | err = -ENODEV; | ||
962 | } else | ||
963 | err = PTR_ERR(device); | ||
964 | platform_driver_unregister(&sa11xx_uda1341_driver); | ||
965 | return err; | ||
966 | } | ||
967 | |||
968 | static void __exit sa11xx_uda1341_exit(void) | ||
969 | { | ||
970 | platform_device_unregister(device); | ||
971 | platform_driver_unregister(&sa11xx_uda1341_driver); | ||
972 | } | ||
973 | |||
974 | module_init(sa11xx_uda1341_init); | ||
975 | module_exit(sa11xx_uda1341_exit); | ||
976 | |||
977 | /* }}} */ | ||
978 | |||
979 | /* | ||
980 | * Local variables: | ||
981 | * indent-tabs-mode: t | ||
982 | * End: | ||
983 | */ | ||
diff --git a/sound/atmel/Kconfig b/sound/atmel/Kconfig new file mode 100644 index 000000000000..6c228a91940d --- /dev/null +++ b/sound/atmel/Kconfig | |||
@@ -0,0 +1,19 @@ | |||
1 | menu "Atmel devices (AVR32 and AT91)" | ||
2 | depends on AVR32 || ARCH_AT91 | ||
3 | |||
4 | config SND_ATMEL_ABDAC | ||
5 | tristate "Atmel Audio Bitstream DAC (ABDAC) driver" | ||
6 | select SND_PCM | ||
7 | depends on DW_DMAC && AVR32 | ||
8 | help | ||
9 | ALSA sound driver for the Atmel Audio Bitstream DAC (ABDAC). | ||
10 | |||
11 | config SND_ATMEL_AC97C | ||
12 | tristate "Atmel AC97 Controller (AC97C) driver" | ||
13 | select SND_PCM | ||
14 | select SND_AC97_CODEC | ||
15 | depends on DW_DMAC && AVR32 | ||
16 | help | ||
17 | ALSA sound driver for the Atmel AC97 controller. | ||
18 | |||
19 | endmenu | ||
diff --git a/sound/atmel/Makefile b/sound/atmel/Makefile new file mode 100644 index 000000000000..219dcfac6086 --- /dev/null +++ b/sound/atmel/Makefile | |||
@@ -0,0 +1,5 @@ | |||
1 | snd-atmel-abdac-objs := abdac.o | ||
2 | snd-atmel-ac97c-objs := ac97c.o | ||
3 | |||
4 | obj-$(CONFIG_SND_ATMEL_ABDAC) += snd-atmel-abdac.o | ||
5 | obj-$(CONFIG_SND_ATMEL_AC97C) += snd-atmel-ac97c.o | ||
diff --git a/sound/atmel/abdac.c b/sound/atmel/abdac.c new file mode 100644 index 000000000000..28b3c7f7cfe6 --- /dev/null +++ b/sound/atmel/abdac.c | |||
@@ -0,0 +1,602 @@ | |||
1 | /* | ||
2 | * Driver for the Atmel on-chip Audio Bitstream DAC (ABDAC) | ||
3 | * | ||
4 | * Copyright (C) 2006-2009 Atmel Corporation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License version 2 as published by | ||
8 | * the Free Software Foundation. | ||
9 | */ | ||
10 | #include <linux/clk.h> | ||
11 | #include <linux/bitmap.h> | ||
12 | #include <linux/dw_dmac.h> | ||
13 | #include <linux/dmaengine.h> | ||
14 | #include <linux/dma-mapping.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/io.h> | ||
20 | |||
21 | #include <sound/core.h> | ||
22 | #include <sound/initval.h> | ||
23 | #include <sound/pcm.h> | ||
24 | #include <sound/pcm_params.h> | ||
25 | #include <sound/atmel-abdac.h> | ||
26 | |||
27 | /* DAC register offsets */ | ||
28 | #define DAC_DATA 0x0000 | ||
29 | #define DAC_CTRL 0x0008 | ||
30 | #define DAC_INT_MASK 0x000c | ||
31 | #define DAC_INT_EN 0x0010 | ||
32 | #define DAC_INT_DIS 0x0014 | ||
33 | #define DAC_INT_CLR 0x0018 | ||
34 | #define DAC_INT_STATUS 0x001c | ||
35 | |||
36 | /* Bitfields in CTRL */ | ||
37 | #define DAC_SWAP_OFFSET 30 | ||
38 | #define DAC_SWAP_SIZE 1 | ||
39 | #define DAC_EN_OFFSET 31 | ||
40 | #define DAC_EN_SIZE 1 | ||
41 | |||
42 | /* Bitfields in INT_MASK/INT_EN/INT_DIS/INT_STATUS/INT_CLR */ | ||
43 | #define DAC_UNDERRUN_OFFSET 28 | ||
44 | #define DAC_UNDERRUN_SIZE 1 | ||
45 | #define DAC_TX_READY_OFFSET 29 | ||
46 | #define DAC_TX_READY_SIZE 1 | ||
47 | |||
48 | /* Bit manipulation macros */ | ||
49 | #define DAC_BIT(name) \ | ||
50 | (1 << DAC_##name##_OFFSET) | ||
51 | #define DAC_BF(name, value) \ | ||
52 | (((value) & ((1 << DAC_##name##_SIZE) - 1)) \ | ||
53 | << DAC_##name##_OFFSET) | ||
54 | #define DAC_BFEXT(name, value) \ | ||
55 | (((value) >> DAC_##name##_OFFSET) \ | ||
56 | & ((1 << DAC_##name##_SIZE) - 1)) | ||
57 | #define DAC_BFINS(name, value, old) \ | ||
58 | (((old) & ~(((1 << DAC_##name##_SIZE) - 1) \ | ||
59 | << DAC_##name##_OFFSET)) \ | ||
60 | | DAC_BF(name, value)) | ||
61 | |||
62 | /* Register access macros */ | ||
63 | #define dac_readl(port, reg) \ | ||
64 | __raw_readl((port)->regs + DAC_##reg) | ||
65 | #define dac_writel(port, reg, value) \ | ||
66 | __raw_writel((value), (port)->regs + DAC_##reg) | ||
67 | |||
68 | /* | ||
69 | * ABDAC supports a maximum of 6 different rates from a generic clock. The | ||
70 | * generic clock has a power of two divider, which gives 6 steps from 192 kHz | ||
71 | * to 5112 Hz. | ||
72 | */ | ||
73 | #define MAX_NUM_RATES 6 | ||
74 | /* ALSA seems to use rates between 192000 Hz and 5112 Hz. */ | ||
75 | #define RATE_MAX 192000 | ||
76 | #define RATE_MIN 5112 | ||
77 | |||
78 | enum { | ||
79 | DMA_READY = 0, | ||
80 | }; | ||
81 | |||
82 | struct atmel_abdac_dma { | ||
83 | struct dma_chan *chan; | ||
84 | struct dw_cyclic_desc *cdesc; | ||
85 | }; | ||
86 | |||
87 | struct atmel_abdac { | ||
88 | struct clk *pclk; | ||
89 | struct clk *sample_clk; | ||
90 | struct platform_device *pdev; | ||
91 | struct atmel_abdac_dma dma; | ||
92 | |||
93 | struct snd_pcm_hw_constraint_list constraints_rates; | ||
94 | struct snd_pcm_substream *substream; | ||
95 | struct snd_card *card; | ||
96 | struct snd_pcm *pcm; | ||
97 | |||
98 | void __iomem *regs; | ||
99 | unsigned long flags; | ||
100 | unsigned int rates[MAX_NUM_RATES]; | ||
101 | unsigned int rates_num; | ||
102 | int irq; | ||
103 | }; | ||
104 | |||
105 | #define get_dac(card) ((struct atmel_abdac *)(card)->private_data) | ||
106 | |||
107 | /* This function is called by the DMA driver. */ | ||
108 | static void atmel_abdac_dma_period_done(void *arg) | ||
109 | { | ||
110 | struct atmel_abdac *dac = arg; | ||
111 | snd_pcm_period_elapsed(dac->substream); | ||
112 | } | ||
113 | |||
114 | static int atmel_abdac_prepare_dma(struct atmel_abdac *dac, | ||
115 | struct snd_pcm_substream *substream, | ||
116 | enum dma_data_direction direction) | ||
117 | { | ||
118 | struct dma_chan *chan = dac->dma.chan; | ||
119 | struct dw_cyclic_desc *cdesc; | ||
120 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
121 | unsigned long buffer_len, period_len; | ||
122 | |||
123 | /* | ||
124 | * We don't do DMA on "complex" transfers, i.e. with | ||
125 | * non-halfword-aligned buffers or lengths. | ||
126 | */ | ||
127 | if (runtime->dma_addr & 1 || runtime->buffer_size & 1) { | ||
128 | dev_dbg(&dac->pdev->dev, "too complex transfer\n"); | ||
129 | return -EINVAL; | ||
130 | } | ||
131 | |||
132 | buffer_len = frames_to_bytes(runtime, runtime->buffer_size); | ||
133 | period_len = frames_to_bytes(runtime, runtime->period_size); | ||
134 | |||
135 | cdesc = dw_dma_cyclic_prep(chan, runtime->dma_addr, buffer_len, | ||
136 | period_len, DMA_TO_DEVICE); | ||
137 | if (IS_ERR(cdesc)) { | ||
138 | dev_dbg(&dac->pdev->dev, "could not prepare cyclic DMA\n"); | ||
139 | return PTR_ERR(cdesc); | ||
140 | } | ||
141 | |||
142 | cdesc->period_callback = atmel_abdac_dma_period_done; | ||
143 | cdesc->period_callback_param = dac; | ||
144 | |||
145 | dac->dma.cdesc = cdesc; | ||
146 | |||
147 | set_bit(DMA_READY, &dac->flags); | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | static struct snd_pcm_hardware atmel_abdac_hw = { | ||
153 | .info = (SNDRV_PCM_INFO_MMAP | ||
154 | | SNDRV_PCM_INFO_MMAP_VALID | ||
155 | | SNDRV_PCM_INFO_INTERLEAVED | ||
156 | | SNDRV_PCM_INFO_BLOCK_TRANSFER | ||
157 | | SNDRV_PCM_INFO_RESUME | ||
158 | | SNDRV_PCM_INFO_PAUSE), | ||
159 | .formats = (SNDRV_PCM_FMTBIT_S16_BE), | ||
160 | .rates = (SNDRV_PCM_RATE_KNOT), | ||
161 | .rate_min = RATE_MIN, | ||
162 | .rate_max = RATE_MAX, | ||
163 | .channels_min = 2, | ||
164 | .channels_max = 2, | ||
165 | .buffer_bytes_max = 64 * 4096, | ||
166 | .period_bytes_min = 4096, | ||
167 | .period_bytes_max = 4096, | ||
168 | .periods_min = 4, | ||
169 | .periods_max = 64, | ||
170 | }; | ||
171 | |||
172 | static int atmel_abdac_open(struct snd_pcm_substream *substream) | ||
173 | { | ||
174 | struct atmel_abdac *dac = snd_pcm_substream_chip(substream); | ||
175 | |||
176 | dac->substream = substream; | ||
177 | atmel_abdac_hw.rate_max = dac->rates[dac->rates_num - 1]; | ||
178 | atmel_abdac_hw.rate_min = dac->rates[0]; | ||
179 | substream->runtime->hw = atmel_abdac_hw; | ||
180 | |||
181 | return snd_pcm_hw_constraint_list(substream->runtime, 0, | ||
182 | SNDRV_PCM_HW_PARAM_RATE, &dac->constraints_rates); | ||
183 | } | ||
184 | |||
185 | static int atmel_abdac_close(struct snd_pcm_substream *substream) | ||
186 | { | ||
187 | struct atmel_abdac *dac = snd_pcm_substream_chip(substream); | ||
188 | dac->substream = NULL; | ||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | static int atmel_abdac_hw_params(struct snd_pcm_substream *substream, | ||
193 | struct snd_pcm_hw_params *hw_params) | ||
194 | { | ||
195 | struct atmel_abdac *dac = snd_pcm_substream_chip(substream); | ||
196 | int retval; | ||
197 | |||
198 | retval = snd_pcm_lib_malloc_pages(substream, | ||
199 | params_buffer_bytes(hw_params)); | ||
200 | if (retval < 0) | ||
201 | return retval; | ||
202 | /* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */ | ||
203 | if (retval == 1) | ||
204 | if (test_and_clear_bit(DMA_READY, &dac->flags)) | ||
205 | dw_dma_cyclic_free(dac->dma.chan); | ||
206 | |||
207 | return retval; | ||
208 | } | ||
209 | |||
210 | static int atmel_abdac_hw_free(struct snd_pcm_substream *substream) | ||
211 | { | ||
212 | struct atmel_abdac *dac = snd_pcm_substream_chip(substream); | ||
213 | if (test_and_clear_bit(DMA_READY, &dac->flags)) | ||
214 | dw_dma_cyclic_free(dac->dma.chan); | ||
215 | return snd_pcm_lib_free_pages(substream); | ||
216 | } | ||
217 | |||
218 | static int atmel_abdac_prepare(struct snd_pcm_substream *substream) | ||
219 | { | ||
220 | struct atmel_abdac *dac = snd_pcm_substream_chip(substream); | ||
221 | int retval; | ||
222 | |||
223 | retval = clk_set_rate(dac->sample_clk, 256 * substream->runtime->rate); | ||
224 | if (retval) | ||
225 | return retval; | ||
226 | |||
227 | if (!test_bit(DMA_READY, &dac->flags)) | ||
228 | retval = atmel_abdac_prepare_dma(dac, substream, DMA_TO_DEVICE); | ||
229 | |||
230 | return retval; | ||
231 | } | ||
232 | |||
233 | static int atmel_abdac_trigger(struct snd_pcm_substream *substream, int cmd) | ||
234 | { | ||
235 | struct atmel_abdac *dac = snd_pcm_substream_chip(substream); | ||
236 | int retval = 0; | ||
237 | |||
238 | switch (cmd) { | ||
239 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */ | ||
240 | case SNDRV_PCM_TRIGGER_RESUME: /* fall through */ | ||
241 | case SNDRV_PCM_TRIGGER_START: | ||
242 | clk_enable(dac->sample_clk); | ||
243 | retval = dw_dma_cyclic_start(dac->dma.chan); | ||
244 | if (retval) | ||
245 | goto out; | ||
246 | dac_writel(dac, CTRL, DAC_BIT(EN)); | ||
247 | break; | ||
248 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */ | ||
249 | case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */ | ||
250 | case SNDRV_PCM_TRIGGER_STOP: | ||
251 | dw_dma_cyclic_stop(dac->dma.chan); | ||
252 | dac_writel(dac, DATA, 0); | ||
253 | dac_writel(dac, CTRL, 0); | ||
254 | clk_disable(dac->sample_clk); | ||
255 | break; | ||
256 | default: | ||
257 | retval = -EINVAL; | ||
258 | break; | ||
259 | } | ||
260 | out: | ||
261 | return retval; | ||
262 | } | ||
263 | |||
264 | static snd_pcm_uframes_t | ||
265 | atmel_abdac_pointer(struct snd_pcm_substream *substream) | ||
266 | { | ||
267 | struct atmel_abdac *dac = snd_pcm_substream_chip(substream); | ||
268 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
269 | snd_pcm_uframes_t frames; | ||
270 | unsigned long bytes; | ||
271 | |||
272 | bytes = dw_dma_get_src_addr(dac->dma.chan); | ||
273 | bytes -= runtime->dma_addr; | ||
274 | |||
275 | frames = bytes_to_frames(runtime, bytes); | ||
276 | if (frames >= runtime->buffer_size) | ||
277 | frames -= runtime->buffer_size; | ||
278 | |||
279 | return frames; | ||
280 | } | ||
281 | |||
282 | static irqreturn_t abdac_interrupt(int irq, void *dev_id) | ||
283 | { | ||
284 | struct atmel_abdac *dac = dev_id; | ||
285 | u32 status; | ||
286 | |||
287 | status = dac_readl(dac, INT_STATUS); | ||
288 | if (status & DAC_BIT(UNDERRUN)) { | ||
289 | dev_err(&dac->pdev->dev, "underrun detected\n"); | ||
290 | dac_writel(dac, INT_CLR, DAC_BIT(UNDERRUN)); | ||
291 | } else { | ||
292 | dev_err(&dac->pdev->dev, "spurious interrupt (status=0x%x)\n", | ||
293 | status); | ||
294 | dac_writel(dac, INT_CLR, status); | ||
295 | } | ||
296 | |||
297 | return IRQ_HANDLED; | ||
298 | } | ||
299 | |||
300 | static struct snd_pcm_ops atmel_abdac_ops = { | ||
301 | .open = atmel_abdac_open, | ||
302 | .close = atmel_abdac_close, | ||
303 | .ioctl = snd_pcm_lib_ioctl, | ||
304 | .hw_params = atmel_abdac_hw_params, | ||
305 | .hw_free = atmel_abdac_hw_free, | ||
306 | .prepare = atmel_abdac_prepare, | ||
307 | .trigger = atmel_abdac_trigger, | ||
308 | .pointer = atmel_abdac_pointer, | ||
309 | }; | ||
310 | |||
311 | static int __devinit atmel_abdac_pcm_new(struct atmel_abdac *dac) | ||
312 | { | ||
313 | struct snd_pcm_hardware hw = atmel_abdac_hw; | ||
314 | struct snd_pcm *pcm; | ||
315 | int retval; | ||
316 | |||
317 | retval = snd_pcm_new(dac->card, dac->card->shortname, | ||
318 | dac->pdev->id, 1, 0, &pcm); | ||
319 | if (retval) | ||
320 | return retval; | ||
321 | |||
322 | strcpy(pcm->name, dac->card->shortname); | ||
323 | pcm->private_data = dac; | ||
324 | pcm->info_flags = 0; | ||
325 | dac->pcm = pcm; | ||
326 | |||
327 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &atmel_abdac_ops); | ||
328 | |||
329 | retval = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | ||
330 | &dac->pdev->dev, hw.periods_min * hw.period_bytes_min, | ||
331 | hw.buffer_bytes_max); | ||
332 | |||
333 | return retval; | ||
334 | } | ||
335 | |||
336 | static bool filter(struct dma_chan *chan, void *slave) | ||
337 | { | ||
338 | struct dw_dma_slave *dws = slave; | ||
339 | |||
340 | if (dws->dma_dev == chan->device->dev) { | ||
341 | chan->private = dws; | ||
342 | return true; | ||
343 | } else | ||
344 | return false; | ||
345 | } | ||
346 | |||
347 | static int set_sample_rates(struct atmel_abdac *dac) | ||
348 | { | ||
349 | long new_rate = RATE_MAX; | ||
350 | int retval = -EINVAL; | ||
351 | int index = 0; | ||
352 | |||
353 | /* we start at 192 kHz and work our way down to 5112 Hz */ | ||
354 | while (new_rate >= RATE_MIN && index < (MAX_NUM_RATES + 1)) { | ||
355 | new_rate = clk_round_rate(dac->sample_clk, 256 * new_rate); | ||
356 | if (new_rate < 0) | ||
357 | break; | ||
358 | /* make sure we are below the ABDAC clock */ | ||
359 | if (new_rate <= clk_get_rate(dac->pclk)) { | ||
360 | dac->rates[index] = new_rate / 256; | ||
361 | index++; | ||
362 | } | ||
363 | /* divide by 256 and then by two to get next rate */ | ||
364 | new_rate /= 256 * 2; | ||
365 | } | ||
366 | |||
367 | if (index) { | ||
368 | int i; | ||
369 | |||
370 | /* reverse array, smallest go first */ | ||
371 | for (i = 0; i < (index / 2); i++) { | ||
372 | unsigned int tmp = dac->rates[index - 1 - i]; | ||
373 | dac->rates[index - 1 - i] = dac->rates[i]; | ||
374 | dac->rates[i] = tmp; | ||
375 | } | ||
376 | |||
377 | dac->constraints_rates.count = index; | ||
378 | dac->constraints_rates.list = dac->rates; | ||
379 | dac->constraints_rates.mask = 0; | ||
380 | dac->rates_num = index; | ||
381 | |||
382 | retval = 0; | ||
383 | } | ||
384 | |||
385 | return retval; | ||
386 | } | ||
387 | |||
388 | static int __devinit atmel_abdac_probe(struct platform_device *pdev) | ||
389 | { | ||
390 | struct snd_card *card; | ||
391 | struct atmel_abdac *dac; | ||
392 | struct resource *regs; | ||
393 | struct atmel_abdac_pdata *pdata; | ||
394 | struct clk *pclk; | ||
395 | struct clk *sample_clk; | ||
396 | int retval; | ||
397 | int irq; | ||
398 | |||
399 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
400 | if (!regs) { | ||
401 | dev_dbg(&pdev->dev, "no memory resource\n"); | ||
402 | return -ENXIO; | ||
403 | } | ||
404 | |||
405 | irq = platform_get_irq(pdev, 0); | ||
406 | if (irq < 0) { | ||
407 | dev_dbg(&pdev->dev, "could not get IRQ number\n"); | ||
408 | return irq; | ||
409 | } | ||
410 | |||
411 | pdata = pdev->dev.platform_data; | ||
412 | if (!pdata) { | ||
413 | dev_dbg(&pdev->dev, "no platform data\n"); | ||
414 | return -ENXIO; | ||
415 | } | ||
416 | |||
417 | pclk = clk_get(&pdev->dev, "pclk"); | ||
418 | if (IS_ERR(pclk)) { | ||
419 | dev_dbg(&pdev->dev, "no peripheral clock\n"); | ||
420 | return PTR_ERR(pclk); | ||
421 | } | ||
422 | sample_clk = clk_get(&pdev->dev, "sample_clk"); | ||
423 | if (IS_ERR(pclk)) { | ||
424 | dev_dbg(&pdev->dev, "no sample clock\n"); | ||
425 | retval = PTR_ERR(pclk); | ||
426 | goto out_put_pclk; | ||
427 | } | ||
428 | clk_enable(pclk); | ||
429 | |||
430 | retval = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, | ||
431 | THIS_MODULE, sizeof(struct atmel_abdac), &card); | ||
432 | if (retval) { | ||
433 | dev_dbg(&pdev->dev, "could not create sound card device\n"); | ||
434 | goto out_put_sample_clk; | ||
435 | } | ||
436 | |||
437 | dac = get_dac(card); | ||
438 | |||
439 | dac->irq = irq; | ||
440 | dac->card = card; | ||
441 | dac->pclk = pclk; | ||
442 | dac->sample_clk = sample_clk; | ||
443 | dac->pdev = pdev; | ||
444 | |||
445 | retval = set_sample_rates(dac); | ||
446 | if (retval < 0) { | ||
447 | dev_dbg(&pdev->dev, "could not set supported rates\n"); | ||
448 | goto out_free_card; | ||
449 | } | ||
450 | |||
451 | dac->regs = ioremap(regs->start, regs->end - regs->start + 1); | ||
452 | if (!dac->regs) { | ||
453 | dev_dbg(&pdev->dev, "could not remap register memory\n"); | ||
454 | goto out_free_card; | ||
455 | } | ||
456 | |||
457 | /* make sure the DAC is silent and disabled */ | ||
458 | dac_writel(dac, DATA, 0); | ||
459 | dac_writel(dac, CTRL, 0); | ||
460 | |||
461 | retval = request_irq(irq, abdac_interrupt, 0, "abdac", dac); | ||
462 | if (retval) { | ||
463 | dev_dbg(&pdev->dev, "could not request irq\n"); | ||
464 | goto out_unmap_regs; | ||
465 | } | ||
466 | |||
467 | snd_card_set_dev(card, &pdev->dev); | ||
468 | |||
469 | if (pdata->dws.dma_dev) { | ||
470 | struct dw_dma_slave *dws = &pdata->dws; | ||
471 | dma_cap_mask_t mask; | ||
472 | |||
473 | dws->tx_reg = regs->start + DAC_DATA; | ||
474 | |||
475 | dma_cap_zero(mask); | ||
476 | dma_cap_set(DMA_SLAVE, mask); | ||
477 | |||
478 | dac->dma.chan = dma_request_channel(mask, filter, dws); | ||
479 | } | ||
480 | if (!pdata->dws.dma_dev || !dac->dma.chan) { | ||
481 | dev_dbg(&pdev->dev, "DMA not available\n"); | ||
482 | retval = -ENODEV; | ||
483 | goto out_unset_card_dev; | ||
484 | } | ||
485 | |||
486 | strcpy(card->driver, "Atmel ABDAC"); | ||
487 | strcpy(card->shortname, "Atmel ABDAC"); | ||
488 | sprintf(card->longname, "Atmel Audio Bitstream DAC"); | ||
489 | |||
490 | retval = atmel_abdac_pcm_new(dac); | ||
491 | if (retval) { | ||
492 | dev_dbg(&pdev->dev, "could not register ABDAC pcm device\n"); | ||
493 | goto out_release_dma; | ||
494 | } | ||
495 | |||
496 | retval = snd_card_register(card); | ||
497 | if (retval) { | ||
498 | dev_dbg(&pdev->dev, "could not register sound card\n"); | ||
499 | goto out_release_dma; | ||
500 | } | ||
501 | |||
502 | platform_set_drvdata(pdev, card); | ||
503 | |||
504 | dev_info(&pdev->dev, "Atmel ABDAC at 0x%p using %s\n", | ||
505 | dac->regs, dac->dma.chan->dev->device.bus_id); | ||
506 | |||
507 | return retval; | ||
508 | |||
509 | out_release_dma: | ||
510 | dma_release_channel(dac->dma.chan); | ||
511 | dac->dma.chan = NULL; | ||
512 | out_unset_card_dev: | ||
513 | snd_card_set_dev(card, NULL); | ||
514 | free_irq(irq, dac); | ||
515 | out_unmap_regs: | ||
516 | iounmap(dac->regs); | ||
517 | out_free_card: | ||
518 | snd_card_free(card); | ||
519 | out_put_sample_clk: | ||
520 | clk_put(sample_clk); | ||
521 | clk_disable(pclk); | ||
522 | out_put_pclk: | ||
523 | clk_put(pclk); | ||
524 | return retval; | ||
525 | } | ||
526 | |||
527 | #ifdef CONFIG_PM | ||
528 | static int atmel_abdac_suspend(struct platform_device *pdev, pm_message_t msg) | ||
529 | { | ||
530 | struct snd_card *card = platform_get_drvdata(pdev); | ||
531 | struct atmel_abdac *dac = card->private_data; | ||
532 | |||
533 | dw_dma_cyclic_stop(dac->dma.chan); | ||
534 | clk_disable(dac->sample_clk); | ||
535 | clk_disable(dac->pclk); | ||
536 | |||
537 | return 0; | ||
538 | } | ||
539 | |||
540 | static int atmel_abdac_resume(struct platform_device *pdev) | ||
541 | { | ||
542 | struct snd_card *card = platform_get_drvdata(pdev); | ||
543 | struct atmel_abdac *dac = card->private_data; | ||
544 | |||
545 | clk_enable(dac->pclk); | ||
546 | clk_enable(dac->sample_clk); | ||
547 | if (test_bit(DMA_READY, &dac->flags)) | ||
548 | dw_dma_cyclic_start(dac->dma.chan); | ||
549 | |||
550 | return 0; | ||
551 | } | ||
552 | #else | ||
553 | #define atmel_abdac_suspend NULL | ||
554 | #define atmel_abdac_resume NULL | ||
555 | #endif | ||
556 | |||
557 | static int __devexit atmel_abdac_remove(struct platform_device *pdev) | ||
558 | { | ||
559 | struct snd_card *card = platform_get_drvdata(pdev); | ||
560 | struct atmel_abdac *dac = get_dac(card); | ||
561 | |||
562 | clk_put(dac->sample_clk); | ||
563 | clk_disable(dac->pclk); | ||
564 | clk_put(dac->pclk); | ||
565 | |||
566 | dma_release_channel(dac->dma.chan); | ||
567 | dac->dma.chan = NULL; | ||
568 | snd_card_set_dev(card, NULL); | ||
569 | iounmap(dac->regs); | ||
570 | free_irq(dac->irq, dac); | ||
571 | snd_card_free(card); | ||
572 | |||
573 | platform_set_drvdata(pdev, NULL); | ||
574 | |||
575 | return 0; | ||
576 | } | ||
577 | |||
578 | static struct platform_driver atmel_abdac_driver = { | ||
579 | .remove = __devexit_p(atmel_abdac_remove), | ||
580 | .driver = { | ||
581 | .name = "atmel_abdac", | ||
582 | }, | ||
583 | .suspend = atmel_abdac_suspend, | ||
584 | .resume = atmel_abdac_resume, | ||
585 | }; | ||
586 | |||
587 | static int __init atmel_abdac_init(void) | ||
588 | { | ||
589 | return platform_driver_probe(&atmel_abdac_driver, | ||
590 | atmel_abdac_probe); | ||
591 | } | ||
592 | module_init(atmel_abdac_init); | ||
593 | |||
594 | static void __exit atmel_abdac_exit(void) | ||
595 | { | ||
596 | platform_driver_unregister(&atmel_abdac_driver); | ||
597 | } | ||
598 | module_exit(atmel_abdac_exit); | ||
599 | |||
600 | MODULE_LICENSE("GPL"); | ||
601 | MODULE_DESCRIPTION("Driver for Atmel Audio Bitstream DAC (ABDAC)"); | ||
602 | MODULE_AUTHOR("Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com>"); | ||
diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c new file mode 100644 index 000000000000..dd72e00e5ae1 --- /dev/null +++ b/sound/atmel/ac97c.c | |||
@@ -0,0 +1,932 @@ | |||
1 | /* | ||
2 | * Driver for the Atmel AC97C controller | ||
3 | * | ||
4 | * Copyright (C) 2005-2009 Atmel Corporation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License version 2 as published by | ||
8 | * the Free Software Foundation. | ||
9 | */ | ||
10 | #include <linux/clk.h> | ||
11 | #include <linux/delay.h> | ||
12 | #include <linux/bitmap.h> | ||
13 | #include <linux/dmaengine.h> | ||
14 | #include <linux/dma-mapping.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/mutex.h> | ||
20 | #include <linux/gpio.h> | ||
21 | #include <linux/io.h> | ||
22 | |||
23 | #include <sound/core.h> | ||
24 | #include <sound/initval.h> | ||
25 | #include <sound/pcm.h> | ||
26 | #include <sound/pcm_params.h> | ||
27 | #include <sound/ac97_codec.h> | ||
28 | #include <sound/atmel-ac97c.h> | ||
29 | #include <sound/memalloc.h> | ||
30 | |||
31 | #include <linux/dw_dmac.h> | ||
32 | |||
33 | #include "ac97c.h" | ||
34 | |||
35 | enum { | ||
36 | DMA_TX_READY = 0, | ||
37 | DMA_RX_READY, | ||
38 | DMA_TX_CHAN_PRESENT, | ||
39 | DMA_RX_CHAN_PRESENT, | ||
40 | }; | ||
41 | |||
42 | /* Serialize access to opened variable */ | ||
43 | static DEFINE_MUTEX(opened_mutex); | ||
44 | |||
45 | struct atmel_ac97c_dma { | ||
46 | struct dma_chan *rx_chan; | ||
47 | struct dma_chan *tx_chan; | ||
48 | }; | ||
49 | |||
50 | struct atmel_ac97c { | ||
51 | struct clk *pclk; | ||
52 | struct platform_device *pdev; | ||
53 | struct atmel_ac97c_dma dma; | ||
54 | |||
55 | struct snd_pcm_substream *playback_substream; | ||
56 | struct snd_pcm_substream *capture_substream; | ||
57 | struct snd_card *card; | ||
58 | struct snd_pcm *pcm; | ||
59 | struct snd_ac97 *ac97; | ||
60 | struct snd_ac97_bus *ac97_bus; | ||
61 | |||
62 | u64 cur_format; | ||
63 | unsigned int cur_rate; | ||
64 | unsigned long flags; | ||
65 | /* Serialize access to opened variable */ | ||
66 | spinlock_t lock; | ||
67 | void __iomem *regs; | ||
68 | int opened; | ||
69 | int reset_pin; | ||
70 | }; | ||
71 | |||
72 | #define get_chip(card) ((struct atmel_ac97c *)(card)->private_data) | ||
73 | |||
74 | #define ac97c_writel(chip, reg, val) \ | ||
75 | __raw_writel((val), (chip)->regs + AC97C_##reg) | ||
76 | #define ac97c_readl(chip, reg) \ | ||
77 | __raw_readl((chip)->regs + AC97C_##reg) | ||
78 | |||
79 | /* This function is called by the DMA driver. */ | ||
80 | static void atmel_ac97c_dma_playback_period_done(void *arg) | ||
81 | { | ||
82 | struct atmel_ac97c *chip = arg; | ||
83 | snd_pcm_period_elapsed(chip->playback_substream); | ||
84 | } | ||
85 | |||
86 | static void atmel_ac97c_dma_capture_period_done(void *arg) | ||
87 | { | ||
88 | struct atmel_ac97c *chip = arg; | ||
89 | snd_pcm_period_elapsed(chip->capture_substream); | ||
90 | } | ||
91 | |||
92 | static int atmel_ac97c_prepare_dma(struct atmel_ac97c *chip, | ||
93 | struct snd_pcm_substream *substream, | ||
94 | enum dma_data_direction direction) | ||
95 | { | ||
96 | struct dma_chan *chan; | ||
97 | struct dw_cyclic_desc *cdesc; | ||
98 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
99 | unsigned long buffer_len, period_len; | ||
100 | |||
101 | /* | ||
102 | * We don't do DMA on "complex" transfers, i.e. with | ||
103 | * non-halfword-aligned buffers or lengths. | ||
104 | */ | ||
105 | if (runtime->dma_addr & 1 || runtime->buffer_size & 1) { | ||
106 | dev_dbg(&chip->pdev->dev, "too complex transfer\n"); | ||
107 | return -EINVAL; | ||
108 | } | ||
109 | |||
110 | if (direction == DMA_TO_DEVICE) | ||
111 | chan = chip->dma.tx_chan; | ||
112 | else | ||
113 | chan = chip->dma.rx_chan; | ||
114 | |||
115 | buffer_len = frames_to_bytes(runtime, runtime->buffer_size); | ||
116 | period_len = frames_to_bytes(runtime, runtime->period_size); | ||
117 | |||
118 | cdesc = dw_dma_cyclic_prep(chan, runtime->dma_addr, buffer_len, | ||
119 | period_len, direction); | ||
120 | if (IS_ERR(cdesc)) { | ||
121 | dev_dbg(&chip->pdev->dev, "could not prepare cyclic DMA\n"); | ||
122 | return PTR_ERR(cdesc); | ||
123 | } | ||
124 | |||
125 | if (direction == DMA_TO_DEVICE) { | ||
126 | cdesc->period_callback = atmel_ac97c_dma_playback_period_done; | ||
127 | set_bit(DMA_TX_READY, &chip->flags); | ||
128 | } else { | ||
129 | cdesc->period_callback = atmel_ac97c_dma_capture_period_done; | ||
130 | set_bit(DMA_RX_READY, &chip->flags); | ||
131 | } | ||
132 | |||
133 | cdesc->period_callback_param = chip; | ||
134 | |||
135 | return 0; | ||
136 | } | ||
137 | |||
138 | static struct snd_pcm_hardware atmel_ac97c_hw = { | ||
139 | .info = (SNDRV_PCM_INFO_MMAP | ||
140 | | SNDRV_PCM_INFO_MMAP_VALID | ||
141 | | SNDRV_PCM_INFO_INTERLEAVED | ||
142 | | SNDRV_PCM_INFO_BLOCK_TRANSFER | ||
143 | | SNDRV_PCM_INFO_JOINT_DUPLEX | ||
144 | | SNDRV_PCM_INFO_RESUME | ||
145 | | SNDRV_PCM_INFO_PAUSE), | ||
146 | .formats = (SNDRV_PCM_FMTBIT_S16_BE | ||
147 | | SNDRV_PCM_FMTBIT_S16_LE), | ||
148 | .rates = (SNDRV_PCM_RATE_CONTINUOUS), | ||
149 | .rate_min = 4000, | ||
150 | .rate_max = 48000, | ||
151 | .channels_min = 1, | ||
152 | .channels_max = 2, | ||
153 | .buffer_bytes_max = 64 * 4096, | ||
154 | .period_bytes_min = 4096, | ||
155 | .period_bytes_max = 4096, | ||
156 | .periods_min = 4, | ||
157 | .periods_max = 64, | ||
158 | }; | ||
159 | |||
160 | static int atmel_ac97c_playback_open(struct snd_pcm_substream *substream) | ||
161 | { | ||
162 | struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); | ||
163 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
164 | |||
165 | mutex_lock(&opened_mutex); | ||
166 | chip->opened++; | ||
167 | runtime->hw = atmel_ac97c_hw; | ||
168 | if (chip->cur_rate) { | ||
169 | runtime->hw.rate_min = chip->cur_rate; | ||
170 | runtime->hw.rate_max = chip->cur_rate; | ||
171 | } | ||
172 | if (chip->cur_format) | ||
173 | runtime->hw.formats = (1ULL << chip->cur_format); | ||
174 | mutex_unlock(&opened_mutex); | ||
175 | chip->playback_substream = substream; | ||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | static int atmel_ac97c_capture_open(struct snd_pcm_substream *substream) | ||
180 | { | ||
181 | struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); | ||
182 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
183 | |||
184 | mutex_lock(&opened_mutex); | ||
185 | chip->opened++; | ||
186 | runtime->hw = atmel_ac97c_hw; | ||
187 | if (chip->cur_rate) { | ||
188 | runtime->hw.rate_min = chip->cur_rate; | ||
189 | runtime->hw.rate_max = chip->cur_rate; | ||
190 | } | ||
191 | if (chip->cur_format) | ||
192 | runtime->hw.formats = (1ULL << chip->cur_format); | ||
193 | mutex_unlock(&opened_mutex); | ||
194 | chip->capture_substream = substream; | ||
195 | return 0; | ||
196 | } | ||
197 | |||
198 | static int atmel_ac97c_playback_close(struct snd_pcm_substream *substream) | ||
199 | { | ||
200 | struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); | ||
201 | |||
202 | mutex_lock(&opened_mutex); | ||
203 | chip->opened--; | ||
204 | if (!chip->opened) { | ||
205 | chip->cur_rate = 0; | ||
206 | chip->cur_format = 0; | ||
207 | } | ||
208 | mutex_unlock(&opened_mutex); | ||
209 | |||
210 | chip->playback_substream = NULL; | ||
211 | |||
212 | return 0; | ||
213 | } | ||
214 | |||
215 | static int atmel_ac97c_capture_close(struct snd_pcm_substream *substream) | ||
216 | { | ||
217 | struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); | ||
218 | |||
219 | mutex_lock(&opened_mutex); | ||
220 | chip->opened--; | ||
221 | if (!chip->opened) { | ||
222 | chip->cur_rate = 0; | ||
223 | chip->cur_format = 0; | ||
224 | } | ||
225 | mutex_unlock(&opened_mutex); | ||
226 | |||
227 | chip->capture_substream = NULL; | ||
228 | |||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | static int atmel_ac97c_playback_hw_params(struct snd_pcm_substream *substream, | ||
233 | struct snd_pcm_hw_params *hw_params) | ||
234 | { | ||
235 | struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); | ||
236 | int retval; | ||
237 | |||
238 | retval = snd_pcm_lib_malloc_pages(substream, | ||
239 | params_buffer_bytes(hw_params)); | ||
240 | if (retval < 0) | ||
241 | return retval; | ||
242 | /* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */ | ||
243 | if (retval == 1) | ||
244 | if (test_and_clear_bit(DMA_TX_READY, &chip->flags)) | ||
245 | dw_dma_cyclic_free(chip->dma.tx_chan); | ||
246 | |||
247 | /* Set restrictions to params. */ | ||
248 | mutex_lock(&opened_mutex); | ||
249 | chip->cur_rate = params_rate(hw_params); | ||
250 | chip->cur_format = params_format(hw_params); | ||
251 | mutex_unlock(&opened_mutex); | ||
252 | |||
253 | return retval; | ||
254 | } | ||
255 | |||
256 | static int atmel_ac97c_capture_hw_params(struct snd_pcm_substream *substream, | ||
257 | struct snd_pcm_hw_params *hw_params) | ||
258 | { | ||
259 | struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); | ||
260 | int retval; | ||
261 | |||
262 | retval = snd_pcm_lib_malloc_pages(substream, | ||
263 | params_buffer_bytes(hw_params)); | ||
264 | if (retval < 0) | ||
265 | return retval; | ||
266 | /* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */ | ||
267 | if (retval == 1) | ||
268 | if (test_and_clear_bit(DMA_RX_READY, &chip->flags)) | ||
269 | dw_dma_cyclic_free(chip->dma.rx_chan); | ||
270 | |||
271 | /* Set restrictions to params. */ | ||
272 | mutex_lock(&opened_mutex); | ||
273 | chip->cur_rate = params_rate(hw_params); | ||
274 | chip->cur_format = params_format(hw_params); | ||
275 | mutex_unlock(&opened_mutex); | ||
276 | |||
277 | return retval; | ||
278 | } | ||
279 | |||
280 | static int atmel_ac97c_playback_hw_free(struct snd_pcm_substream *substream) | ||
281 | { | ||
282 | struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); | ||
283 | if (test_and_clear_bit(DMA_TX_READY, &chip->flags)) | ||
284 | dw_dma_cyclic_free(chip->dma.tx_chan); | ||
285 | return snd_pcm_lib_free_pages(substream); | ||
286 | } | ||
287 | |||
288 | static int atmel_ac97c_capture_hw_free(struct snd_pcm_substream *substream) | ||
289 | { | ||
290 | struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); | ||
291 | if (test_and_clear_bit(DMA_RX_READY, &chip->flags)) | ||
292 | dw_dma_cyclic_free(chip->dma.rx_chan); | ||
293 | return snd_pcm_lib_free_pages(substream); | ||
294 | } | ||
295 | |||
296 | static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream) | ||
297 | { | ||
298 | struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); | ||
299 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
300 | unsigned long word = 0; | ||
301 | int retval; | ||
302 | |||
303 | /* assign channels to AC97C channel A */ | ||
304 | switch (runtime->channels) { | ||
305 | case 1: | ||
306 | word |= AC97C_CH_ASSIGN(PCM_LEFT, A); | ||
307 | break; | ||
308 | case 2: | ||
309 | word |= AC97C_CH_ASSIGN(PCM_LEFT, A) | ||
310 | | AC97C_CH_ASSIGN(PCM_RIGHT, A); | ||
311 | break; | ||
312 | default: | ||
313 | /* TODO: support more than two channels */ | ||
314 | return -EINVAL; | ||
315 | break; | ||
316 | } | ||
317 | ac97c_writel(chip, OCA, word); | ||
318 | |||
319 | /* configure sample format and size */ | ||
320 | word = AC97C_CMR_DMAEN | AC97C_CMR_SIZE_16; | ||
321 | |||
322 | switch (runtime->format) { | ||
323 | case SNDRV_PCM_FORMAT_S16_LE: | ||
324 | word |= AC97C_CMR_CEM_LITTLE; | ||
325 | break; | ||
326 | case SNDRV_PCM_FORMAT_S16_BE: /* fall through */ | ||
327 | default: | ||
328 | word &= ~(AC97C_CMR_CEM_LITTLE); | ||
329 | break; | ||
330 | } | ||
331 | |||
332 | ac97c_writel(chip, CAMR, word); | ||
333 | |||
334 | /* set variable rate if needed */ | ||
335 | if (runtime->rate != 48000) { | ||
336 | word = ac97c_readl(chip, MR); | ||
337 | word |= AC97C_MR_VRA; | ||
338 | ac97c_writel(chip, MR, word); | ||
339 | } else { | ||
340 | word = ac97c_readl(chip, MR); | ||
341 | word &= ~(AC97C_MR_VRA); | ||
342 | ac97c_writel(chip, MR, word); | ||
343 | } | ||
344 | |||
345 | retval = snd_ac97_set_rate(chip->ac97, AC97_PCM_FRONT_DAC_RATE, | ||
346 | runtime->rate); | ||
347 | if (retval) | ||
348 | dev_dbg(&chip->pdev->dev, "could not set rate %d Hz\n", | ||
349 | runtime->rate); | ||
350 | |||
351 | if (!test_bit(DMA_TX_READY, &chip->flags)) | ||
352 | retval = atmel_ac97c_prepare_dma(chip, substream, | ||
353 | DMA_TO_DEVICE); | ||
354 | |||
355 | return retval; | ||
356 | } | ||
357 | |||
358 | static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream) | ||
359 | { | ||
360 | struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); | ||
361 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
362 | unsigned long word = 0; | ||
363 | int retval; | ||
364 | |||
365 | /* assign channels to AC97C channel A */ | ||
366 | switch (runtime->channels) { | ||
367 | case 1: | ||
368 | word |= AC97C_CH_ASSIGN(PCM_LEFT, A); | ||
369 | break; | ||
370 | case 2: | ||
371 | word |= AC97C_CH_ASSIGN(PCM_LEFT, A) | ||
372 | | AC97C_CH_ASSIGN(PCM_RIGHT, A); | ||
373 | break; | ||
374 | default: | ||
375 | /* TODO: support more than two channels */ | ||
376 | return -EINVAL; | ||
377 | break; | ||
378 | } | ||
379 | ac97c_writel(chip, ICA, word); | ||
380 | |||
381 | /* configure sample format and size */ | ||
382 | word = AC97C_CMR_DMAEN | AC97C_CMR_SIZE_16; | ||
383 | |||
384 | switch (runtime->format) { | ||
385 | case SNDRV_PCM_FORMAT_S16_LE: | ||
386 | word |= AC97C_CMR_CEM_LITTLE; | ||
387 | break; | ||
388 | case SNDRV_PCM_FORMAT_S16_BE: /* fall through */ | ||
389 | default: | ||
390 | word &= ~(AC97C_CMR_CEM_LITTLE); | ||
391 | break; | ||
392 | } | ||
393 | |||
394 | ac97c_writel(chip, CAMR, word); | ||
395 | |||
396 | /* set variable rate if needed */ | ||
397 | if (runtime->rate != 48000) { | ||
398 | word = ac97c_readl(chip, MR); | ||
399 | word |= AC97C_MR_VRA; | ||
400 | ac97c_writel(chip, MR, word); | ||
401 | } else { | ||
402 | word = ac97c_readl(chip, MR); | ||
403 | word &= ~(AC97C_MR_VRA); | ||
404 | ac97c_writel(chip, MR, word); | ||
405 | } | ||
406 | |||
407 | retval = snd_ac97_set_rate(chip->ac97, AC97_PCM_LR_ADC_RATE, | ||
408 | runtime->rate); | ||
409 | if (retval) | ||
410 | dev_dbg(&chip->pdev->dev, "could not set rate %d Hz\n", | ||
411 | runtime->rate); | ||
412 | |||
413 | if (!test_bit(DMA_RX_READY, &chip->flags)) | ||
414 | retval = atmel_ac97c_prepare_dma(chip, substream, | ||
415 | DMA_FROM_DEVICE); | ||
416 | |||
417 | return retval; | ||
418 | } | ||
419 | |||
420 | static int | ||
421 | atmel_ac97c_playback_trigger(struct snd_pcm_substream *substream, int cmd) | ||
422 | { | ||
423 | struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); | ||
424 | unsigned long camr; | ||
425 | int retval = 0; | ||
426 | |||
427 | camr = ac97c_readl(chip, CAMR); | ||
428 | |||
429 | switch (cmd) { | ||
430 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */ | ||
431 | case SNDRV_PCM_TRIGGER_RESUME: /* fall through */ | ||
432 | case SNDRV_PCM_TRIGGER_START: | ||
433 | retval = dw_dma_cyclic_start(chip->dma.tx_chan); | ||
434 | if (retval) | ||
435 | goto out; | ||
436 | camr |= AC97C_CMR_CENA; | ||
437 | break; | ||
438 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */ | ||
439 | case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */ | ||
440 | case SNDRV_PCM_TRIGGER_STOP: | ||
441 | dw_dma_cyclic_stop(chip->dma.tx_chan); | ||
442 | if (chip->opened <= 1) | ||
443 | camr &= ~AC97C_CMR_CENA; | ||
444 | break; | ||
445 | default: | ||
446 | retval = -EINVAL; | ||
447 | goto out; | ||
448 | } | ||
449 | |||
450 | ac97c_writel(chip, CAMR, camr); | ||
451 | out: | ||
452 | return retval; | ||
453 | } | ||
454 | |||
455 | static int | ||
456 | atmel_ac97c_capture_trigger(struct snd_pcm_substream *substream, int cmd) | ||
457 | { | ||
458 | struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); | ||
459 | unsigned long camr; | ||
460 | int retval = 0; | ||
461 | |||
462 | camr = ac97c_readl(chip, CAMR); | ||
463 | |||
464 | switch (cmd) { | ||
465 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */ | ||
466 | case SNDRV_PCM_TRIGGER_RESUME: /* fall through */ | ||
467 | case SNDRV_PCM_TRIGGER_START: | ||
468 | retval = dw_dma_cyclic_start(chip->dma.rx_chan); | ||
469 | if (retval) | ||
470 | goto out; | ||
471 | camr |= AC97C_CMR_CENA; | ||
472 | break; | ||
473 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */ | ||
474 | case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */ | ||
475 | case SNDRV_PCM_TRIGGER_STOP: | ||
476 | dw_dma_cyclic_stop(chip->dma.rx_chan); | ||
477 | if (chip->opened <= 1) | ||
478 | camr &= ~AC97C_CMR_CENA; | ||
479 | break; | ||
480 | default: | ||
481 | retval = -EINVAL; | ||
482 | break; | ||
483 | } | ||
484 | |||
485 | ac97c_writel(chip, CAMR, camr); | ||
486 | out: | ||
487 | return retval; | ||
488 | } | ||
489 | |||
490 | static snd_pcm_uframes_t | ||
491 | atmel_ac97c_playback_pointer(struct snd_pcm_substream *substream) | ||
492 | { | ||
493 | struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); | ||
494 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
495 | snd_pcm_uframes_t frames; | ||
496 | unsigned long bytes; | ||
497 | |||
498 | bytes = dw_dma_get_src_addr(chip->dma.tx_chan); | ||
499 | bytes -= runtime->dma_addr; | ||
500 | |||
501 | frames = bytes_to_frames(runtime, bytes); | ||
502 | if (frames >= runtime->buffer_size) | ||
503 | frames -= runtime->buffer_size; | ||
504 | return frames; | ||
505 | } | ||
506 | |||
507 | static snd_pcm_uframes_t | ||
508 | atmel_ac97c_capture_pointer(struct snd_pcm_substream *substream) | ||
509 | { | ||
510 | struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); | ||
511 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
512 | snd_pcm_uframes_t frames; | ||
513 | unsigned long bytes; | ||
514 | |||
515 | bytes = dw_dma_get_dst_addr(chip->dma.rx_chan); | ||
516 | bytes -= runtime->dma_addr; | ||
517 | |||
518 | frames = bytes_to_frames(runtime, bytes); | ||
519 | if (frames >= runtime->buffer_size) | ||
520 | frames -= runtime->buffer_size; | ||
521 | return frames; | ||
522 | } | ||
523 | |||
524 | static struct snd_pcm_ops atmel_ac97_playback_ops = { | ||
525 | .open = atmel_ac97c_playback_open, | ||
526 | .close = atmel_ac97c_playback_close, | ||
527 | .ioctl = snd_pcm_lib_ioctl, | ||
528 | .hw_params = atmel_ac97c_playback_hw_params, | ||
529 | .hw_free = atmel_ac97c_playback_hw_free, | ||
530 | .prepare = atmel_ac97c_playback_prepare, | ||
531 | .trigger = atmel_ac97c_playback_trigger, | ||
532 | .pointer = atmel_ac97c_playback_pointer, | ||
533 | }; | ||
534 | |||
535 | static struct snd_pcm_ops atmel_ac97_capture_ops = { | ||
536 | .open = atmel_ac97c_capture_open, | ||
537 | .close = atmel_ac97c_capture_close, | ||
538 | .ioctl = snd_pcm_lib_ioctl, | ||
539 | .hw_params = atmel_ac97c_capture_hw_params, | ||
540 | .hw_free = atmel_ac97c_capture_hw_free, | ||
541 | .prepare = atmel_ac97c_capture_prepare, | ||
542 | .trigger = atmel_ac97c_capture_trigger, | ||
543 | .pointer = atmel_ac97c_capture_pointer, | ||
544 | }; | ||
545 | |||
546 | static int __devinit atmel_ac97c_pcm_new(struct atmel_ac97c *chip) | ||
547 | { | ||
548 | struct snd_pcm *pcm; | ||
549 | struct snd_pcm_hardware hw = atmel_ac97c_hw; | ||
550 | int capture, playback, retval; | ||
551 | |||
552 | capture = test_bit(DMA_RX_CHAN_PRESENT, &chip->flags); | ||
553 | playback = test_bit(DMA_TX_CHAN_PRESENT, &chip->flags); | ||
554 | |||
555 | retval = snd_pcm_new(chip->card, chip->card->shortname, | ||
556 | chip->pdev->id, playback, capture, &pcm); | ||
557 | if (retval) | ||
558 | return retval; | ||
559 | |||
560 | if (capture) | ||
561 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, | ||
562 | &atmel_ac97_capture_ops); | ||
563 | if (playback) | ||
564 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, | ||
565 | &atmel_ac97_playback_ops); | ||
566 | |||
567 | retval = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | ||
568 | &chip->pdev->dev, hw.periods_min * hw.period_bytes_min, | ||
569 | hw.buffer_bytes_max); | ||
570 | if (retval) | ||
571 | return retval; | ||
572 | |||
573 | pcm->private_data = chip; | ||
574 | pcm->info_flags = 0; | ||
575 | strcpy(pcm->name, chip->card->shortname); | ||
576 | chip->pcm = pcm; | ||
577 | |||
578 | return 0; | ||
579 | } | ||
580 | |||
581 | static int atmel_ac97c_mixer_new(struct atmel_ac97c *chip) | ||
582 | { | ||
583 | struct snd_ac97_template template; | ||
584 | memset(&template, 0, sizeof(template)); | ||
585 | template.private_data = chip; | ||
586 | return snd_ac97_mixer(chip->ac97_bus, &template, &chip->ac97); | ||
587 | } | ||
588 | |||
589 | static void atmel_ac97c_write(struct snd_ac97 *ac97, unsigned short reg, | ||
590 | unsigned short val) | ||
591 | { | ||
592 | struct atmel_ac97c *chip = get_chip(ac97); | ||
593 | unsigned long word; | ||
594 | int timeout = 40; | ||
595 | |||
596 | word = (reg & 0x7f) << 16 | val; | ||
597 | |||
598 | do { | ||
599 | if (ac97c_readl(chip, COSR) & AC97C_CSR_TXRDY) { | ||
600 | ac97c_writel(chip, COTHR, word); | ||
601 | return; | ||
602 | } | ||
603 | udelay(1); | ||
604 | } while (--timeout); | ||
605 | |||
606 | dev_dbg(&chip->pdev->dev, "codec write timeout\n"); | ||
607 | } | ||
608 | |||
609 | static unsigned short atmel_ac97c_read(struct snd_ac97 *ac97, | ||
610 | unsigned short reg) | ||
611 | { | ||
612 | struct atmel_ac97c *chip = get_chip(ac97); | ||
613 | unsigned long word; | ||
614 | int timeout = 40; | ||
615 | int write = 10; | ||
616 | |||
617 | word = (0x80 | (reg & 0x7f)) << 16; | ||
618 | |||
619 | if ((ac97c_readl(chip, COSR) & AC97C_CSR_RXRDY) != 0) | ||
620 | ac97c_readl(chip, CORHR); | ||
621 | |||
622 | retry_write: | ||
623 | timeout = 40; | ||
624 | |||
625 | do { | ||
626 | if ((ac97c_readl(chip, COSR) & AC97C_CSR_TXRDY) != 0) { | ||
627 | ac97c_writel(chip, COTHR, word); | ||
628 | goto read_reg; | ||
629 | } | ||
630 | udelay(10); | ||
631 | } while (--timeout); | ||
632 | |||
633 | if (!--write) | ||
634 | goto timed_out; | ||
635 | goto retry_write; | ||
636 | |||
637 | read_reg: | ||
638 | do { | ||
639 | if ((ac97c_readl(chip, COSR) & AC97C_CSR_RXRDY) != 0) { | ||
640 | unsigned short val = ac97c_readl(chip, CORHR); | ||
641 | return val; | ||
642 | } | ||
643 | udelay(10); | ||
644 | } while (--timeout); | ||
645 | |||
646 | if (!--write) | ||
647 | goto timed_out; | ||
648 | goto retry_write; | ||
649 | |||
650 | timed_out: | ||
651 | dev_dbg(&chip->pdev->dev, "codec read timeout\n"); | ||
652 | return 0xffff; | ||
653 | } | ||
654 | |||
655 | static bool filter(struct dma_chan *chan, void *slave) | ||
656 | { | ||
657 | struct dw_dma_slave *dws = slave; | ||
658 | |||
659 | if (dws->dma_dev == chan->device->dev) { | ||
660 | chan->private = dws; | ||
661 | return true; | ||
662 | } else | ||
663 | return false; | ||
664 | } | ||
665 | |||
666 | static void atmel_ac97c_reset(struct atmel_ac97c *chip) | ||
667 | { | ||
668 | ac97c_writel(chip, MR, AC97C_MR_WRST); | ||
669 | |||
670 | if (gpio_is_valid(chip->reset_pin)) { | ||
671 | gpio_set_value(chip->reset_pin, 0); | ||
672 | /* AC97 v2.2 specifications says minimum 1 us. */ | ||
673 | udelay(10); | ||
674 | gpio_set_value(chip->reset_pin, 1); | ||
675 | } | ||
676 | |||
677 | udelay(1); | ||
678 | ac97c_writel(chip, MR, AC97C_MR_ENA); | ||
679 | } | ||
680 | |||
681 | static int __devinit atmel_ac97c_probe(struct platform_device *pdev) | ||
682 | { | ||
683 | struct snd_card *card; | ||
684 | struct atmel_ac97c *chip; | ||
685 | struct resource *regs; | ||
686 | struct ac97c_platform_data *pdata; | ||
687 | struct clk *pclk; | ||
688 | static struct snd_ac97_bus_ops ops = { | ||
689 | .write = atmel_ac97c_write, | ||
690 | .read = atmel_ac97c_read, | ||
691 | }; | ||
692 | int retval; | ||
693 | |||
694 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
695 | if (!regs) { | ||
696 | dev_dbg(&pdev->dev, "no memory resource\n"); | ||
697 | return -ENXIO; | ||
698 | } | ||
699 | |||
700 | pdata = pdev->dev.platform_data; | ||
701 | if (!pdata) { | ||
702 | dev_dbg(&pdev->dev, "no platform data\n"); | ||
703 | return -ENXIO; | ||
704 | } | ||
705 | |||
706 | pclk = clk_get(&pdev->dev, "pclk"); | ||
707 | if (IS_ERR(pclk)) { | ||
708 | dev_dbg(&pdev->dev, "no peripheral clock\n"); | ||
709 | return PTR_ERR(pclk); | ||
710 | } | ||
711 | clk_enable(pclk); | ||
712 | |||
713 | retval = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, | ||
714 | THIS_MODULE, sizeof(struct atmel_ac97c), &card); | ||
715 | if (retval) { | ||
716 | dev_dbg(&pdev->dev, "could not create sound card device\n"); | ||
717 | goto err_snd_card_new; | ||
718 | } | ||
719 | |||
720 | chip = get_chip(card); | ||
721 | |||
722 | spin_lock_init(&chip->lock); | ||
723 | |||
724 | strcpy(card->driver, "Atmel AC97C"); | ||
725 | strcpy(card->shortname, "Atmel AC97C"); | ||
726 | sprintf(card->longname, "Atmel AC97 controller"); | ||
727 | |||
728 | chip->card = card; | ||
729 | chip->pclk = pclk; | ||
730 | chip->pdev = pdev; | ||
731 | chip->regs = ioremap(regs->start, regs->end - regs->start + 1); | ||
732 | |||
733 | if (!chip->regs) { | ||
734 | dev_dbg(&pdev->dev, "could not remap register memory\n"); | ||
735 | goto err_ioremap; | ||
736 | } | ||
737 | |||
738 | if (gpio_is_valid(pdata->reset_pin)) { | ||
739 | if (gpio_request(pdata->reset_pin, "reset_pin")) { | ||
740 | dev_dbg(&pdev->dev, "reset pin not available\n"); | ||
741 | chip->reset_pin = -ENODEV; | ||
742 | } else { | ||
743 | gpio_direction_output(pdata->reset_pin, 1); | ||
744 | chip->reset_pin = pdata->reset_pin; | ||
745 | } | ||
746 | } | ||
747 | |||
748 | snd_card_set_dev(card, &pdev->dev); | ||
749 | |||
750 | retval = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus); | ||
751 | if (retval) { | ||
752 | dev_dbg(&pdev->dev, "could not register on ac97 bus\n"); | ||
753 | goto err_ac97_bus; | ||
754 | } | ||
755 | |||
756 | atmel_ac97c_reset(chip); | ||
757 | |||
758 | retval = atmel_ac97c_mixer_new(chip); | ||
759 | if (retval) { | ||
760 | dev_dbg(&pdev->dev, "could not register ac97 mixer\n"); | ||
761 | goto err_ac97_bus; | ||
762 | } | ||
763 | |||
764 | if (pdata->rx_dws.dma_dev) { | ||
765 | struct dw_dma_slave *dws = &pdata->rx_dws; | ||
766 | dma_cap_mask_t mask; | ||
767 | |||
768 | dws->rx_reg = regs->start + AC97C_CARHR + 2; | ||
769 | |||
770 | dma_cap_zero(mask); | ||
771 | dma_cap_set(DMA_SLAVE, mask); | ||
772 | |||
773 | chip->dma.rx_chan = dma_request_channel(mask, filter, dws); | ||
774 | |||
775 | dev_info(&chip->pdev->dev, "using %s for DMA RX\n", | ||
776 | chip->dma.rx_chan->dev->device.bus_id); | ||
777 | set_bit(DMA_RX_CHAN_PRESENT, &chip->flags); | ||
778 | } | ||
779 | |||
780 | if (pdata->tx_dws.dma_dev) { | ||
781 | struct dw_dma_slave *dws = &pdata->tx_dws; | ||
782 | dma_cap_mask_t mask; | ||
783 | |||
784 | dws->tx_reg = regs->start + AC97C_CATHR + 2; | ||
785 | |||
786 | dma_cap_zero(mask); | ||
787 | dma_cap_set(DMA_SLAVE, mask); | ||
788 | |||
789 | chip->dma.tx_chan = dma_request_channel(mask, filter, dws); | ||
790 | |||
791 | dev_info(&chip->pdev->dev, "using %s for DMA TX\n", | ||
792 | chip->dma.tx_chan->dev->device.bus_id); | ||
793 | set_bit(DMA_TX_CHAN_PRESENT, &chip->flags); | ||
794 | } | ||
795 | |||
796 | if (!test_bit(DMA_RX_CHAN_PRESENT, &chip->flags) && | ||
797 | !test_bit(DMA_TX_CHAN_PRESENT, &chip->flags)) { | ||
798 | dev_dbg(&pdev->dev, "DMA not available\n"); | ||
799 | retval = -ENODEV; | ||
800 | goto err_dma; | ||
801 | } | ||
802 | |||
803 | retval = atmel_ac97c_pcm_new(chip); | ||
804 | if (retval) { | ||
805 | dev_dbg(&pdev->dev, "could not register ac97 pcm device\n"); | ||
806 | goto err_dma; | ||
807 | } | ||
808 | |||
809 | retval = snd_card_register(card); | ||
810 | if (retval) { | ||
811 | dev_dbg(&pdev->dev, "could not register sound card\n"); | ||
812 | goto err_ac97_bus; | ||
813 | } | ||
814 | |||
815 | platform_set_drvdata(pdev, card); | ||
816 | |||
817 | dev_info(&pdev->dev, "Atmel AC97 controller at 0x%p\n", | ||
818 | chip->regs); | ||
819 | |||
820 | return 0; | ||
821 | |||
822 | err_dma: | ||
823 | if (test_bit(DMA_RX_CHAN_PRESENT, &chip->flags)) | ||
824 | dma_release_channel(chip->dma.rx_chan); | ||
825 | if (test_bit(DMA_TX_CHAN_PRESENT, &chip->flags)) | ||
826 | dma_release_channel(chip->dma.tx_chan); | ||
827 | clear_bit(DMA_RX_CHAN_PRESENT, &chip->flags); | ||
828 | clear_bit(DMA_TX_CHAN_PRESENT, &chip->flags); | ||
829 | chip->dma.rx_chan = NULL; | ||
830 | chip->dma.tx_chan = NULL; | ||
831 | err_ac97_bus: | ||
832 | snd_card_set_dev(card, NULL); | ||
833 | |||
834 | if (gpio_is_valid(chip->reset_pin)) | ||
835 | gpio_free(chip->reset_pin); | ||
836 | |||
837 | iounmap(chip->regs); | ||
838 | err_ioremap: | ||
839 | snd_card_free(card); | ||
840 | err_snd_card_new: | ||
841 | clk_disable(pclk); | ||
842 | clk_put(pclk); | ||
843 | return retval; | ||
844 | } | ||
845 | |||
846 | #ifdef CONFIG_PM | ||
847 | static int atmel_ac97c_suspend(struct platform_device *pdev, pm_message_t msg) | ||
848 | { | ||
849 | struct snd_card *card = platform_get_drvdata(pdev); | ||
850 | struct atmel_ac97c *chip = card->private_data; | ||
851 | |||
852 | if (test_bit(DMA_RX_READY, &chip->flags)) | ||
853 | dw_dma_cyclic_stop(chip->dma.rx_chan); | ||
854 | if (test_bit(DMA_TX_READY, &chip->flags)) | ||
855 | dw_dma_cyclic_stop(chip->dma.tx_chan); | ||
856 | clk_disable(chip->pclk); | ||
857 | |||
858 | return 0; | ||
859 | } | ||
860 | |||
861 | static int atmel_ac97c_resume(struct platform_device *pdev) | ||
862 | { | ||
863 | struct snd_card *card = platform_get_drvdata(pdev); | ||
864 | struct atmel_ac97c *chip = card->private_data; | ||
865 | |||
866 | clk_enable(chip->pclk); | ||
867 | if (test_bit(DMA_RX_READY, &chip->flags)) | ||
868 | dw_dma_cyclic_start(chip->dma.rx_chan); | ||
869 | if (test_bit(DMA_TX_READY, &chip->flags)) | ||
870 | dw_dma_cyclic_start(chip->dma.tx_chan); | ||
871 | |||
872 | return 0; | ||
873 | } | ||
874 | #else | ||
875 | #define atmel_ac97c_suspend NULL | ||
876 | #define atmel_ac97c_resume NULL | ||
877 | #endif | ||
878 | |||
879 | static int __devexit atmel_ac97c_remove(struct platform_device *pdev) | ||
880 | { | ||
881 | struct snd_card *card = platform_get_drvdata(pdev); | ||
882 | struct atmel_ac97c *chip = get_chip(card); | ||
883 | |||
884 | if (gpio_is_valid(chip->reset_pin)) | ||
885 | gpio_free(chip->reset_pin); | ||
886 | |||
887 | clk_disable(chip->pclk); | ||
888 | clk_put(chip->pclk); | ||
889 | iounmap(chip->regs); | ||
890 | |||
891 | if (test_bit(DMA_RX_CHAN_PRESENT, &chip->flags)) | ||
892 | dma_release_channel(chip->dma.rx_chan); | ||
893 | if (test_bit(DMA_TX_CHAN_PRESENT, &chip->flags)) | ||
894 | dma_release_channel(chip->dma.tx_chan); | ||
895 | clear_bit(DMA_RX_CHAN_PRESENT, &chip->flags); | ||
896 | clear_bit(DMA_TX_CHAN_PRESENT, &chip->flags); | ||
897 | chip->dma.rx_chan = NULL; | ||
898 | chip->dma.tx_chan = NULL; | ||
899 | |||
900 | snd_card_set_dev(card, NULL); | ||
901 | snd_card_free(card); | ||
902 | |||
903 | platform_set_drvdata(pdev, NULL); | ||
904 | |||
905 | return 0; | ||
906 | } | ||
907 | |||
908 | static struct platform_driver atmel_ac97c_driver = { | ||
909 | .remove = __devexit_p(atmel_ac97c_remove), | ||
910 | .driver = { | ||
911 | .name = "atmel_ac97c", | ||
912 | }, | ||
913 | .suspend = atmel_ac97c_suspend, | ||
914 | .resume = atmel_ac97c_resume, | ||
915 | }; | ||
916 | |||
917 | static int __init atmel_ac97c_init(void) | ||
918 | { | ||
919 | return platform_driver_probe(&atmel_ac97c_driver, | ||
920 | atmel_ac97c_probe); | ||
921 | } | ||
922 | module_init(atmel_ac97c_init); | ||
923 | |||
924 | static void __exit atmel_ac97c_exit(void) | ||
925 | { | ||
926 | platform_driver_unregister(&atmel_ac97c_driver); | ||
927 | } | ||
928 | module_exit(atmel_ac97c_exit); | ||
929 | |||
930 | MODULE_LICENSE("GPL"); | ||
931 | MODULE_DESCRIPTION("Driver for Atmel AC97 controller"); | ||
932 | MODULE_AUTHOR("Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com>"); | ||
diff --git a/sound/atmel/ac97c.h b/sound/atmel/ac97c.h new file mode 100644 index 000000000000..c17bd5825980 --- /dev/null +++ b/sound/atmel/ac97c.h | |||
@@ -0,0 +1,71 @@ | |||
1 | /* | ||
2 | * Register definitions for the Atmel AC97C controller | ||
3 | * | ||
4 | * Copyright (C) 2005-2009 Atmel Corporation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License version 2 as published | ||
8 | * by the Free Software Foundation. | ||
9 | */ | ||
10 | #ifndef __SOUND_ATMEL_AC97C_H | ||
11 | #define __SOUND_ATMEL_AC97C_H | ||
12 | |||
13 | #define AC97C_MR 0x08 | ||
14 | #define AC97C_ICA 0x10 | ||
15 | #define AC97C_OCA 0x14 | ||
16 | #define AC97C_CARHR 0x20 | ||
17 | #define AC97C_CATHR 0x24 | ||
18 | #define AC97C_CASR 0x28 | ||
19 | #define AC97C_CAMR 0x2c | ||
20 | #define AC97C_CBRHR 0x30 | ||
21 | #define AC97C_CBTHR 0x34 | ||
22 | #define AC97C_CBSR 0x38 | ||
23 | #define AC97C_CBMR 0x3c | ||
24 | #define AC97C_CORHR 0x40 | ||
25 | #define AC97C_COTHR 0x44 | ||
26 | #define AC97C_COSR 0x48 | ||
27 | #define AC97C_COMR 0x4c | ||
28 | #define AC97C_SR 0x50 | ||
29 | #define AC97C_IER 0x54 | ||
30 | #define AC97C_IDR 0x58 | ||
31 | #define AC97C_IMR 0x5c | ||
32 | #define AC97C_VERSION 0xfc | ||
33 | |||
34 | #define AC97C_CATPR PDC_TPR | ||
35 | #define AC97C_CATCR PDC_TCR | ||
36 | #define AC97C_CATNPR PDC_TNPR | ||
37 | #define AC97C_CATNCR PDC_TNCR | ||
38 | #define AC97C_CARPR PDC_RPR | ||
39 | #define AC97C_CARCR PDC_RCR | ||
40 | #define AC97C_CARNPR PDC_RNPR | ||
41 | #define AC97C_CARNCR PDC_RNCR | ||
42 | #define AC97C_PTCR PDC_PTCR | ||
43 | |||
44 | #define AC97C_MR_ENA (1 << 0) | ||
45 | #define AC97C_MR_WRST (1 << 1) | ||
46 | #define AC97C_MR_VRA (1 << 2) | ||
47 | |||
48 | #define AC97C_CSR_TXRDY (1 << 0) | ||
49 | #define AC97C_CSR_UNRUN (1 << 2) | ||
50 | #define AC97C_CSR_RXRDY (1 << 4) | ||
51 | #define AC97C_CSR_ENDTX (1 << 10) | ||
52 | #define AC97C_CSR_ENDRX (1 << 14) | ||
53 | |||
54 | #define AC97C_CMR_SIZE_20 (0 << 16) | ||
55 | #define AC97C_CMR_SIZE_18 (1 << 16) | ||
56 | #define AC97C_CMR_SIZE_16 (2 << 16) | ||
57 | #define AC97C_CMR_SIZE_10 (3 << 16) | ||
58 | #define AC97C_CMR_CEM_LITTLE (1 << 18) | ||
59 | #define AC97C_CMR_CEM_BIG (0 << 18) | ||
60 | #define AC97C_CMR_CENA (1 << 21) | ||
61 | #define AC97C_CMR_DMAEN (1 << 22) | ||
62 | |||
63 | #define AC97C_SR_CAEVT (1 << 3) | ||
64 | |||
65 | #define AC97C_CH_ASSIGN(slot, channel) \ | ||
66 | (AC97C_CHANNEL_##channel << (3 * (AC97_SLOT_##slot - 3))) | ||
67 | #define AC97C_CHANNEL_NONE 0x0 | ||
68 | #define AC97C_CHANNEL_A 0x1 | ||
69 | #define AC97C_CHANNEL_B 0x2 | ||
70 | |||
71 | #endif /* __SOUND_ATMEL_AC97C_H */ | ||
diff --git a/sound/core/control.c b/sound/core/control.c index 636b3b52ef8b..4b20fa2b7e6d 100644 --- a/sound/core/control.c +++ b/sound/core/control.c | |||
@@ -1373,12 +1373,9 @@ EXPORT_SYMBOL(snd_ctl_unregister_ioctl_compat); | |||
1373 | static int snd_ctl_fasync(int fd, struct file * file, int on) | 1373 | static int snd_ctl_fasync(int fd, struct file * file, int on) |
1374 | { | 1374 | { |
1375 | struct snd_ctl_file *ctl; | 1375 | struct snd_ctl_file *ctl; |
1376 | int err; | 1376 | |
1377 | ctl = file->private_data; | 1377 | ctl = file->private_data; |
1378 | err = fasync_helper(fd, file, on, &ctl->fasync); | 1378 | return fasync_helper(fd, file, on, &ctl->fasync); |
1379 | if (err < 0) | ||
1380 | return err; | ||
1381 | return 0; | ||
1382 | } | 1379 | } |
1383 | 1380 | ||
1384 | /* | 1381 | /* |
diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c index 195cafc5a553..a70ee7f1ed98 100644 --- a/sound/core/hwdep.c +++ b/sound/core/hwdep.c | |||
@@ -99,9 +99,6 @@ static int snd_hwdep_open(struct inode *inode, struct file * file) | |||
99 | if (hw == NULL) | 99 | if (hw == NULL) |
100 | return -ENODEV; | 100 | return -ENODEV; |
101 | 101 | ||
102 | if (!hw->ops.open) | ||
103 | return -ENXIO; | ||
104 | |||
105 | if (!try_module_get(hw->card->module)) | 102 | if (!try_module_get(hw->card->module)) |
106 | return -EFAULT; | 103 | return -EFAULT; |
107 | 104 | ||
@@ -113,6 +110,10 @@ static int snd_hwdep_open(struct inode *inode, struct file * file) | |||
113 | err = -EBUSY; | 110 | err = -EBUSY; |
114 | break; | 111 | break; |
115 | } | 112 | } |
113 | if (!hw->ops.open) { | ||
114 | err = 0; | ||
115 | break; | ||
116 | } | ||
116 | err = hw->ops.open(hw, file); | 117 | err = hw->ops.open(hw, file); |
117 | if (err >= 0) | 118 | if (err >= 0) |
118 | break; | 119 | break; |
@@ -151,7 +152,7 @@ static int snd_hwdep_open(struct inode *inode, struct file * file) | |||
151 | 152 | ||
152 | static int snd_hwdep_release(struct inode *inode, struct file * file) | 153 | static int snd_hwdep_release(struct inode *inode, struct file * file) |
153 | { | 154 | { |
154 | int err = -ENXIO; | 155 | int err = 0; |
155 | struct snd_hwdep *hw = file->private_data; | 156 | struct snd_hwdep *hw = file->private_data; |
156 | struct module *mod = hw->card->module; | 157 | struct module *mod = hw->card->module; |
157 | 158 | ||
diff --git a/sound/core/init.c b/sound/core/init.c index 0d5520c415d3..fd56afe846ed 100644 --- a/sound/core/init.c +++ b/sound/core/init.c | |||
@@ -121,31 +121,44 @@ static inline int init_info_for_card(struct snd_card *card) | |||
121 | #endif | 121 | #endif |
122 | 122 | ||
123 | /** | 123 | /** |
124 | * snd_card_new - create and initialize a soundcard structure | 124 | * snd_card_create - create and initialize a soundcard structure |
125 | * @idx: card index (address) [0 ... (SNDRV_CARDS-1)] | 125 | * @idx: card index (address) [0 ... (SNDRV_CARDS-1)] |
126 | * @xid: card identification (ASCII string) | 126 | * @xid: card identification (ASCII string) |
127 | * @module: top level module for locking | 127 | * @module: top level module for locking |
128 | * @extra_size: allocate this extra size after the main soundcard structure | 128 | * @extra_size: allocate this extra size after the main soundcard structure |
129 | * @card_ret: the pointer to store the created card instance | ||
129 | * | 130 | * |
130 | * Creates and initializes a soundcard structure. | 131 | * Creates and initializes a soundcard structure. |
131 | * | 132 | * |
132 | * Returns kmallocated snd_card structure. Creates the ALSA control interface | 133 | * The function allocates snd_card instance via kzalloc with the given |
133 | * (which is blocked until snd_card_register function is called). | 134 | * space for the driver to use freely. The allocated struct is stored |
135 | * in the given card_ret pointer. | ||
136 | * | ||
137 | * Returns zero if successful or a negative error code. | ||
134 | */ | 138 | */ |
135 | struct snd_card *snd_card_new(int idx, const char *xid, | 139 | int snd_card_create(int idx, const char *xid, |
136 | struct module *module, int extra_size) | 140 | struct module *module, int extra_size, |
141 | struct snd_card **card_ret) | ||
137 | { | 142 | { |
138 | struct snd_card *card; | 143 | struct snd_card *card; |
139 | int err, idx2; | 144 | int err, idx2; |
140 | 145 | ||
146 | if (snd_BUG_ON(!card_ret)) | ||
147 | return -EINVAL; | ||
148 | *card_ret = NULL; | ||
149 | |||
141 | if (extra_size < 0) | 150 | if (extra_size < 0) |
142 | extra_size = 0; | 151 | extra_size = 0; |
143 | card = kzalloc(sizeof(*card) + extra_size, GFP_KERNEL); | 152 | card = kzalloc(sizeof(*card) + extra_size, GFP_KERNEL); |
144 | if (card == NULL) | 153 | if (!card) |
145 | return NULL; | 154 | return -ENOMEM; |
146 | if (xid) { | 155 | if (xid) { |
147 | if (!snd_info_check_reserved_words(xid)) | 156 | if (!snd_info_check_reserved_words(xid)) { |
157 | snd_printk(KERN_ERR | ||
158 | "given id string '%s' is reserved.\n", xid); | ||
159 | err = -EBUSY; | ||
148 | goto __error; | 160 | goto __error; |
161 | } | ||
149 | strlcpy(card->id, xid, sizeof(card->id)); | 162 | strlcpy(card->id, xid, sizeof(card->id)); |
150 | } | 163 | } |
151 | err = 0; | 164 | err = 0; |
@@ -195,6 +208,7 @@ struct snd_card *snd_card_new(int idx, const char *xid, | |||
195 | INIT_LIST_HEAD(&card->controls); | 208 | INIT_LIST_HEAD(&card->controls); |
196 | INIT_LIST_HEAD(&card->ctl_files); | 209 | INIT_LIST_HEAD(&card->ctl_files); |
197 | spin_lock_init(&card->files_lock); | 210 | spin_lock_init(&card->files_lock); |
211 | INIT_LIST_HEAD(&card->files_list); | ||
198 | init_waitqueue_head(&card->shutdown_sleep); | 212 | init_waitqueue_head(&card->shutdown_sleep); |
199 | #ifdef CONFIG_PM | 213 | #ifdef CONFIG_PM |
200 | mutex_init(&card->power_lock); | 214 | mutex_init(&card->power_lock); |
@@ -202,26 +216,28 @@ struct snd_card *snd_card_new(int idx, const char *xid, | |||
202 | #endif | 216 | #endif |
203 | /* the control interface cannot be accessed from the user space until */ | 217 | /* the control interface cannot be accessed from the user space until */ |
204 | /* snd_cards_bitmask and snd_cards are set with snd_card_register */ | 218 | /* snd_cards_bitmask and snd_cards are set with snd_card_register */ |
205 | if ((err = snd_ctl_create(card)) < 0) { | 219 | err = snd_ctl_create(card); |
206 | snd_printd("unable to register control minors\n"); | 220 | if (err < 0) { |
221 | snd_printk(KERN_ERR "unable to register control minors\n"); | ||
207 | goto __error; | 222 | goto __error; |
208 | } | 223 | } |
209 | if ((err = snd_info_card_create(card)) < 0) { | 224 | err = snd_info_card_create(card); |
210 | snd_printd("unable to create card info\n"); | 225 | if (err < 0) { |
226 | snd_printk(KERN_ERR "unable to create card info\n"); | ||
211 | goto __error_ctl; | 227 | goto __error_ctl; |
212 | } | 228 | } |
213 | if (extra_size > 0) | 229 | if (extra_size > 0) |
214 | card->private_data = (char *)card + sizeof(struct snd_card); | 230 | card->private_data = (char *)card + sizeof(struct snd_card); |
215 | return card; | 231 | *card_ret = card; |
232 | return 0; | ||
216 | 233 | ||
217 | __error_ctl: | 234 | __error_ctl: |
218 | snd_device_free_all(card, SNDRV_DEV_CMD_PRE); | 235 | snd_device_free_all(card, SNDRV_DEV_CMD_PRE); |
219 | __error: | 236 | __error: |
220 | kfree(card); | 237 | kfree(card); |
221 | return NULL; | 238 | return err; |
222 | } | 239 | } |
223 | 240 | EXPORT_SYMBOL(snd_card_create); | |
224 | EXPORT_SYMBOL(snd_card_new); | ||
225 | 241 | ||
226 | /* return non-zero if a card is already locked */ | 242 | /* return non-zero if a card is already locked */ |
227 | int snd_card_locked(int card) | 243 | int snd_card_locked(int card) |
@@ -259,6 +275,7 @@ static int snd_disconnect_release(struct inode *inode, struct file *file) | |||
259 | list_for_each_entry(_df, &shutdown_files, shutdown_list) { | 275 | list_for_each_entry(_df, &shutdown_files, shutdown_list) { |
260 | if (_df->file == file) { | 276 | if (_df->file == file) { |
261 | df = _df; | 277 | df = _df; |
278 | list_del_init(&df->shutdown_list); | ||
262 | break; | 279 | break; |
263 | } | 280 | } |
264 | } | 281 | } |
@@ -347,8 +364,7 @@ int snd_card_disconnect(struct snd_card *card) | |||
347 | /* phase 2: replace file->f_op with special dummy operations */ | 364 | /* phase 2: replace file->f_op with special dummy operations */ |
348 | 365 | ||
349 | spin_lock(&card->files_lock); | 366 | spin_lock(&card->files_lock); |
350 | mfile = card->files; | 367 | list_for_each_entry(mfile, &card->files_list, list) { |
351 | while (mfile) { | ||
352 | file = mfile->file; | 368 | file = mfile->file; |
353 | 369 | ||
354 | /* it's critical part, use endless loop */ | 370 | /* it's critical part, use endless loop */ |
@@ -361,8 +377,6 @@ int snd_card_disconnect(struct snd_card *card) | |||
361 | 377 | ||
362 | mfile->file->f_op = &snd_shutdown_f_ops; | 378 | mfile->file->f_op = &snd_shutdown_f_ops; |
363 | fops_get(mfile->file->f_op); | 379 | fops_get(mfile->file->f_op); |
364 | |||
365 | mfile = mfile->next; | ||
366 | } | 380 | } |
367 | spin_unlock(&card->files_lock); | 381 | spin_unlock(&card->files_lock); |
368 | 382 | ||
@@ -442,7 +456,7 @@ int snd_card_free_when_closed(struct snd_card *card) | |||
442 | return ret; | 456 | return ret; |
443 | 457 | ||
444 | spin_lock(&card->files_lock); | 458 | spin_lock(&card->files_lock); |
445 | if (card->files == NULL) | 459 | if (list_empty(&card->files_list)) |
446 | free_now = 1; | 460 | free_now = 1; |
447 | else | 461 | else |
448 | card->free_on_last_close = 1; | 462 | card->free_on_last_close = 1; |
@@ -462,7 +476,7 @@ int snd_card_free(struct snd_card *card) | |||
462 | return ret; | 476 | return ret; |
463 | 477 | ||
464 | /* wait, until all devices are ready for the free operation */ | 478 | /* wait, until all devices are ready for the free operation */ |
465 | wait_event(card->shutdown_sleep, card->files == NULL); | 479 | wait_event(card->shutdown_sleep, list_empty(&card->files_list)); |
466 | snd_card_do_free(card); | 480 | snd_card_do_free(card); |
467 | return 0; | 481 | return 0; |
468 | } | 482 | } |
@@ -809,15 +823,13 @@ int snd_card_file_add(struct snd_card *card, struct file *file) | |||
809 | return -ENOMEM; | 823 | return -ENOMEM; |
810 | mfile->file = file; | 824 | mfile->file = file; |
811 | mfile->disconnected_f_op = NULL; | 825 | mfile->disconnected_f_op = NULL; |
812 | mfile->next = NULL; | ||
813 | spin_lock(&card->files_lock); | 826 | spin_lock(&card->files_lock); |
814 | if (card->shutdown) { | 827 | if (card->shutdown) { |
815 | spin_unlock(&card->files_lock); | 828 | spin_unlock(&card->files_lock); |
816 | kfree(mfile); | 829 | kfree(mfile); |
817 | return -ENODEV; | 830 | return -ENODEV; |
818 | } | 831 | } |
819 | mfile->next = card->files; | 832 | list_add(&mfile->list, &card->files_list); |
820 | card->files = mfile; | ||
821 | spin_unlock(&card->files_lock); | 833 | spin_unlock(&card->files_lock); |
822 | return 0; | 834 | return 0; |
823 | } | 835 | } |
@@ -839,29 +851,20 @@ EXPORT_SYMBOL(snd_card_file_add); | |||
839 | */ | 851 | */ |
840 | int snd_card_file_remove(struct snd_card *card, struct file *file) | 852 | int snd_card_file_remove(struct snd_card *card, struct file *file) |
841 | { | 853 | { |
842 | struct snd_monitor_file *mfile, *pfile = NULL; | 854 | struct snd_monitor_file *mfile, *found = NULL; |
843 | int last_close = 0; | 855 | int last_close = 0; |
844 | 856 | ||
845 | spin_lock(&card->files_lock); | 857 | spin_lock(&card->files_lock); |
846 | mfile = card->files; | 858 | list_for_each_entry(mfile, &card->files_list, list) { |
847 | while (mfile) { | ||
848 | if (mfile->file == file) { | 859 | if (mfile->file == file) { |
849 | if (pfile) | 860 | list_del(&mfile->list); |
850 | pfile->next = mfile->next; | 861 | if (mfile->disconnected_f_op) |
851 | else | 862 | fops_put(mfile->disconnected_f_op); |
852 | card->files = mfile->next; | 863 | found = mfile; |
853 | break; | 864 | break; |
854 | } | 865 | } |
855 | pfile = mfile; | ||
856 | mfile = mfile->next; | ||
857 | } | ||
858 | if (mfile && mfile->disconnected_f_op) { | ||
859 | fops_put(mfile->disconnected_f_op); | ||
860 | spin_lock(&shutdown_lock); | ||
861 | list_del(&mfile->shutdown_list); | ||
862 | spin_unlock(&shutdown_lock); | ||
863 | } | 866 | } |
864 | if (card->files == NULL) | 867 | if (list_empty(&card->files_list)) |
865 | last_close = 1; | 868 | last_close = 1; |
866 | spin_unlock(&card->files_lock); | 869 | spin_unlock(&card->files_lock); |
867 | if (last_close) { | 870 | if (last_close) { |
@@ -869,11 +872,11 @@ int snd_card_file_remove(struct snd_card *card, struct file *file) | |||
869 | if (card->free_on_last_close) | 872 | if (card->free_on_last_close) |
870 | snd_card_do_free(card); | 873 | snd_card_do_free(card); |
871 | } | 874 | } |
872 | if (!mfile) { | 875 | if (!found) { |
873 | snd_printk(KERN_ERR "ALSA card file remove problem (%p)\n", file); | 876 | snd_printk(KERN_ERR "ALSA card file remove problem (%p)\n", file); |
874 | return -ENOENT; | 877 | return -ENOENT; |
875 | } | 878 | } |
876 | kfree(mfile); | 879 | kfree(found); |
877 | return 0; | 880 | return 0; |
878 | } | 881 | } |
879 | 882 | ||
diff --git a/sound/core/jack.c b/sound/core/jack.c index 077a85262c1c..c8254c667c62 100644 --- a/sound/core/jack.c +++ b/sound/core/jack.c | |||
@@ -23,6 +23,14 @@ | |||
23 | #include <sound/jack.h> | 23 | #include <sound/jack.h> |
24 | #include <sound/core.h> | 24 | #include <sound/core.h> |
25 | 25 | ||
26 | static int jack_types[] = { | ||
27 | SW_HEADPHONE_INSERT, | ||
28 | SW_MICROPHONE_INSERT, | ||
29 | SW_LINEOUT_INSERT, | ||
30 | SW_JACK_PHYSICAL_INSERT, | ||
31 | SW_VIDEOOUT_INSERT, | ||
32 | }; | ||
33 | |||
26 | static int snd_jack_dev_free(struct snd_device *device) | 34 | static int snd_jack_dev_free(struct snd_device *device) |
27 | { | 35 | { |
28 | struct snd_jack *jack = device->device_data; | 36 | struct snd_jack *jack = device->device_data; |
@@ -79,6 +87,7 @@ int snd_jack_new(struct snd_card *card, const char *id, int type, | |||
79 | { | 87 | { |
80 | struct snd_jack *jack; | 88 | struct snd_jack *jack; |
81 | int err; | 89 | int err; |
90 | int i; | ||
82 | static struct snd_device_ops ops = { | 91 | static struct snd_device_ops ops = { |
83 | .dev_free = snd_jack_dev_free, | 92 | .dev_free = snd_jack_dev_free, |
84 | .dev_register = snd_jack_dev_register, | 93 | .dev_register = snd_jack_dev_register, |
@@ -100,18 +109,10 @@ int snd_jack_new(struct snd_card *card, const char *id, int type, | |||
100 | 109 | ||
101 | jack->type = type; | 110 | jack->type = type; |
102 | 111 | ||
103 | if (type & SND_JACK_HEADPHONE) | 112 | for (i = 0; i < ARRAY_SIZE(jack_types); i++) |
104 | input_set_capability(jack->input_dev, EV_SW, | 113 | if (type & (1 << i)) |
105 | SW_HEADPHONE_INSERT); | 114 | input_set_capability(jack->input_dev, EV_SW, |
106 | if (type & SND_JACK_LINEOUT) | 115 | jack_types[i]); |
107 | input_set_capability(jack->input_dev, EV_SW, | ||
108 | SW_LINEOUT_INSERT); | ||
109 | if (type & SND_JACK_MICROPHONE) | ||
110 | input_set_capability(jack->input_dev, EV_SW, | ||
111 | SW_MICROPHONE_INSERT); | ||
112 | if (type & SND_JACK_MECHANICAL) | ||
113 | input_set_capability(jack->input_dev, EV_SW, | ||
114 | SW_JACK_PHYSICAL_INSERT); | ||
115 | 116 | ||
116 | err = snd_device_new(card, SNDRV_DEV_JACK, jack, &ops); | 117 | err = snd_device_new(card, SNDRV_DEV_JACK, jack, &ops); |
117 | if (err < 0) | 118 | if (err < 0) |
@@ -154,21 +155,17 @@ EXPORT_SYMBOL(snd_jack_set_parent); | |||
154 | */ | 155 | */ |
155 | void snd_jack_report(struct snd_jack *jack, int status) | 156 | void snd_jack_report(struct snd_jack *jack, int status) |
156 | { | 157 | { |
158 | int i; | ||
159 | |||
157 | if (!jack) | 160 | if (!jack) |
158 | return; | 161 | return; |
159 | 162 | ||
160 | if (jack->type & SND_JACK_HEADPHONE) | 163 | for (i = 0; i < ARRAY_SIZE(jack_types); i++) { |
161 | input_report_switch(jack->input_dev, SW_HEADPHONE_INSERT, | 164 | int testbit = 1 << i; |
162 | status & SND_JACK_HEADPHONE); | 165 | if (jack->type & testbit) |
163 | if (jack->type & SND_JACK_LINEOUT) | 166 | input_report_switch(jack->input_dev, jack_types[i], |
164 | input_report_switch(jack->input_dev, SW_LINEOUT_INSERT, | 167 | status & testbit); |
165 | status & SND_JACK_LINEOUT); | 168 | } |
166 | if (jack->type & SND_JACK_MICROPHONE) | ||
167 | input_report_switch(jack->input_dev, SW_MICROPHONE_INSERT, | ||
168 | status & SND_JACK_MICROPHONE); | ||
169 | if (jack->type & SND_JACK_MECHANICAL) | ||
170 | input_report_switch(jack->input_dev, SW_JACK_PHYSICAL_INSERT, | ||
171 | status & SND_JACK_MECHANICAL); | ||
172 | 169 | ||
173 | input_sync(jack->input_dev); | 170 | input_sync(jack->input_dev); |
174 | } | 171 | } |
diff --git a/sound/core/misc.c b/sound/core/misc.c index 38524f615d94..a9710e0c97af 100644 --- a/sound/core/misc.c +++ b/sound/core/misc.c | |||
@@ -95,12 +95,14 @@ snd_pci_quirk_lookup(struct pci_dev *pci, const struct snd_pci_quirk *list) | |||
95 | { | 95 | { |
96 | const struct snd_pci_quirk *q; | 96 | const struct snd_pci_quirk *q; |
97 | 97 | ||
98 | for (q = list; q->subvendor; q++) | 98 | for (q = list; q->subvendor; q++) { |
99 | if (q->subvendor == pci->subsystem_vendor && | 99 | if (q->subvendor != pci->subsystem_vendor) |
100 | (!q->subdevice || q->subdevice == pci->subsystem_device)) | 100 | continue; |
101 | if (!q->subdevice || | ||
102 | (pci->subsystem_device & q->subdevice_mask) == q->subdevice) | ||
101 | return q; | 103 | return q; |
104 | } | ||
102 | return NULL; | 105 | return NULL; |
103 | } | 106 | } |
104 | |||
105 | EXPORT_SYMBOL(snd_pci_quirk_lookup); | 107 | EXPORT_SYMBOL(snd_pci_quirk_lookup); |
106 | #endif | 108 | #endif |
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 699d2890535c..dda000b9684c 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c | |||
@@ -1160,9 +1160,11 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const | |||
1160 | runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { | 1160 | runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { |
1161 | #ifdef OSS_DEBUG | 1161 | #ifdef OSS_DEBUG |
1162 | if (runtime->status->state == SNDRV_PCM_STATE_XRUN) | 1162 | if (runtime->status->state == SNDRV_PCM_STATE_XRUN) |
1163 | printk("pcm_oss: write: recovering from XRUN\n"); | 1163 | printk(KERN_DEBUG "pcm_oss: write: " |
1164 | "recovering from XRUN\n"); | ||
1164 | else | 1165 | else |
1165 | printk("pcm_oss: write: recovering from SUSPEND\n"); | 1166 | printk(KERN_DEBUG "pcm_oss: write: " |
1167 | "recovering from SUSPEND\n"); | ||
1166 | #endif | 1168 | #endif |
1167 | ret = snd_pcm_oss_prepare(substream); | 1169 | ret = snd_pcm_oss_prepare(substream); |
1168 | if (ret < 0) | 1170 | if (ret < 0) |
@@ -1196,9 +1198,11 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p | |||
1196 | runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { | 1198 | runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { |
1197 | #ifdef OSS_DEBUG | 1199 | #ifdef OSS_DEBUG |
1198 | if (runtime->status->state == SNDRV_PCM_STATE_XRUN) | 1200 | if (runtime->status->state == SNDRV_PCM_STATE_XRUN) |
1199 | printk("pcm_oss: read: recovering from XRUN\n"); | 1201 | printk(KERN_DEBUG "pcm_oss: read: " |
1202 | "recovering from XRUN\n"); | ||
1200 | else | 1203 | else |
1201 | printk("pcm_oss: read: recovering from SUSPEND\n"); | 1204 | printk(KERN_DEBUG "pcm_oss: read: " |
1205 | "recovering from SUSPEND\n"); | ||
1202 | #endif | 1206 | #endif |
1203 | ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL); | 1207 | ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL); |
1204 | if (ret < 0) | 1208 | if (ret < 0) |
@@ -1242,9 +1246,11 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void | |||
1242 | runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { | 1246 | runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { |
1243 | #ifdef OSS_DEBUG | 1247 | #ifdef OSS_DEBUG |
1244 | if (runtime->status->state == SNDRV_PCM_STATE_XRUN) | 1248 | if (runtime->status->state == SNDRV_PCM_STATE_XRUN) |
1245 | printk("pcm_oss: writev: recovering from XRUN\n"); | 1249 | printk(KERN_DEBUG "pcm_oss: writev: " |
1250 | "recovering from XRUN\n"); | ||
1246 | else | 1251 | else |
1247 | printk("pcm_oss: writev: recovering from SUSPEND\n"); | 1252 | printk(KERN_DEBUG "pcm_oss: writev: " |
1253 | "recovering from SUSPEND\n"); | ||
1248 | #endif | 1254 | #endif |
1249 | ret = snd_pcm_oss_prepare(substream); | 1255 | ret = snd_pcm_oss_prepare(substream); |
1250 | if (ret < 0) | 1256 | if (ret < 0) |
@@ -1278,9 +1284,11 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void * | |||
1278 | runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { | 1284 | runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { |
1279 | #ifdef OSS_DEBUG | 1285 | #ifdef OSS_DEBUG |
1280 | if (runtime->status->state == SNDRV_PCM_STATE_XRUN) | 1286 | if (runtime->status->state == SNDRV_PCM_STATE_XRUN) |
1281 | printk("pcm_oss: readv: recovering from XRUN\n"); | 1287 | printk(KERN_DEBUG "pcm_oss: readv: " |
1288 | "recovering from XRUN\n"); | ||
1282 | else | 1289 | else |
1283 | printk("pcm_oss: readv: recovering from SUSPEND\n"); | 1290 | printk(KERN_DEBUG "pcm_oss: readv: " |
1291 | "recovering from SUSPEND\n"); | ||
1284 | #endif | 1292 | #endif |
1285 | ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL); | 1293 | ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL); |
1286 | if (ret < 0) | 1294 | if (ret < 0) |
@@ -1533,7 +1541,7 @@ static int snd_pcm_oss_sync1(struct snd_pcm_substream *substream, size_t size) | |||
1533 | init_waitqueue_entry(&wait, current); | 1541 | init_waitqueue_entry(&wait, current); |
1534 | add_wait_queue(&runtime->sleep, &wait); | 1542 | add_wait_queue(&runtime->sleep, &wait); |
1535 | #ifdef OSS_DEBUG | 1543 | #ifdef OSS_DEBUG |
1536 | printk("sync1: size = %li\n", size); | 1544 | printk(KERN_DEBUG "sync1: size = %li\n", size); |
1537 | #endif | 1545 | #endif |
1538 | while (1) { | 1546 | while (1) { |
1539 | result = snd_pcm_oss_write2(substream, runtime->oss.buffer, size, 1); | 1547 | result = snd_pcm_oss_write2(substream, runtime->oss.buffer, size, 1); |
@@ -1590,7 +1598,7 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file) | |||
1590 | mutex_lock(&runtime->oss.params_lock); | 1598 | mutex_lock(&runtime->oss.params_lock); |
1591 | if (runtime->oss.buffer_used > 0) { | 1599 | if (runtime->oss.buffer_used > 0) { |
1592 | #ifdef OSS_DEBUG | 1600 | #ifdef OSS_DEBUG |
1593 | printk("sync: buffer_used\n"); | 1601 | printk(KERN_DEBUG "sync: buffer_used\n"); |
1594 | #endif | 1602 | #endif |
1595 | size = (8 * (runtime->oss.period_bytes - runtime->oss.buffer_used) + 7) / width; | 1603 | size = (8 * (runtime->oss.period_bytes - runtime->oss.buffer_used) + 7) / width; |
1596 | snd_pcm_format_set_silence(format, | 1604 | snd_pcm_format_set_silence(format, |
@@ -1603,7 +1611,7 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file) | |||
1603 | } | 1611 | } |
1604 | } else if (runtime->oss.period_ptr > 0) { | 1612 | } else if (runtime->oss.period_ptr > 0) { |
1605 | #ifdef OSS_DEBUG | 1613 | #ifdef OSS_DEBUG |
1606 | printk("sync: period_ptr\n"); | 1614 | printk(KERN_DEBUG "sync: period_ptr\n"); |
1607 | #endif | 1615 | #endif |
1608 | size = runtime->oss.period_bytes - runtime->oss.period_ptr; | 1616 | size = runtime->oss.period_bytes - runtime->oss.period_ptr; |
1609 | snd_pcm_format_set_silence(format, | 1617 | snd_pcm_format_set_silence(format, |
@@ -1895,7 +1903,9 @@ static int snd_pcm_oss_set_fragment(struct snd_pcm_oss_file *pcm_oss_file, unsig | |||
1895 | 1903 | ||
1896 | static int snd_pcm_oss_nonblock(struct file * file) | 1904 | static int snd_pcm_oss_nonblock(struct file * file) |
1897 | { | 1905 | { |
1906 | spin_lock(&file->f_lock); | ||
1898 | file->f_flags |= O_NONBLOCK; | 1907 | file->f_flags |= O_NONBLOCK; |
1908 | spin_unlock(&file->f_lock); | ||
1899 | return 0; | 1909 | return 0; |
1900 | } | 1910 | } |
1901 | 1911 | ||
@@ -1952,7 +1962,7 @@ static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int tr | |||
1952 | int err, cmd; | 1962 | int err, cmd; |
1953 | 1963 | ||
1954 | #ifdef OSS_DEBUG | 1964 | #ifdef OSS_DEBUG |
1955 | printk("pcm_oss: trigger = 0x%x\n", trigger); | 1965 | printk(KERN_DEBUG "pcm_oss: trigger = 0x%x\n", trigger); |
1956 | #endif | 1966 | #endif |
1957 | 1967 | ||
1958 | psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; | 1968 | psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; |
@@ -2170,7 +2180,9 @@ static int snd_pcm_oss_get_space(struct snd_pcm_oss_file *pcm_oss_file, int stre | |||
2170 | } | 2180 | } |
2171 | 2181 | ||
2172 | #ifdef OSS_DEBUG | 2182 | #ifdef OSS_DEBUG |
2173 | printk("pcm_oss: space: bytes = %i, fragments = %i, fragstotal = %i, fragsize = %i\n", info.bytes, info.fragments, info.fragstotal, info.fragsize); | 2183 | printk(KERN_DEBUG "pcm_oss: space: bytes = %i, fragments = %i, " |
2184 | "fragstotal = %i, fragsize = %i\n", | ||
2185 | info.bytes, info.fragments, info.fragstotal, info.fragsize); | ||
2174 | #endif | 2186 | #endif |
2175 | if (copy_to_user(_info, &info, sizeof(info))) | 2187 | if (copy_to_user(_info, &info, sizeof(info))) |
2176 | return -EFAULT; | 2188 | return -EFAULT; |
@@ -2473,7 +2485,7 @@ static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long | |||
2473 | if (((cmd >> 8) & 0xff) != 'P') | 2485 | if (((cmd >> 8) & 0xff) != 'P') |
2474 | return -EINVAL; | 2486 | return -EINVAL; |
2475 | #ifdef OSS_DEBUG | 2487 | #ifdef OSS_DEBUG |
2476 | printk("pcm_oss: ioctl = 0x%x\n", cmd); | 2488 | printk(KERN_DEBUG "pcm_oss: ioctl = 0x%x\n", cmd); |
2477 | #endif | 2489 | #endif |
2478 | switch (cmd) { | 2490 | switch (cmd) { |
2479 | case SNDCTL_DSP_RESET: | 2491 | case SNDCTL_DSP_RESET: |
@@ -2627,7 +2639,8 @@ static ssize_t snd_pcm_oss_read(struct file *file, char __user *buf, size_t coun | |||
2627 | #else | 2639 | #else |
2628 | { | 2640 | { |
2629 | ssize_t res = snd_pcm_oss_read1(substream, buf, count); | 2641 | ssize_t res = snd_pcm_oss_read1(substream, buf, count); |
2630 | printk("pcm_oss: read %li bytes (returned %li bytes)\n", (long)count, (long)res); | 2642 | printk(KERN_DEBUG "pcm_oss: read %li bytes " |
2643 | "(returned %li bytes)\n", (long)count, (long)res); | ||
2631 | return res; | 2644 | return res; |
2632 | } | 2645 | } |
2633 | #endif | 2646 | #endif |
@@ -2646,7 +2659,8 @@ static ssize_t snd_pcm_oss_write(struct file *file, const char __user *buf, size | |||
2646 | substream->f_flags = file->f_flags & O_NONBLOCK; | 2659 | substream->f_flags = file->f_flags & O_NONBLOCK; |
2647 | result = snd_pcm_oss_write1(substream, buf, count); | 2660 | result = snd_pcm_oss_write1(substream, buf, count); |
2648 | #ifdef OSS_DEBUG | 2661 | #ifdef OSS_DEBUG |
2649 | printk("pcm_oss: write %li bytes (wrote %li bytes)\n", (long)count, (long)result); | 2662 | printk(KERN_DEBUG "pcm_oss: write %li bytes (wrote %li bytes)\n", |
2663 | (long)count, (long)result); | ||
2650 | #endif | 2664 | #endif |
2651 | return result; | 2665 | return result; |
2652 | } | 2666 | } |
@@ -2720,7 +2734,7 @@ static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area) | |||
2720 | int err; | 2734 | int err; |
2721 | 2735 | ||
2722 | #ifdef OSS_DEBUG | 2736 | #ifdef OSS_DEBUG |
2723 | printk("pcm_oss: mmap begin\n"); | 2737 | printk(KERN_DEBUG "pcm_oss: mmap begin\n"); |
2724 | #endif | 2738 | #endif |
2725 | pcm_oss_file = file->private_data; | 2739 | pcm_oss_file = file->private_data; |
2726 | switch ((area->vm_flags & (VM_READ | VM_WRITE))) { | 2740 | switch ((area->vm_flags & (VM_READ | VM_WRITE))) { |
@@ -2770,7 +2784,8 @@ static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area) | |||
2770 | runtime->silence_threshold = 0; | 2784 | runtime->silence_threshold = 0; |
2771 | runtime->silence_size = 0; | 2785 | runtime->silence_size = 0; |
2772 | #ifdef OSS_DEBUG | 2786 | #ifdef OSS_DEBUG |
2773 | printk("pcm_oss: mmap ok, bytes = 0x%x\n", runtime->oss.mmap_bytes); | 2787 | printk(KERN_DEBUG "pcm_oss: mmap ok, bytes = 0x%x\n", |
2788 | runtime->oss.mmap_bytes); | ||
2774 | #endif | 2789 | #endif |
2775 | /* In mmap mode we never stop */ | 2790 | /* In mmap mode we never stop */ |
2776 | runtime->stop_threshold = runtime->boundary; | 2791 | runtime->stop_threshold = runtime->boundary; |
diff --git a/sound/core/oss/pcm_plugin.h b/sound/core/oss/pcm_plugin.h index ca2f4c39be46..b9afab603711 100644 --- a/sound/core/oss/pcm_plugin.h +++ b/sound/core/oss/pcm_plugin.h | |||
@@ -176,9 +176,9 @@ static inline int snd_pcm_plug_slave_format(int format, struct snd_mask *format_ | |||
176 | #endif | 176 | #endif |
177 | 177 | ||
178 | #ifdef PLUGIN_DEBUG | 178 | #ifdef PLUGIN_DEBUG |
179 | #define pdprintf( fmt, args... ) printk( "plugin: " fmt, ##args) | 179 | #define pdprintf(fmt, args...) printk(KERN_DEBUG "plugin: " fmt, ##args) |
180 | #else | 180 | #else |
181 | #define pdprintf( fmt, args... ) | 181 | #define pdprintf(fmt, args...) |
182 | #endif | 182 | #endif |
183 | 183 | ||
184 | #endif /* __PCM_PLUGIN_H */ | 184 | #endif /* __PCM_PLUGIN_H */ |
diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 192a433a2403..145931a9ff30 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c | |||
@@ -667,7 +667,6 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count) | |||
667 | spin_lock_init(&substream->self_group.lock); | 667 | spin_lock_init(&substream->self_group.lock); |
668 | INIT_LIST_HEAD(&substream->self_group.substreams); | 668 | INIT_LIST_HEAD(&substream->self_group.substreams); |
669 | list_add_tail(&substream->link_list, &substream->self_group.substreams); | 669 | list_add_tail(&substream->link_list, &substream->self_group.substreams); |
670 | spin_lock_init(&substream->timer_lock); | ||
671 | atomic_set(&substream->mmap_count, 0); | 670 | atomic_set(&substream->mmap_count, 0); |
672 | prev = substream; | 671 | prev = substream; |
673 | } | 672 | } |
@@ -692,7 +691,7 @@ EXPORT_SYMBOL(snd_pcm_new_stream); | |||
692 | * | 691 | * |
693 | * Returns zero if successful, or a negative error code on failure. | 692 | * Returns zero if successful, or a negative error code on failure. |
694 | */ | 693 | */ |
695 | int snd_pcm_new(struct snd_card *card, char *id, int device, | 694 | int snd_pcm_new(struct snd_card *card, const char *id, int device, |
696 | int playback_count, int capture_count, | 695 | int playback_count, int capture_count, |
697 | struct snd_pcm ** rpcm) | 696 | struct snd_pcm ** rpcm) |
698 | { | 697 | { |
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 921691080f35..fbb2e391591e 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c | |||
@@ -125,23 +125,32 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram | |||
125 | } | 125 | } |
126 | } | 126 | } |
127 | 127 | ||
128 | #ifdef CONFIG_SND_PCM_XRUN_DEBUG | ||
129 | #define xrun_debug(substream) ((substream)->pstr->xrun_debug) | ||
130 | #else | ||
131 | #define xrun_debug(substream) 0 | ||
132 | #endif | ||
133 | |||
134 | #define dump_stack_on_xrun(substream) do { \ | ||
135 | if (xrun_debug(substream) > 1) \ | ||
136 | dump_stack(); \ | ||
137 | } while (0) | ||
138 | |||
128 | static void xrun(struct snd_pcm_substream *substream) | 139 | static void xrun(struct snd_pcm_substream *substream) |
129 | { | 140 | { |
130 | snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); | 141 | snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); |
131 | #ifdef CONFIG_SND_PCM_XRUN_DEBUG | 142 | if (xrun_debug(substream)) { |
132 | if (substream->pstr->xrun_debug) { | ||
133 | snd_printd(KERN_DEBUG "XRUN: pcmC%dD%d%c\n", | 143 | snd_printd(KERN_DEBUG "XRUN: pcmC%dD%d%c\n", |
134 | substream->pcm->card->number, | 144 | substream->pcm->card->number, |
135 | substream->pcm->device, | 145 | substream->pcm->device, |
136 | substream->stream ? 'c' : 'p'); | 146 | substream->stream ? 'c' : 'p'); |
137 | if (substream->pstr->xrun_debug > 1) | 147 | dump_stack_on_xrun(substream); |
138 | dump_stack(); | ||
139 | } | 148 | } |
140 | #endif | ||
141 | } | 149 | } |
142 | 150 | ||
143 | static inline snd_pcm_uframes_t snd_pcm_update_hw_ptr_pos(struct snd_pcm_substream *substream, | 151 | static snd_pcm_uframes_t |
144 | struct snd_pcm_runtime *runtime) | 152 | snd_pcm_update_hw_ptr_pos(struct snd_pcm_substream *substream, |
153 | struct snd_pcm_runtime *runtime) | ||
145 | { | 154 | { |
146 | snd_pcm_uframes_t pos; | 155 | snd_pcm_uframes_t pos; |
147 | 156 | ||
@@ -150,17 +159,21 @@ static inline snd_pcm_uframes_t snd_pcm_update_hw_ptr_pos(struct snd_pcm_substre | |||
150 | pos = substream->ops->pointer(substream); | 159 | pos = substream->ops->pointer(substream); |
151 | if (pos == SNDRV_PCM_POS_XRUN) | 160 | if (pos == SNDRV_PCM_POS_XRUN) |
152 | return pos; /* XRUN */ | 161 | return pos; /* XRUN */ |
153 | #ifdef CONFIG_SND_DEBUG | ||
154 | if (pos >= runtime->buffer_size) { | 162 | if (pos >= runtime->buffer_size) { |
155 | snd_printk(KERN_ERR "BUG: stream = %i, pos = 0x%lx, buffer size = 0x%lx, period size = 0x%lx\n", substream->stream, pos, runtime->buffer_size, runtime->period_size); | 163 | if (printk_ratelimit()) { |
164 | snd_printd(KERN_ERR "BUG: stream = %i, pos = 0x%lx, " | ||
165 | "buffer size = 0x%lx, period size = 0x%lx\n", | ||
166 | substream->stream, pos, runtime->buffer_size, | ||
167 | runtime->period_size); | ||
168 | } | ||
169 | pos = 0; | ||
156 | } | 170 | } |
157 | #endif | ||
158 | pos -= pos % runtime->min_align; | 171 | pos -= pos % runtime->min_align; |
159 | return pos; | 172 | return pos; |
160 | } | 173 | } |
161 | 174 | ||
162 | static inline int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream, | 175 | static int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream, |
163 | struct snd_pcm_runtime *runtime) | 176 | struct snd_pcm_runtime *runtime) |
164 | { | 177 | { |
165 | snd_pcm_uframes_t avail; | 178 | snd_pcm_uframes_t avail; |
166 | 179 | ||
@@ -182,11 +195,21 @@ static inline int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream | |||
182 | return 0; | 195 | return 0; |
183 | } | 196 | } |
184 | 197 | ||
185 | static inline int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream) | 198 | #define hw_ptr_error(substream, fmt, args...) \ |
199 | do { \ | ||
200 | if (xrun_debug(substream)) { \ | ||
201 | if (printk_ratelimit()) { \ | ||
202 | snd_printd("PCM: " fmt, ##args); \ | ||
203 | } \ | ||
204 | dump_stack_on_xrun(substream); \ | ||
205 | } \ | ||
206 | } while (0) | ||
207 | |||
208 | static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream) | ||
186 | { | 209 | { |
187 | struct snd_pcm_runtime *runtime = substream->runtime; | 210 | struct snd_pcm_runtime *runtime = substream->runtime; |
188 | snd_pcm_uframes_t pos; | 211 | snd_pcm_uframes_t pos; |
189 | snd_pcm_uframes_t new_hw_ptr, hw_ptr_interrupt; | 212 | snd_pcm_uframes_t new_hw_ptr, hw_ptr_interrupt, hw_base; |
190 | snd_pcm_sframes_t delta; | 213 | snd_pcm_sframes_t delta; |
191 | 214 | ||
192 | pos = snd_pcm_update_hw_ptr_pos(substream, runtime); | 215 | pos = snd_pcm_update_hw_ptr_pos(substream, runtime); |
@@ -194,36 +217,53 @@ static inline int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *subs | |||
194 | xrun(substream); | 217 | xrun(substream); |
195 | return -EPIPE; | 218 | return -EPIPE; |
196 | } | 219 | } |
197 | if (runtime->period_size == runtime->buffer_size) | 220 | hw_base = runtime->hw_ptr_base; |
198 | goto __next_buf; | 221 | new_hw_ptr = hw_base + pos; |
199 | new_hw_ptr = runtime->hw_ptr_base + pos; | ||
200 | hw_ptr_interrupt = runtime->hw_ptr_interrupt + runtime->period_size; | 222 | hw_ptr_interrupt = runtime->hw_ptr_interrupt + runtime->period_size; |
201 | 223 | delta = new_hw_ptr - hw_ptr_interrupt; | |
202 | delta = hw_ptr_interrupt - new_hw_ptr; | 224 | if (hw_ptr_interrupt >= runtime->boundary) { |
203 | if (delta > 0) { | 225 | hw_ptr_interrupt -= runtime->boundary; |
204 | if ((snd_pcm_uframes_t)delta < runtime->buffer_size / 2) { | 226 | if (hw_base < runtime->boundary / 2) |
205 | #ifdef CONFIG_SND_PCM_XRUN_DEBUG | 227 | /* hw_base was already lapped; recalc delta */ |
206 | if (runtime->periods > 1 && substream->pstr->xrun_debug) { | 228 | delta = new_hw_ptr - hw_ptr_interrupt; |
207 | snd_printd(KERN_ERR "Unexpected hw_pointer value [1] (stream = %i, delta: -%ld, max jitter = %ld): wrong interrupt acknowledge?\n", substream->stream, (long) delta, runtime->buffer_size / 2); | 229 | } |
208 | if (substream->pstr->xrun_debug > 1) | 230 | if (delta < 0) { |
209 | dump_stack(); | 231 | delta += runtime->buffer_size; |
210 | } | 232 | if (delta < 0) { |
211 | #endif | 233 | hw_ptr_error(substream, |
212 | return 0; | 234 | "Unexpected hw_pointer value " |
235 | "(stream=%i, pos=%ld, intr_ptr=%ld)\n", | ||
236 | substream->stream, (long)pos, | ||
237 | (long)hw_ptr_interrupt); | ||
238 | /* rebase to interrupt position */ | ||
239 | hw_base = new_hw_ptr = hw_ptr_interrupt; | ||
240 | /* align hw_base to buffer_size */ | ||
241 | hw_base -= hw_base % runtime->buffer_size; | ||
242 | delta = 0; | ||
243 | } else { | ||
244 | hw_base += runtime->buffer_size; | ||
245 | if (hw_base >= runtime->boundary) | ||
246 | hw_base = 0; | ||
247 | new_hw_ptr = hw_base + pos; | ||
213 | } | 248 | } |
214 | __next_buf: | ||
215 | runtime->hw_ptr_base += runtime->buffer_size; | ||
216 | if (runtime->hw_ptr_base == runtime->boundary) | ||
217 | runtime->hw_ptr_base = 0; | ||
218 | new_hw_ptr = runtime->hw_ptr_base + pos; | ||
219 | } | 249 | } |
220 | 250 | if (delta > runtime->period_size) { | |
251 | hw_ptr_error(substream, | ||
252 | "Lost interrupts? " | ||
253 | "(stream=%i, delta=%ld, intr_ptr=%ld)\n", | ||
254 | substream->stream, (long)delta, | ||
255 | (long)hw_ptr_interrupt); | ||
256 | /* rebase hw_ptr_interrupt */ | ||
257 | hw_ptr_interrupt = | ||
258 | new_hw_ptr - new_hw_ptr % runtime->period_size; | ||
259 | } | ||
221 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && | 260 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && |
222 | runtime->silence_size > 0) | 261 | runtime->silence_size > 0) |
223 | snd_pcm_playback_silence(substream, new_hw_ptr); | 262 | snd_pcm_playback_silence(substream, new_hw_ptr); |
224 | 263 | ||
264 | runtime->hw_ptr_base = hw_base; | ||
225 | runtime->status->hw_ptr = new_hw_ptr; | 265 | runtime->status->hw_ptr = new_hw_ptr; |
226 | runtime->hw_ptr_interrupt = new_hw_ptr - new_hw_ptr % runtime->period_size; | 266 | runtime->hw_ptr_interrupt = hw_ptr_interrupt; |
227 | 267 | ||
228 | return snd_pcm_update_hw_ptr_post(substream, runtime); | 268 | return snd_pcm_update_hw_ptr_post(substream, runtime); |
229 | } | 269 | } |
@@ -233,7 +273,7 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream) | |||
233 | { | 273 | { |
234 | struct snd_pcm_runtime *runtime = substream->runtime; | 274 | struct snd_pcm_runtime *runtime = substream->runtime; |
235 | snd_pcm_uframes_t pos; | 275 | snd_pcm_uframes_t pos; |
236 | snd_pcm_uframes_t old_hw_ptr, new_hw_ptr; | 276 | snd_pcm_uframes_t old_hw_ptr, new_hw_ptr, hw_base; |
237 | snd_pcm_sframes_t delta; | 277 | snd_pcm_sframes_t delta; |
238 | 278 | ||
239 | old_hw_ptr = runtime->status->hw_ptr; | 279 | old_hw_ptr = runtime->status->hw_ptr; |
@@ -242,29 +282,38 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream) | |||
242 | xrun(substream); | 282 | xrun(substream); |
243 | return -EPIPE; | 283 | return -EPIPE; |
244 | } | 284 | } |
245 | new_hw_ptr = runtime->hw_ptr_base + pos; | 285 | hw_base = runtime->hw_ptr_base; |
246 | 286 | new_hw_ptr = hw_base + pos; | |
247 | delta = old_hw_ptr - new_hw_ptr; | 287 | |
248 | if (delta > 0) { | 288 | delta = new_hw_ptr - old_hw_ptr; |
249 | if ((snd_pcm_uframes_t)delta < runtime->buffer_size / 2) { | 289 | if (delta < 0) { |
250 | #ifdef CONFIG_SND_PCM_XRUN_DEBUG | 290 | delta += runtime->buffer_size; |
251 | if (runtime->periods > 2 && substream->pstr->xrun_debug) { | 291 | if (delta < 0) { |
252 | snd_printd(KERN_ERR "Unexpected hw_pointer value [2] (stream = %i, delta: -%ld, max jitter = %ld): wrong interrupt acknowledge?\n", substream->stream, (long) delta, runtime->buffer_size / 2); | 292 | hw_ptr_error(substream, |
253 | if (substream->pstr->xrun_debug > 1) | 293 | "Unexpected hw_pointer value [2] " |
254 | dump_stack(); | 294 | "(stream=%i, pos=%ld, old_ptr=%ld)\n", |
255 | } | 295 | substream->stream, (long)pos, |
256 | #endif | 296 | (long)old_hw_ptr); |
257 | return 0; | 297 | return 0; |
258 | } | 298 | } |
259 | runtime->hw_ptr_base += runtime->buffer_size; | 299 | hw_base += runtime->buffer_size; |
260 | if (runtime->hw_ptr_base == runtime->boundary) | 300 | if (hw_base >= runtime->boundary) |
261 | runtime->hw_ptr_base = 0; | 301 | hw_base = 0; |
262 | new_hw_ptr = runtime->hw_ptr_base + pos; | 302 | new_hw_ptr = hw_base + pos; |
303 | } | ||
304 | if (delta > runtime->period_size && runtime->periods > 1) { | ||
305 | hw_ptr_error(substream, | ||
306 | "hw_ptr skipping! " | ||
307 | "(pos=%ld, delta=%ld, period=%ld)\n", | ||
308 | (long)pos, (long)delta, | ||
309 | (long)runtime->period_size); | ||
310 | return 0; | ||
263 | } | 311 | } |
264 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && | 312 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && |
265 | runtime->silence_size > 0) | 313 | runtime->silence_size > 0) |
266 | snd_pcm_playback_silence(substream, new_hw_ptr); | 314 | snd_pcm_playback_silence(substream, new_hw_ptr); |
267 | 315 | ||
316 | runtime->hw_ptr_base = hw_base; | ||
268 | runtime->status->hw_ptr = new_hw_ptr; | 317 | runtime->status->hw_ptr = new_hw_ptr; |
269 | 318 | ||
270 | return snd_pcm_update_hw_ptr_post(substream, runtime); | 319 | return snd_pcm_update_hw_ptr_post(substream, runtime); |
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index a789efc9df39..a151fb01ba82 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c | |||
@@ -186,7 +186,7 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream, | |||
186 | if (!(params->rmask & (1 << k))) | 186 | if (!(params->rmask & (1 << k))) |
187 | continue; | 187 | continue; |
188 | #ifdef RULES_DEBUG | 188 | #ifdef RULES_DEBUG |
189 | printk("%s = ", snd_pcm_hw_param_names[k]); | 189 | printk(KERN_DEBUG "%s = ", snd_pcm_hw_param_names[k]); |
190 | printk("%04x%04x%04x%04x -> ", m->bits[3], m->bits[2], m->bits[1], m->bits[0]); | 190 | printk("%04x%04x%04x%04x -> ", m->bits[3], m->bits[2], m->bits[1], m->bits[0]); |
191 | #endif | 191 | #endif |
192 | changed = snd_mask_refine(m, constrs_mask(constrs, k)); | 192 | changed = snd_mask_refine(m, constrs_mask(constrs, k)); |
@@ -206,7 +206,7 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream, | |||
206 | if (!(params->rmask & (1 << k))) | 206 | if (!(params->rmask & (1 << k))) |
207 | continue; | 207 | continue; |
208 | #ifdef RULES_DEBUG | 208 | #ifdef RULES_DEBUG |
209 | printk("%s = ", snd_pcm_hw_param_names[k]); | 209 | printk(KERN_DEBUG "%s = ", snd_pcm_hw_param_names[k]); |
210 | if (i->empty) | 210 | if (i->empty) |
211 | printk("empty"); | 211 | printk("empty"); |
212 | else | 212 | else |
@@ -251,7 +251,7 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream, | |||
251 | if (!doit) | 251 | if (!doit) |
252 | continue; | 252 | continue; |
253 | #ifdef RULES_DEBUG | 253 | #ifdef RULES_DEBUG |
254 | printk("Rule %d [%p]: ", k, r->func); | 254 | printk(KERN_DEBUG "Rule %d [%p]: ", k, r->func); |
255 | if (r->var >= 0) { | 255 | if (r->var >= 0) { |
256 | printk("%s = ", snd_pcm_hw_param_names[r->var]); | 256 | printk("%s = ", snd_pcm_hw_param_names[r->var]); |
257 | if (hw_is_mask(r->var)) { | 257 | if (hw_is_mask(r->var)) { |
@@ -3246,9 +3246,7 @@ static int snd_pcm_fasync(int fd, struct file * file, int on) | |||
3246 | err = fasync_helper(fd, file, on, &runtime->fasync); | 3246 | err = fasync_helper(fd, file, on, &runtime->fasync); |
3247 | out: | 3247 | out: |
3248 | unlock_kernel(); | 3248 | unlock_kernel(); |
3249 | if (err < 0) | 3249 | return err; |
3250 | return err; | ||
3251 | return 0; | ||
3252 | } | 3250 | } |
3253 | 3251 | ||
3254 | /* | 3252 | /* |
diff --git a/sound/core/pcm_timer.c b/sound/core/pcm_timer.c index 2c89c04f2916..ca8068b63d6c 100644 --- a/sound/core/pcm_timer.c +++ b/sound/core/pcm_timer.c | |||
@@ -85,25 +85,19 @@ static unsigned long snd_pcm_timer_resolution(struct snd_timer * timer) | |||
85 | 85 | ||
86 | static int snd_pcm_timer_start(struct snd_timer * timer) | 86 | static int snd_pcm_timer_start(struct snd_timer * timer) |
87 | { | 87 | { |
88 | unsigned long flags; | ||
89 | struct snd_pcm_substream *substream; | 88 | struct snd_pcm_substream *substream; |
90 | 89 | ||
91 | substream = snd_timer_chip(timer); | 90 | substream = snd_timer_chip(timer); |
92 | spin_lock_irqsave(&substream->timer_lock, flags); | ||
93 | substream->timer_running = 1; | 91 | substream->timer_running = 1; |
94 | spin_unlock_irqrestore(&substream->timer_lock, flags); | ||
95 | return 0; | 92 | return 0; |
96 | } | 93 | } |
97 | 94 | ||
98 | static int snd_pcm_timer_stop(struct snd_timer * timer) | 95 | static int snd_pcm_timer_stop(struct snd_timer * timer) |
99 | { | 96 | { |
100 | unsigned long flags; | ||
101 | struct snd_pcm_substream *substream; | 97 | struct snd_pcm_substream *substream; |
102 | 98 | ||
103 | substream = snd_timer_chip(timer); | 99 | substream = snd_timer_chip(timer); |
104 | spin_lock_irqsave(&substream->timer_lock, flags); | ||
105 | substream->timer_running = 0; | 100 | substream->timer_running = 0; |
106 | spin_unlock_irqrestore(&substream->timer_lock, flags); | ||
107 | return 0; | 101 | return 0; |
108 | } | 102 | } |
109 | 103 | ||
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 002777ba336a..473247c8e6d3 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c | |||
@@ -224,156 +224,143 @@ int snd_rawmidi_drain_input(struct snd_rawmidi_substream *substream) | |||
224 | return 0; | 224 | return 0; |
225 | } | 225 | } |
226 | 226 | ||
227 | int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice, | 227 | /* look for an available substream for the given stream direction; |
228 | int mode, struct snd_rawmidi_file * rfile) | 228 | * if a specific subdevice is given, try to assign it |
229 | */ | ||
230 | static int assign_substream(struct snd_rawmidi *rmidi, int subdevice, | ||
231 | int stream, int mode, | ||
232 | struct snd_rawmidi_substream **sub_ret) | ||
233 | { | ||
234 | struct snd_rawmidi_substream *substream; | ||
235 | struct snd_rawmidi_str *s = &rmidi->streams[stream]; | ||
236 | static unsigned int info_flags[2] = { | ||
237 | [SNDRV_RAWMIDI_STREAM_OUTPUT] = SNDRV_RAWMIDI_INFO_OUTPUT, | ||
238 | [SNDRV_RAWMIDI_STREAM_INPUT] = SNDRV_RAWMIDI_INFO_INPUT, | ||
239 | }; | ||
240 | |||
241 | if (!(rmidi->info_flags & info_flags[stream])) | ||
242 | return -ENXIO; | ||
243 | if (subdevice >= 0 && subdevice >= s->substream_count) | ||
244 | return -ENODEV; | ||
245 | if (s->substream_opened >= s->substream_count) | ||
246 | return -EAGAIN; | ||
247 | |||
248 | list_for_each_entry(substream, &s->substreams, list) { | ||
249 | if (substream->opened) { | ||
250 | if (stream == SNDRV_RAWMIDI_STREAM_INPUT || | ||
251 | !(mode & SNDRV_RAWMIDI_LFLG_APPEND)) | ||
252 | continue; | ||
253 | } | ||
254 | if (subdevice < 0 || subdevice == substream->number) { | ||
255 | *sub_ret = substream; | ||
256 | return 0; | ||
257 | } | ||
258 | } | ||
259 | return -EAGAIN; | ||
260 | } | ||
261 | |||
262 | /* open and do ref-counting for the given substream */ | ||
263 | static int open_substream(struct snd_rawmidi *rmidi, | ||
264 | struct snd_rawmidi_substream *substream, | ||
265 | int mode) | ||
266 | { | ||
267 | int err; | ||
268 | |||
269 | err = snd_rawmidi_runtime_create(substream); | ||
270 | if (err < 0) | ||
271 | return err; | ||
272 | err = substream->ops->open(substream); | ||
273 | if (err < 0) | ||
274 | return err; | ||
275 | substream->opened = 1; | ||
276 | if (substream->use_count++ == 0) | ||
277 | substream->active_sensing = 1; | ||
278 | if (mode & SNDRV_RAWMIDI_LFLG_APPEND) | ||
279 | substream->append = 1; | ||
280 | rmidi->streams[substream->stream].substream_opened++; | ||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | static void close_substream(struct snd_rawmidi *rmidi, | ||
285 | struct snd_rawmidi_substream *substream, | ||
286 | int cleanup); | ||
287 | |||
288 | static int rawmidi_open_priv(struct snd_rawmidi *rmidi, int subdevice, int mode, | ||
289 | struct snd_rawmidi_file *rfile) | ||
229 | { | 290 | { |
230 | struct snd_rawmidi *rmidi; | ||
231 | struct list_head *list1, *list2; | ||
232 | struct snd_rawmidi_substream *sinput = NULL, *soutput = NULL; | 291 | struct snd_rawmidi_substream *sinput = NULL, *soutput = NULL; |
233 | struct snd_rawmidi_runtime *input = NULL, *output = NULL; | ||
234 | int err; | 292 | int err; |
235 | 293 | ||
236 | if (rfile) | 294 | rfile->input = rfile->output = NULL; |
237 | rfile->input = rfile->output = NULL; | ||
238 | mutex_lock(®ister_mutex); | ||
239 | rmidi = snd_rawmidi_search(card, device); | ||
240 | mutex_unlock(®ister_mutex); | ||
241 | if (rmidi == NULL) { | ||
242 | err = -ENODEV; | ||
243 | goto __error1; | ||
244 | } | ||
245 | if (!try_module_get(rmidi->card->module)) { | ||
246 | err = -EFAULT; | ||
247 | goto __error1; | ||
248 | } | ||
249 | if (!(mode & SNDRV_RAWMIDI_LFLG_NOOPENLOCK)) | ||
250 | mutex_lock(&rmidi->open_mutex); | ||
251 | if (mode & SNDRV_RAWMIDI_LFLG_INPUT) { | 295 | if (mode & SNDRV_RAWMIDI_LFLG_INPUT) { |
252 | if (!(rmidi->info_flags & SNDRV_RAWMIDI_INFO_INPUT)) { | 296 | err = assign_substream(rmidi, subdevice, |
253 | err = -ENXIO; | 297 | SNDRV_RAWMIDI_STREAM_INPUT, |
254 | goto __error; | 298 | mode, &sinput); |
255 | } | 299 | if (err < 0) |
256 | if (subdevice >= 0 && (unsigned int)subdevice >= rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_count) { | ||
257 | err = -ENODEV; | ||
258 | goto __error; | ||
259 | } | ||
260 | if (rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_opened >= | ||
261 | rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_count) { | ||
262 | err = -EAGAIN; | ||
263 | goto __error; | 300 | goto __error; |
264 | } | ||
265 | } | 301 | } |
266 | if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) { | 302 | if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) { |
267 | if (!(rmidi->info_flags & SNDRV_RAWMIDI_INFO_OUTPUT)) { | 303 | err = assign_substream(rmidi, subdevice, |
268 | err = -ENXIO; | 304 | SNDRV_RAWMIDI_STREAM_OUTPUT, |
269 | goto __error; | 305 | mode, &soutput); |
270 | } | 306 | if (err < 0) |
271 | if (subdevice >= 0 && (unsigned int)subdevice >= rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substream_count) { | ||
272 | err = -ENODEV; | ||
273 | goto __error; | ||
274 | } | ||
275 | if (rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substream_opened >= | ||
276 | rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substream_count) { | ||
277 | err = -EAGAIN; | ||
278 | goto __error; | 307 | goto __error; |
279 | } | ||
280 | } | ||
281 | list1 = rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams.next; | ||
282 | while (1) { | ||
283 | if (list1 == &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams) { | ||
284 | sinput = NULL; | ||
285 | if (mode & SNDRV_RAWMIDI_LFLG_INPUT) { | ||
286 | err = -EAGAIN; | ||
287 | goto __error; | ||
288 | } | ||
289 | break; | ||
290 | } | ||
291 | sinput = list_entry(list1, struct snd_rawmidi_substream, list); | ||
292 | if ((mode & SNDRV_RAWMIDI_LFLG_INPUT) && sinput->opened) | ||
293 | goto __nexti; | ||
294 | if (subdevice < 0 || (subdevice >= 0 && subdevice == sinput->number)) | ||
295 | break; | ||
296 | __nexti: | ||
297 | list1 = list1->next; | ||
298 | } | 308 | } |
299 | list2 = rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams.next; | 309 | |
300 | while (1) { | 310 | if (sinput) { |
301 | if (list2 == &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams) { | 311 | err = open_substream(rmidi, sinput, mode); |
302 | soutput = NULL; | 312 | if (err < 0) |
303 | if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) { | ||
304 | err = -EAGAIN; | ||
305 | goto __error; | ||
306 | } | ||
307 | break; | ||
308 | } | ||
309 | soutput = list_entry(list2, struct snd_rawmidi_substream, list); | ||
310 | if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) { | ||
311 | if (mode & SNDRV_RAWMIDI_LFLG_APPEND) { | ||
312 | if (soutput->opened && !soutput->append) | ||
313 | goto __nexto; | ||
314 | } else { | ||
315 | if (soutput->opened) | ||
316 | goto __nexto; | ||
317 | } | ||
318 | } | ||
319 | if (subdevice < 0 || (subdevice >= 0 && subdevice == soutput->number)) | ||
320 | break; | ||
321 | __nexto: | ||
322 | list2 = list2->next; | ||
323 | } | ||
324 | if (mode & SNDRV_RAWMIDI_LFLG_INPUT) { | ||
325 | if ((err = snd_rawmidi_runtime_create(sinput)) < 0) | ||
326 | goto __error; | ||
327 | input = sinput->runtime; | ||
328 | if ((err = sinput->ops->open(sinput)) < 0) | ||
329 | goto __error; | 313 | goto __error; |
330 | sinput->opened = 1; | ||
331 | rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_opened++; | ||
332 | } else { | ||
333 | sinput = NULL; | ||
334 | } | 314 | } |
335 | if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) { | 315 | if (soutput) { |
336 | if (soutput->opened) | 316 | err = open_substream(rmidi, soutput, mode); |
337 | goto __skip_output; | 317 | if (err < 0) { |
338 | if ((err = snd_rawmidi_runtime_create(soutput)) < 0) { | 318 | if (sinput) |
339 | if (mode & SNDRV_RAWMIDI_LFLG_INPUT) | 319 | close_substream(rmidi, sinput, 0); |
340 | sinput->ops->close(sinput); | ||
341 | goto __error; | ||
342 | } | ||
343 | output = soutput->runtime; | ||
344 | if ((err = soutput->ops->open(soutput)) < 0) { | ||
345 | if (mode & SNDRV_RAWMIDI_LFLG_INPUT) | ||
346 | sinput->ops->close(sinput); | ||
347 | goto __error; | 320 | goto __error; |
348 | } | 321 | } |
349 | __skip_output: | ||
350 | soutput->opened = 1; | ||
351 | if (mode & SNDRV_RAWMIDI_LFLG_APPEND) | ||
352 | soutput->append = 1; | ||
353 | if (soutput->use_count++ == 0) | ||
354 | soutput->active_sensing = 1; | ||
355 | rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substream_opened++; | ||
356 | } else { | ||
357 | soutput = NULL; | ||
358 | } | ||
359 | if (!(mode & SNDRV_RAWMIDI_LFLG_NOOPENLOCK)) | ||
360 | mutex_unlock(&rmidi->open_mutex); | ||
361 | if (rfile) { | ||
362 | rfile->rmidi = rmidi; | ||
363 | rfile->input = sinput; | ||
364 | rfile->output = soutput; | ||
365 | } | 322 | } |
323 | |||
324 | rfile->rmidi = rmidi; | ||
325 | rfile->input = sinput; | ||
326 | rfile->output = soutput; | ||
366 | return 0; | 327 | return 0; |
367 | 328 | ||
368 | __error: | 329 | __error: |
369 | if (input != NULL) | 330 | if (sinput && sinput->runtime) |
370 | snd_rawmidi_runtime_free(sinput); | 331 | snd_rawmidi_runtime_free(sinput); |
371 | if (output != NULL) | 332 | if (soutput && soutput->runtime) |
372 | snd_rawmidi_runtime_free(soutput); | 333 | snd_rawmidi_runtime_free(soutput); |
373 | module_put(rmidi->card->module); | 334 | return err; |
374 | if (!(mode & SNDRV_RAWMIDI_LFLG_NOOPENLOCK)) | 335 | } |
375 | mutex_unlock(&rmidi->open_mutex); | 336 | |
376 | __error1: | 337 | /* called from sound/core/seq/seq_midi.c */ |
338 | int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice, | ||
339 | int mode, struct snd_rawmidi_file * rfile) | ||
340 | { | ||
341 | struct snd_rawmidi *rmidi; | ||
342 | int err; | ||
343 | |||
344 | if (snd_BUG_ON(!rfile)) | ||
345 | return -EINVAL; | ||
346 | |||
347 | mutex_lock(®ister_mutex); | ||
348 | rmidi = snd_rawmidi_search(card, device); | ||
349 | if (rmidi == NULL) { | ||
350 | mutex_unlock(®ister_mutex); | ||
351 | return -ENODEV; | ||
352 | } | ||
353 | if (!try_module_get(rmidi->card->module)) { | ||
354 | mutex_unlock(®ister_mutex); | ||
355 | return -ENXIO; | ||
356 | } | ||
357 | mutex_unlock(®ister_mutex); | ||
358 | |||
359 | mutex_lock(&rmidi->open_mutex); | ||
360 | err = rawmidi_open_priv(rmidi, subdevice, mode, rfile); | ||
361 | mutex_unlock(&rmidi->open_mutex); | ||
362 | if (err < 0) | ||
363 | module_put(rmidi->card->module); | ||
377 | return err; | 364 | return err; |
378 | } | 365 | } |
379 | 366 | ||
@@ -385,10 +372,13 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) | |||
385 | unsigned short fflags; | 372 | unsigned short fflags; |
386 | int err; | 373 | int err; |
387 | struct snd_rawmidi *rmidi; | 374 | struct snd_rawmidi *rmidi; |
388 | struct snd_rawmidi_file *rawmidi_file; | 375 | struct snd_rawmidi_file *rawmidi_file = NULL; |
389 | wait_queue_t wait; | 376 | wait_queue_t wait; |
390 | struct snd_ctl_file *kctl; | 377 | struct snd_ctl_file *kctl; |
391 | 378 | ||
379 | if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK)) | ||
380 | return -EINVAL; /* invalid combination */ | ||
381 | |||
392 | if (maj == snd_major) { | 382 | if (maj == snd_major) { |
393 | rmidi = snd_lookup_minor_data(iminor(inode), | 383 | rmidi = snd_lookup_minor_data(iminor(inode), |
394 | SNDRV_DEVICE_TYPE_RAWMIDI); | 384 | SNDRV_DEVICE_TYPE_RAWMIDI); |
@@ -402,24 +392,25 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) | |||
402 | 392 | ||
403 | if (rmidi == NULL) | 393 | if (rmidi == NULL) |
404 | return -ENODEV; | 394 | return -ENODEV; |
405 | if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK)) | 395 | |
406 | return -EINVAL; /* invalid combination */ | 396 | if (!try_module_get(rmidi->card->module)) |
397 | return -ENXIO; | ||
398 | |||
399 | mutex_lock(&rmidi->open_mutex); | ||
407 | card = rmidi->card; | 400 | card = rmidi->card; |
408 | err = snd_card_file_add(card, file); | 401 | err = snd_card_file_add(card, file); |
409 | if (err < 0) | 402 | if (err < 0) |
410 | return -ENODEV; | 403 | goto __error_card; |
411 | fflags = snd_rawmidi_file_flags(file); | 404 | fflags = snd_rawmidi_file_flags(file); |
412 | if ((file->f_flags & O_APPEND) || maj == SOUND_MAJOR) /* OSS emul? */ | 405 | if ((file->f_flags & O_APPEND) || maj == SOUND_MAJOR) /* OSS emul? */ |
413 | fflags |= SNDRV_RAWMIDI_LFLG_APPEND; | 406 | fflags |= SNDRV_RAWMIDI_LFLG_APPEND; |
414 | fflags |= SNDRV_RAWMIDI_LFLG_NOOPENLOCK; | ||
415 | rawmidi_file = kmalloc(sizeof(*rawmidi_file), GFP_KERNEL); | 407 | rawmidi_file = kmalloc(sizeof(*rawmidi_file), GFP_KERNEL); |
416 | if (rawmidi_file == NULL) { | 408 | if (rawmidi_file == NULL) { |
417 | snd_card_file_remove(card, file); | 409 | err = -ENOMEM; |
418 | return -ENOMEM; | 410 | goto __error; |
419 | } | 411 | } |
420 | init_waitqueue_entry(&wait, current); | 412 | init_waitqueue_entry(&wait, current); |
421 | add_wait_queue(&rmidi->open_wait, &wait); | 413 | add_wait_queue(&rmidi->open_wait, &wait); |
422 | mutex_lock(&rmidi->open_mutex); | ||
423 | while (1) { | 414 | while (1) { |
424 | subdevice = -1; | 415 | subdevice = -1; |
425 | read_lock(&card->ctl_files_rwlock); | 416 | read_lock(&card->ctl_files_rwlock); |
@@ -431,8 +422,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) | |||
431 | } | 422 | } |
432 | } | 423 | } |
433 | read_unlock(&card->ctl_files_rwlock); | 424 | read_unlock(&card->ctl_files_rwlock); |
434 | err = snd_rawmidi_kernel_open(rmidi->card, rmidi->device, | 425 | err = rawmidi_open_priv(rmidi, subdevice, fflags, rawmidi_file); |
435 | subdevice, fflags, rawmidi_file); | ||
436 | if (err >= 0) | 426 | if (err >= 0) |
437 | break; | 427 | break; |
438 | if (err == -EAGAIN) { | 428 | if (err == -EAGAIN) { |
@@ -451,67 +441,89 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) | |||
451 | break; | 441 | break; |
452 | } | 442 | } |
453 | } | 443 | } |
444 | remove_wait_queue(&rmidi->open_wait, &wait); | ||
445 | if (err < 0) { | ||
446 | kfree(rawmidi_file); | ||
447 | goto __error; | ||
448 | } | ||
454 | #ifdef CONFIG_SND_OSSEMUL | 449 | #ifdef CONFIG_SND_OSSEMUL |
455 | if (rawmidi_file->input && rawmidi_file->input->runtime) | 450 | if (rawmidi_file->input && rawmidi_file->input->runtime) |
456 | rawmidi_file->input->runtime->oss = (maj == SOUND_MAJOR); | 451 | rawmidi_file->input->runtime->oss = (maj == SOUND_MAJOR); |
457 | if (rawmidi_file->output && rawmidi_file->output->runtime) | 452 | if (rawmidi_file->output && rawmidi_file->output->runtime) |
458 | rawmidi_file->output->runtime->oss = (maj == SOUND_MAJOR); | 453 | rawmidi_file->output->runtime->oss = (maj == SOUND_MAJOR); |
459 | #endif | 454 | #endif |
460 | remove_wait_queue(&rmidi->open_wait, &wait); | 455 | file->private_data = rawmidi_file; |
461 | if (err >= 0) { | 456 | mutex_unlock(&rmidi->open_mutex); |
462 | file->private_data = rawmidi_file; | 457 | return 0; |
463 | } else { | 458 | |
464 | snd_card_file_remove(card, file); | 459 | __error: |
465 | kfree(rawmidi_file); | 460 | snd_card_file_remove(card, file); |
466 | } | 461 | __error_card: |
467 | mutex_unlock(&rmidi->open_mutex); | 462 | mutex_unlock(&rmidi->open_mutex); |
463 | module_put(rmidi->card->module); | ||
468 | return err; | 464 | return err; |
469 | } | 465 | } |
470 | 466 | ||
471 | int snd_rawmidi_kernel_release(struct snd_rawmidi_file * rfile) | 467 | static void close_substream(struct snd_rawmidi *rmidi, |
468 | struct snd_rawmidi_substream *substream, | ||
469 | int cleanup) | ||
472 | { | 470 | { |
473 | struct snd_rawmidi *rmidi; | 471 | rmidi->streams[substream->stream].substream_opened--; |
474 | struct snd_rawmidi_substream *substream; | 472 | if (--substream->use_count) |
475 | struct snd_rawmidi_runtime *runtime; | 473 | return; |
476 | 474 | ||
477 | if (snd_BUG_ON(!rfile)) | 475 | if (cleanup) { |
478 | return -ENXIO; | 476 | if (substream->stream == SNDRV_RAWMIDI_STREAM_INPUT) |
479 | rmidi = rfile->rmidi; | 477 | snd_rawmidi_input_trigger(substream, 0); |
480 | mutex_lock(&rmidi->open_mutex); | 478 | else { |
481 | if (rfile->input != NULL) { | ||
482 | substream = rfile->input; | ||
483 | rfile->input = NULL; | ||
484 | runtime = substream->runtime; | ||
485 | snd_rawmidi_input_trigger(substream, 0); | ||
486 | substream->ops->close(substream); | ||
487 | if (runtime->private_free != NULL) | ||
488 | runtime->private_free(substream); | ||
489 | snd_rawmidi_runtime_free(substream); | ||
490 | substream->opened = 0; | ||
491 | rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_opened--; | ||
492 | } | ||
493 | if (rfile->output != NULL) { | ||
494 | substream = rfile->output; | ||
495 | rfile->output = NULL; | ||
496 | if (--substream->use_count == 0) { | ||
497 | runtime = substream->runtime; | ||
498 | if (substream->active_sensing) { | 479 | if (substream->active_sensing) { |
499 | unsigned char buf = 0xfe; | 480 | unsigned char buf = 0xfe; |
500 | /* sending single active sensing message to shut the device up */ | 481 | /* sending single active sensing message |
482 | * to shut the device up | ||
483 | */ | ||
501 | snd_rawmidi_kernel_write(substream, &buf, 1); | 484 | snd_rawmidi_kernel_write(substream, &buf, 1); |
502 | } | 485 | } |
503 | if (snd_rawmidi_drain_output(substream) == -ERESTARTSYS) | 486 | if (snd_rawmidi_drain_output(substream) == -ERESTARTSYS) |
504 | snd_rawmidi_output_trigger(substream, 0); | 487 | snd_rawmidi_output_trigger(substream, 0); |
505 | substream->ops->close(substream); | ||
506 | if (runtime->private_free != NULL) | ||
507 | runtime->private_free(substream); | ||
508 | snd_rawmidi_runtime_free(substream); | ||
509 | substream->opened = 0; | ||
510 | substream->append = 0; | ||
511 | } | 488 | } |
512 | rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substream_opened--; | ||
513 | } | 489 | } |
490 | substream->ops->close(substream); | ||
491 | if (substream->runtime->private_free) | ||
492 | substream->runtime->private_free(substream); | ||
493 | snd_rawmidi_runtime_free(substream); | ||
494 | substream->opened = 0; | ||
495 | substream->append = 0; | ||
496 | } | ||
497 | |||
498 | static void rawmidi_release_priv(struct snd_rawmidi_file *rfile) | ||
499 | { | ||
500 | struct snd_rawmidi *rmidi; | ||
501 | |||
502 | rmidi = rfile->rmidi; | ||
503 | mutex_lock(&rmidi->open_mutex); | ||
504 | if (rfile->input) { | ||
505 | close_substream(rmidi, rfile->input, 1); | ||
506 | rfile->input = NULL; | ||
507 | } | ||
508 | if (rfile->output) { | ||
509 | close_substream(rmidi, rfile->output, 1); | ||
510 | rfile->output = NULL; | ||
511 | } | ||
512 | rfile->rmidi = NULL; | ||
514 | mutex_unlock(&rmidi->open_mutex); | 513 | mutex_unlock(&rmidi->open_mutex); |
514 | wake_up(&rmidi->open_wait); | ||
515 | } | ||
516 | |||
517 | /* called from sound/core/seq/seq_midi.c */ | ||
518 | int snd_rawmidi_kernel_release(struct snd_rawmidi_file *rfile) | ||
519 | { | ||
520 | struct snd_rawmidi *rmidi; | ||
521 | |||
522 | if (snd_BUG_ON(!rfile)) | ||
523 | return -ENXIO; | ||
524 | |||
525 | rmidi = rfile->rmidi; | ||
526 | rawmidi_release_priv(rfile); | ||
515 | module_put(rmidi->card->module); | 527 | module_put(rmidi->card->module); |
516 | return 0; | 528 | return 0; |
517 | } | 529 | } |
@@ -520,15 +532,14 @@ static int snd_rawmidi_release(struct inode *inode, struct file *file) | |||
520 | { | 532 | { |
521 | struct snd_rawmidi_file *rfile; | 533 | struct snd_rawmidi_file *rfile; |
522 | struct snd_rawmidi *rmidi; | 534 | struct snd_rawmidi *rmidi; |
523 | int err; | ||
524 | 535 | ||
525 | rfile = file->private_data; | 536 | rfile = file->private_data; |
526 | err = snd_rawmidi_kernel_release(rfile); | ||
527 | rmidi = rfile->rmidi; | 537 | rmidi = rfile->rmidi; |
528 | wake_up(&rmidi->open_wait); | 538 | rawmidi_release_priv(rfile); |
529 | kfree(rfile); | 539 | kfree(rfile); |
530 | snd_card_file_remove(rmidi->card, file); | 540 | snd_card_file_remove(rmidi->card, file); |
531 | return err; | 541 | module_put(rmidi->card->module); |
542 | return 0; | ||
532 | } | 543 | } |
533 | 544 | ||
534 | static int snd_rawmidi_info(struct snd_rawmidi_substream *substream, | 545 | static int snd_rawmidi_info(struct snd_rawmidi_substream *substream, |
diff --git a/sound/core/seq/oss/seq_oss_device.h b/sound/core/seq/oss/seq_oss_device.h index bf8d2b4cb15e..c0154a959d55 100644 --- a/sound/core/seq/oss/seq_oss_device.h +++ b/sound/core/seq/oss/seq_oss_device.h | |||
@@ -181,7 +181,7 @@ char *enabled_str(int bool); | |||
181 | /* for debug */ | 181 | /* for debug */ |
182 | #ifdef SNDRV_SEQ_OSS_DEBUG | 182 | #ifdef SNDRV_SEQ_OSS_DEBUG |
183 | extern int seq_oss_debug; | 183 | extern int seq_oss_debug; |
184 | #define debug_printk(x) do { if (seq_oss_debug > 0) snd_printk x; } while (0) | 184 | #define debug_printk(x) do { if (seq_oss_debug > 0) snd_printd x; } while (0) |
185 | #else | 185 | #else |
186 | #define debug_printk(x) /**/ | 186 | #define debug_printk(x) /**/ |
187 | #endif | 187 | #endif |
diff --git a/sound/core/seq/seq_prioq.c b/sound/core/seq/seq_prioq.c index 0101a8b99b73..29896ab23403 100644 --- a/sound/core/seq/seq_prioq.c +++ b/sound/core/seq/seq_prioq.c | |||
@@ -321,7 +321,8 @@ void snd_seq_prioq_leave(struct snd_seq_prioq * f, int client, int timestamp) | |||
321 | freeprev = cell; | 321 | freeprev = cell; |
322 | } else { | 322 | } else { |
323 | #if 0 | 323 | #if 0 |
324 | printk("type = %i, source = %i, dest = %i, client = %i\n", | 324 | printk(KERN_DEBUG "type = %i, source = %i, dest = %i, " |
325 | "client = %i\n", | ||
325 | cell->event.type, | 326 | cell->event.type, |
326 | cell->event.source.client, | 327 | cell->event.source.client, |
327 | cell->event.dest.client, | 328 | cell->event.dest.client, |
diff --git a/sound/core/timer.c b/sound/core/timer.c index 796532081e81..3f0050d0b71e 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c | |||
@@ -1825,13 +1825,9 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, | |||
1825 | static int snd_timer_user_fasync(int fd, struct file * file, int on) | 1825 | static int snd_timer_user_fasync(int fd, struct file * file, int on) |
1826 | { | 1826 | { |
1827 | struct snd_timer_user *tu; | 1827 | struct snd_timer_user *tu; |
1828 | int err; | ||
1829 | 1828 | ||
1830 | tu = file->private_data; | 1829 | tu = file->private_data; |
1831 | err = fasync_helper(fd, file, on, &tu->fasync); | 1830 | return fasync_helper(fd, file, on, &tu->fasync); |
1832 | if (err < 0) | ||
1833 | return err; | ||
1834 | return 0; | ||
1835 | } | 1831 | } |
1836 | 1832 | ||
1837 | static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, | 1833 | static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, |
diff --git a/sound/core/vmaster.c b/sound/core/vmaster.c index 4cc57f902e2c..257624bd1997 100644 --- a/sound/core/vmaster.c +++ b/sound/core/vmaster.c | |||
@@ -50,18 +50,38 @@ struct link_slave { | |||
50 | struct link_master *master; | 50 | struct link_master *master; |
51 | struct link_ctl_info info; | 51 | struct link_ctl_info info; |
52 | int vals[2]; /* current values */ | 52 | int vals[2]; /* current values */ |
53 | unsigned int flags; | ||
53 | struct snd_kcontrol slave; /* the copy of original control entry */ | 54 | struct snd_kcontrol slave; /* the copy of original control entry */ |
54 | }; | 55 | }; |
55 | 56 | ||
57 | static int slave_update(struct link_slave *slave) | ||
58 | { | ||
59 | struct snd_ctl_elem_value *uctl; | ||
60 | int err, ch; | ||
61 | |||
62 | uctl = kmalloc(sizeof(*uctl), GFP_KERNEL); | ||
63 | if (!uctl) | ||
64 | return -ENOMEM; | ||
65 | uctl->id = slave->slave.id; | ||
66 | err = slave->slave.get(&slave->slave, uctl); | ||
67 | for (ch = 0; ch < slave->info.count; ch++) | ||
68 | slave->vals[ch] = uctl->value.integer.value[ch]; | ||
69 | kfree(uctl); | ||
70 | return 0; | ||
71 | } | ||
72 | |||
56 | /* get the slave ctl info and save the initial values */ | 73 | /* get the slave ctl info and save the initial values */ |
57 | static int slave_init(struct link_slave *slave) | 74 | static int slave_init(struct link_slave *slave) |
58 | { | 75 | { |
59 | struct snd_ctl_elem_info *uinfo; | 76 | struct snd_ctl_elem_info *uinfo; |
60 | struct snd_ctl_elem_value *uctl; | 77 | int err; |
61 | int err, ch; | ||
62 | 78 | ||
63 | if (slave->info.count) | 79 | if (slave->info.count) { |
64 | return 0; /* already initialized */ | 80 | /* already initialized */ |
81 | if (slave->flags & SND_CTL_SLAVE_NEED_UPDATE) | ||
82 | return slave_update(slave); | ||
83 | return 0; | ||
84 | } | ||
65 | 85 | ||
66 | uinfo = kmalloc(sizeof(*uinfo), GFP_KERNEL); | 86 | uinfo = kmalloc(sizeof(*uinfo), GFP_KERNEL); |
67 | if (!uinfo) | 87 | if (!uinfo) |
@@ -85,15 +105,7 @@ static int slave_init(struct link_slave *slave) | |||
85 | slave->info.max_val = uinfo->value.integer.max; | 105 | slave->info.max_val = uinfo->value.integer.max; |
86 | kfree(uinfo); | 106 | kfree(uinfo); |
87 | 107 | ||
88 | uctl = kmalloc(sizeof(*uctl), GFP_KERNEL); | 108 | return slave_update(slave); |
89 | if (!uctl) | ||
90 | return -ENOMEM; | ||
91 | uctl->id = slave->slave.id; | ||
92 | err = slave->slave.get(&slave->slave, uctl); | ||
93 | for (ch = 0; ch < slave->info.count; ch++) | ||
94 | slave->vals[ch] = uctl->value.integer.value[ch]; | ||
95 | kfree(uctl); | ||
96 | return 0; | ||
97 | } | 109 | } |
98 | 110 | ||
99 | /* initialize master volume */ | 111 | /* initialize master volume */ |
@@ -229,7 +241,8 @@ static void slave_free(struct snd_kcontrol *kcontrol) | |||
229 | * - logarithmic volume control (dB level), no linear volume | 241 | * - logarithmic volume control (dB level), no linear volume |
230 | * - master can only attenuate the volume, no gain | 242 | * - master can only attenuate the volume, no gain |
231 | */ | 243 | */ |
232 | int snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave) | 244 | int _snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave, |
245 | unsigned int flags) | ||
233 | { | 246 | { |
234 | struct link_master *master_link = snd_kcontrol_chip(master); | 247 | struct link_master *master_link = snd_kcontrol_chip(master); |
235 | struct link_slave *srec; | 248 | struct link_slave *srec; |
@@ -241,6 +254,7 @@ int snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave) | |||
241 | srec->slave = *slave; | 254 | srec->slave = *slave; |
242 | memcpy(srec->slave.vd, slave->vd, slave->count * sizeof(*slave->vd)); | 255 | memcpy(srec->slave.vd, slave->vd, slave->count * sizeof(*slave->vd)); |
243 | srec->master = master_link; | 256 | srec->master = master_link; |
257 | srec->flags = flags; | ||
244 | 258 | ||
245 | /* override callbacks */ | 259 | /* override callbacks */ |
246 | slave->info = slave_info; | 260 | slave->info = slave_info; |
@@ -254,8 +268,7 @@ int snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave) | |||
254 | list_add_tail(&srec->list, &master_link->slaves); | 268 | list_add_tail(&srec->list, &master_link->slaves); |
255 | return 0; | 269 | return 0; |
256 | } | 270 | } |
257 | 271 | EXPORT_SYMBOL(_snd_ctl_add_slave); | |
258 | EXPORT_SYMBOL(snd_ctl_add_slave); | ||
259 | 272 | ||
260 | /* | 273 | /* |
261 | * ctl callbacks for master controls | 274 | * ctl callbacks for master controls |
@@ -327,8 +340,20 @@ static void master_free(struct snd_kcontrol *kcontrol) | |||
327 | } | 340 | } |
328 | 341 | ||
329 | 342 | ||
330 | /* | 343 | /** |
331 | * Create a virtual master control with the given name | 344 | * snd_ctl_make_virtual_master - Create a virtual master control |
345 | * @name: name string of the control element to create | ||
346 | * @tlv: optional TLV int array for dB information | ||
347 | * | ||
348 | * Creates a virtual matster control with the given name string. | ||
349 | * Returns the created control element, or NULL for errors (ENOMEM). | ||
350 | * | ||
351 | * After creating a vmaster element, you can add the slave controls | ||
352 | * via snd_ctl_add_slave() or snd_ctl_add_slave_uncached(). | ||
353 | * | ||
354 | * The optional argument @tlv can be used to specify the TLV information | ||
355 | * for dB scale of the master control. It should be a single element | ||
356 | * with #SNDRV_CTL_TLVT_DB_SCALE type, and should be the max 0dB. | ||
332 | */ | 357 | */ |
333 | struct snd_kcontrol *snd_ctl_make_virtual_master(char *name, | 358 | struct snd_kcontrol *snd_ctl_make_virtual_master(char *name, |
334 | const unsigned int *tlv) | 359 | const unsigned int *tlv) |
@@ -367,5 +392,4 @@ struct snd_kcontrol *snd_ctl_make_virtual_master(char *name, | |||
367 | 392 | ||
368 | return kctl; | 393 | return kctl; |
369 | } | 394 | } |
370 | |||
371 | EXPORT_SYMBOL(snd_ctl_make_virtual_master); | 395 | EXPORT_SYMBOL(snd_ctl_make_virtual_master); |
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c index 73be7e14a603..54239d2e0997 100644 --- a/sound/drivers/dummy.c +++ b/sound/drivers/dummy.c | |||
@@ -588,10 +588,10 @@ static int __devinit snd_dummy_probe(struct platform_device *devptr) | |||
588 | int idx, err; | 588 | int idx, err; |
589 | int dev = devptr->id; | 589 | int dev = devptr->id; |
590 | 590 | ||
591 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, | 591 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, |
592 | sizeof(struct snd_dummy)); | 592 | sizeof(struct snd_dummy), &card); |
593 | if (card == NULL) | 593 | if (err < 0) |
594 | return -ENOMEM; | 594 | return err; |
595 | dummy = card->private_data; | 595 | dummy = card->private_data; |
596 | dummy->card = card; | 596 | dummy->card = card; |
597 | for (idx = 0; idx < MAX_PCM_DEVICES && idx < pcm_devs[dev]; idx++) { | 597 | for (idx = 0; idx < MAX_PCM_DEVICES && idx < pcm_devs[dev]; idx++) { |
diff --git a/sound/drivers/ml403-ac97cr.c b/sound/drivers/ml403-ac97cr.c index 7783843ca9ae..1950ffce2b54 100644 --- a/sound/drivers/ml403-ac97cr.c +++ b/sound/drivers/ml403-ac97cr.c | |||
@@ -1279,9 +1279,9 @@ static int __devinit snd_ml403_ac97cr_probe(struct platform_device *pfdev) | |||
1279 | if (!enable[dev]) | 1279 | if (!enable[dev]) |
1280 | return -ENOENT; | 1280 | return -ENOENT; |
1281 | 1281 | ||
1282 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 1282 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); |
1283 | if (card == NULL) | 1283 | if (err < 0) |
1284 | return -ENOMEM; | 1284 | return err; |
1285 | err = snd_ml403_ac97cr_create(card, pfdev, &ml403_ac97cr); | 1285 | err = snd_ml403_ac97cr_create(card, pfdev, &ml403_ac97cr); |
1286 | if (err < 0) { | 1286 | if (err < 0) { |
1287 | PDEBUG(INIT_FAILURE, "probe(): create failed!\n"); | 1287 | PDEBUG(INIT_FAILURE, "probe(): create failed!\n"); |
diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c index 5b996f3faba5..149d05a8202d 100644 --- a/sound/drivers/mpu401/mpu401.c +++ b/sound/drivers/mpu401/mpu401.c | |||
@@ -73,9 +73,9 @@ static int snd_mpu401_create(int dev, struct snd_card **rcard) | |||
73 | snd_printk(KERN_ERR "the uart_enter option is obsolete; remove it\n"); | 73 | snd_printk(KERN_ERR "the uart_enter option is obsolete; remove it\n"); |
74 | 74 | ||
75 | *rcard = NULL; | 75 | *rcard = NULL; |
76 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 76 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); |
77 | if (card == NULL) | 77 | if (err < 0) |
78 | return -ENOMEM; | 78 | return err; |
79 | strcpy(card->driver, "MPU-401 UART"); | 79 | strcpy(card->driver, "MPU-401 UART"); |
80 | strcpy(card->shortname, card->driver); | 80 | strcpy(card->shortname, card->driver); |
81 | sprintf(card->longname, "%s at %#lx, ", card->shortname, port[dev]); | 81 | sprintf(card->longname, "%s at %#lx, ", card->shortname, port[dev]); |
diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c index 48b64e6b2670..2f8f295d6b0c 100644 --- a/sound/drivers/mtpav.c +++ b/sound/drivers/mtpav.c | |||
@@ -303,8 +303,10 @@ static void snd_mtpav_output_port_write(struct mtpav *mtp_card, | |||
303 | 303 | ||
304 | snd_mtpav_send_byte(mtp_card, 0xf5); | 304 | snd_mtpav_send_byte(mtp_card, 0xf5); |
305 | snd_mtpav_send_byte(mtp_card, portp->hwport); | 305 | snd_mtpav_send_byte(mtp_card, portp->hwport); |
306 | //snd_printk("new outport: 0x%x\n", (unsigned int) portp->hwport); | 306 | /* |
307 | 307 | snd_printk(KERN_DEBUG "new outport: 0x%x\n", | |
308 | (unsigned int) portp->hwport); | ||
309 | */ | ||
308 | if (!(outbyte & 0x80) && portp->running_status) | 310 | if (!(outbyte & 0x80) && portp->running_status) |
309 | snd_mtpav_send_byte(mtp_card, portp->running_status); | 311 | snd_mtpav_send_byte(mtp_card, portp->running_status); |
310 | } | 312 | } |
@@ -540,7 +542,7 @@ static void snd_mtpav_read_bytes(struct mtpav *mcrd) | |||
540 | 542 | ||
541 | u8 sbyt = snd_mtpav_getreg(mcrd, SREG); | 543 | u8 sbyt = snd_mtpav_getreg(mcrd, SREG); |
542 | 544 | ||
543 | //printk("snd_mtpav_read_bytes() sbyt: 0x%x\n", sbyt); | 545 | /* printk(KERN_DEBUG "snd_mtpav_read_bytes() sbyt: 0x%x\n", sbyt); */ |
544 | 546 | ||
545 | if (!(sbyt & SIGS_BYTE)) | 547 | if (!(sbyt & SIGS_BYTE)) |
546 | return; | 548 | return; |
@@ -585,12 +587,12 @@ static irqreturn_t snd_mtpav_irqh(int irq, void *dev_id) | |||
585 | static int __devinit snd_mtpav_get_ISA(struct mtpav * mcard) | 587 | static int __devinit snd_mtpav_get_ISA(struct mtpav * mcard) |
586 | { | 588 | { |
587 | if ((mcard->res_port = request_region(port, 3, "MotuMTPAV MIDI")) == NULL) { | 589 | if ((mcard->res_port = request_region(port, 3, "MotuMTPAV MIDI")) == NULL) { |
588 | snd_printk("MTVAP port 0x%lx is busy\n", port); | 590 | snd_printk(KERN_ERR "MTVAP port 0x%lx is busy\n", port); |
589 | return -EBUSY; | 591 | return -EBUSY; |
590 | } | 592 | } |
591 | mcard->port = port; | 593 | mcard->port = port; |
592 | if (request_irq(irq, snd_mtpav_irqh, IRQF_DISABLED, "MOTU MTPAV", mcard)) { | 594 | if (request_irq(irq, snd_mtpav_irqh, IRQF_DISABLED, "MOTU MTPAV", mcard)) { |
593 | snd_printk("MTVAP IRQ %d busy\n", irq); | 595 | snd_printk(KERN_ERR "MTVAP IRQ %d busy\n", irq); |
594 | return -EBUSY; | 596 | return -EBUSY; |
595 | } | 597 | } |
596 | mcard->irq = irq; | 598 | mcard->irq = irq; |
@@ -696,9 +698,9 @@ static int __devinit snd_mtpav_probe(struct platform_device *dev) | |||
696 | int err; | 698 | int err; |
697 | struct mtpav *mtp_card; | 699 | struct mtpav *mtp_card; |
698 | 700 | ||
699 | card = snd_card_new(index, id, THIS_MODULE, sizeof(*mtp_card)); | 701 | err = snd_card_create(index, id, THIS_MODULE, sizeof(*mtp_card), &card); |
700 | if (! card) | 702 | if (err < 0) |
701 | return -ENOMEM; | 703 | return err; |
702 | 704 | ||
703 | mtp_card = card->private_data; | 705 | mtp_card = card->private_data; |
704 | spin_lock_init(&mtp_card->spinlock); | 706 | spin_lock_init(&mtp_card->spinlock); |
diff --git a/sound/drivers/mts64.c b/sound/drivers/mts64.c index 87ba1ddc0115..9284829bf927 100644 --- a/sound/drivers/mts64.c +++ b/sound/drivers/mts64.c | |||
@@ -957,10 +957,10 @@ static int __devinit snd_mts64_probe(struct platform_device *pdev) | |||
957 | if ((err = snd_mts64_probe_port(p)) < 0) | 957 | if ((err = snd_mts64_probe_port(p)) < 0) |
958 | return err; | 958 | return err; |
959 | 959 | ||
960 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 960 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); |
961 | if (card == NULL) { | 961 | if (err < 0) { |
962 | snd_printd("Cannot create card\n"); | 962 | snd_printd("Cannot create card\n"); |
963 | return -ENOMEM; | 963 | return err; |
964 | } | 964 | } |
965 | strcpy(card->driver, DRIVER_NAME); | 965 | strcpy(card->driver, DRIVER_NAME); |
966 | strcpy(card->shortname, "ESI " CARD_NAME); | 966 | strcpy(card->shortname, "ESI " CARD_NAME); |
@@ -1015,7 +1015,7 @@ static int __devinit snd_mts64_probe(struct platform_device *pdev) | |||
1015 | goto __err; | 1015 | goto __err; |
1016 | } | 1016 | } |
1017 | 1017 | ||
1018 | snd_printk("ESI Miditerminal 4140 on 0x%lx\n", p->base); | 1018 | snd_printk(KERN_INFO "ESI Miditerminal 4140 on 0x%lx\n", p->base); |
1019 | return 0; | 1019 | return 0; |
1020 | 1020 | ||
1021 | __err: | 1021 | __err: |
diff --git a/sound/drivers/opl3/opl3_lib.c b/sound/drivers/opl3/opl3_lib.c index 780582340fef..6e31e46ca393 100644 --- a/sound/drivers/opl3/opl3_lib.c +++ b/sound/drivers/opl3/opl3_lib.c | |||
@@ -302,7 +302,7 @@ void snd_opl3_interrupt(struct snd_hwdep * hw) | |||
302 | opl3 = hw->private_data; | 302 | opl3 = hw->private_data; |
303 | status = inb(opl3->l_port); | 303 | status = inb(opl3->l_port); |
304 | #if 0 | 304 | #if 0 |
305 | snd_printk("AdLib IRQ status = 0x%x\n", status); | 305 | snd_printk(KERN_DEBUG "AdLib IRQ status = 0x%x\n", status); |
306 | #endif | 306 | #endif |
307 | if (!(status & 0x80)) | 307 | if (!(status & 0x80)) |
308 | return; | 308 | return; |
diff --git a/sound/drivers/opl3/opl3_midi.c b/sound/drivers/opl3/opl3_midi.c index 16feafa2c51e..6e7d09ae0e82 100644 --- a/sound/drivers/opl3/opl3_midi.c +++ b/sound/drivers/opl3/opl3_midi.c | |||
@@ -125,7 +125,7 @@ static void debug_alloc(struct snd_opl3 *opl3, char *s, int voice) { | |||
125 | int i; | 125 | int i; |
126 | char *str = "x.24"; | 126 | char *str = "x.24"; |
127 | 127 | ||
128 | printk("time %.5i: %s [%.2i]: ", opl3->use_time, s, voice); | 128 | printk(KERN_DEBUG "time %.5i: %s [%.2i]: ", opl3->use_time, s, voice); |
129 | for (i = 0; i < opl3->max_voices; i++) | 129 | for (i = 0; i < opl3->max_voices; i++) |
130 | printk("%c", *(str + opl3->voices[i].state + 1)); | 130 | printk("%c", *(str + opl3->voices[i].state + 1)); |
131 | printk("\n"); | 131 | printk("\n"); |
@@ -218,7 +218,7 @@ static int opl3_get_voice(struct snd_opl3 *opl3, int instr_4op, | |||
218 | for (i = 0; i < END; i++) { | 218 | for (i = 0; i < END; i++) { |
219 | if (best[i].voice >= 0) { | 219 | if (best[i].voice >= 0) { |
220 | #ifdef DEBUG_ALLOC | 220 | #ifdef DEBUG_ALLOC |
221 | printk("%s %iop allocation on voice %i\n", | 221 | printk(KERN_DEBUG "%s %iop allocation on voice %i\n", |
222 | alloc_type[i], instr_4op ? 4 : 2, | 222 | alloc_type[i], instr_4op ? 4 : 2, |
223 | best[i].voice); | 223 | best[i].voice); |
224 | #endif | 224 | #endif |
@@ -317,7 +317,7 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) | |||
317 | opl3 = p; | 317 | opl3 = p; |
318 | 318 | ||
319 | #ifdef DEBUG_MIDI | 319 | #ifdef DEBUG_MIDI |
320 | snd_printk("Note on, ch %i, inst %i, note %i, vel %i\n", | 320 | snd_printk(KERN_DEBUG "Note on, ch %i, inst %i, note %i, vel %i\n", |
321 | chan->number, chan->midi_program, note, vel); | 321 | chan->number, chan->midi_program, note, vel); |
322 | #endif | 322 | #endif |
323 | 323 | ||
@@ -372,7 +372,7 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) | |||
372 | return; | 372 | return; |
373 | } | 373 | } |
374 | #ifdef DEBUG_MIDI | 374 | #ifdef DEBUG_MIDI |
375 | snd_printk(" --> OPL%i instrument: %s\n", | 375 | snd_printk(KERN_DEBUG " --> OPL%i instrument: %s\n", |
376 | instr_4op ? 3 : 2, patch->name); | 376 | instr_4op ? 3 : 2, patch->name); |
377 | #endif | 377 | #endif |
378 | /* in SYNTH mode, application takes care of voices */ | 378 | /* in SYNTH mode, application takes care of voices */ |
@@ -431,7 +431,7 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) | |||
431 | } | 431 | } |
432 | 432 | ||
433 | #ifdef DEBUG_MIDI | 433 | #ifdef DEBUG_MIDI |
434 | snd_printk(" --> setting OPL3 connection: 0x%x\n", | 434 | snd_printk(KERN_DEBUG " --> setting OPL3 connection: 0x%x\n", |
435 | opl3->connection_reg); | 435 | opl3->connection_reg); |
436 | #endif | 436 | #endif |
437 | /* | 437 | /* |
@@ -466,7 +466,7 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) | |||
466 | /* Program the FM voice characteristics */ | 466 | /* Program the FM voice characteristics */ |
467 | for (i = 0; i < (instr_4op ? 4 : 2); i++) { | 467 | for (i = 0; i < (instr_4op ? 4 : 2); i++) { |
468 | #ifdef DEBUG_MIDI | 468 | #ifdef DEBUG_MIDI |
469 | snd_printk(" --> programming operator %i\n", i); | 469 | snd_printk(KERN_DEBUG " --> programming operator %i\n", i); |
470 | #endif | 470 | #endif |
471 | op_offset = snd_opl3_regmap[voice_offset][i]; | 471 | op_offset = snd_opl3_regmap[voice_offset][i]; |
472 | 472 | ||
@@ -546,7 +546,7 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) | |||
546 | blocknum |= OPL3_KEYON_BIT; | 546 | blocknum |= OPL3_KEYON_BIT; |
547 | 547 | ||
548 | #ifdef DEBUG_MIDI | 548 | #ifdef DEBUG_MIDI |
549 | snd_printk(" --> trigger voice %i\n", voice); | 549 | snd_printk(KERN_DEBUG " --> trigger voice %i\n", voice); |
550 | #endif | 550 | #endif |
551 | /* Set OPL3 KEYON_BLOCK register of requested voice */ | 551 | /* Set OPL3 KEYON_BLOCK register of requested voice */ |
552 | opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset); | 552 | opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset); |
@@ -602,7 +602,7 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) | |||
602 | prg = extra_prg - 1; | 602 | prg = extra_prg - 1; |
603 | } | 603 | } |
604 | #ifdef DEBUG_MIDI | 604 | #ifdef DEBUG_MIDI |
605 | snd_printk(" *** allocating extra program\n"); | 605 | snd_printk(KERN_DEBUG " *** allocating extra program\n"); |
606 | #endif | 606 | #endif |
607 | goto __extra_prg; | 607 | goto __extra_prg; |
608 | } | 608 | } |
@@ -633,7 +633,7 @@ static void snd_opl3_kill_voice(struct snd_opl3 *opl3, int voice) | |||
633 | 633 | ||
634 | /* kill voice */ | 634 | /* kill voice */ |
635 | #ifdef DEBUG_MIDI | 635 | #ifdef DEBUG_MIDI |
636 | snd_printk(" --> kill voice %i\n", voice); | 636 | snd_printk(KERN_DEBUG " --> kill voice %i\n", voice); |
637 | #endif | 637 | #endif |
638 | opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset); | 638 | opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset); |
639 | /* clear Key ON bit */ | 639 | /* clear Key ON bit */ |
@@ -670,7 +670,7 @@ void snd_opl3_note_off(void *p, int note, int vel, struct snd_midi_channel *chan | |||
670 | opl3 = p; | 670 | opl3 = p; |
671 | 671 | ||
672 | #ifdef DEBUG_MIDI | 672 | #ifdef DEBUG_MIDI |
673 | snd_printk("Note off, ch %i, inst %i, note %i\n", | 673 | snd_printk(KERN_DEBUG "Note off, ch %i, inst %i, note %i\n", |
674 | chan->number, chan->midi_program, note); | 674 | chan->number, chan->midi_program, note); |
675 | #endif | 675 | #endif |
676 | 676 | ||
@@ -709,7 +709,7 @@ void snd_opl3_key_press(void *p, int note, int vel, struct snd_midi_channel *cha | |||
709 | 709 | ||
710 | opl3 = p; | 710 | opl3 = p; |
711 | #ifdef DEBUG_MIDI | 711 | #ifdef DEBUG_MIDI |
712 | snd_printk("Key pressure, ch#: %i, inst#: %i\n", | 712 | snd_printk(KERN_DEBUG "Key pressure, ch#: %i, inst#: %i\n", |
713 | chan->number, chan->midi_program); | 713 | chan->number, chan->midi_program); |
714 | #endif | 714 | #endif |
715 | } | 715 | } |
@@ -723,7 +723,7 @@ void snd_opl3_terminate_note(void *p, int note, struct snd_midi_channel *chan) | |||
723 | 723 | ||
724 | opl3 = p; | 724 | opl3 = p; |
725 | #ifdef DEBUG_MIDI | 725 | #ifdef DEBUG_MIDI |
726 | snd_printk("Terminate note, ch#: %i, inst#: %i\n", | 726 | snd_printk(KERN_DEBUG "Terminate note, ch#: %i, inst#: %i\n", |
727 | chan->number, chan->midi_program); | 727 | chan->number, chan->midi_program); |
728 | #endif | 728 | #endif |
729 | } | 729 | } |
@@ -812,7 +812,7 @@ void snd_opl3_control(void *p, int type, struct snd_midi_channel *chan) | |||
812 | 812 | ||
813 | opl3 = p; | 813 | opl3 = p; |
814 | #ifdef DEBUG_MIDI | 814 | #ifdef DEBUG_MIDI |
815 | snd_printk("Controller, TYPE = %i, ch#: %i, inst#: %i\n", | 815 | snd_printk(KERN_DEBUG "Controller, TYPE = %i, ch#: %i, inst#: %i\n", |
816 | type, chan->number, chan->midi_program); | 816 | type, chan->number, chan->midi_program); |
817 | #endif | 817 | #endif |
818 | 818 | ||
@@ -849,7 +849,7 @@ void snd_opl3_nrpn(void *p, struct snd_midi_channel *chan, | |||
849 | 849 | ||
850 | opl3 = p; | 850 | opl3 = p; |
851 | #ifdef DEBUG_MIDI | 851 | #ifdef DEBUG_MIDI |
852 | snd_printk("NRPN, ch#: %i, inst#: %i\n", | 852 | snd_printk(KERN_DEBUG "NRPN, ch#: %i, inst#: %i\n", |
853 | chan->number, chan->midi_program); | 853 | chan->number, chan->midi_program); |
854 | #endif | 854 | #endif |
855 | } | 855 | } |
@@ -864,6 +864,6 @@ void snd_opl3_sysex(void *p, unsigned char *buf, int len, | |||
864 | 864 | ||
865 | opl3 = p; | 865 | opl3 = p; |
866 | #ifdef DEBUG_MIDI | 866 | #ifdef DEBUG_MIDI |
867 | snd_printk("SYSEX\n"); | 867 | snd_printk(KERN_DEBUG "SYSEX\n"); |
868 | #endif | 868 | #endif |
869 | } | 869 | } |
diff --git a/sound/drivers/opl3/opl3_oss.c b/sound/drivers/opl3/opl3_oss.c index 9a2271dc046a..a54b1dc5cc78 100644 --- a/sound/drivers/opl3/opl3_oss.c +++ b/sound/drivers/opl3/opl3_oss.c | |||
@@ -220,14 +220,14 @@ static int snd_opl3_load_patch_seq_oss(struct snd_seq_oss_arg *arg, int format, | |||
220 | return -EINVAL; | 220 | return -EINVAL; |
221 | 221 | ||
222 | if (count < (int)sizeof(sbi)) { | 222 | if (count < (int)sizeof(sbi)) { |
223 | snd_printk("FM Error: Patch record too short\n"); | 223 | snd_printk(KERN_ERR "FM Error: Patch record too short\n"); |
224 | return -EINVAL; | 224 | return -EINVAL; |
225 | } | 225 | } |
226 | if (copy_from_user(&sbi, buf, sizeof(sbi))) | 226 | if (copy_from_user(&sbi, buf, sizeof(sbi))) |
227 | return -EFAULT; | 227 | return -EFAULT; |
228 | 228 | ||
229 | if (sbi.channel < 0 || sbi.channel >= SBFM_MAXINSTR) { | 229 | if (sbi.channel < 0 || sbi.channel >= SBFM_MAXINSTR) { |
230 | snd_printk("FM Error: Invalid instrument number %d\n", | 230 | snd_printk(KERN_ERR "FM Error: Invalid instrument number %d\n", |
231 | sbi.channel); | 231 | sbi.channel); |
232 | return -EINVAL; | 232 | return -EINVAL; |
233 | } | 233 | } |
@@ -254,7 +254,9 @@ static int snd_opl3_ioctl_seq_oss(struct snd_seq_oss_arg *arg, unsigned int cmd, | |||
254 | opl3 = arg->private_data; | 254 | opl3 = arg->private_data; |
255 | switch (cmd) { | 255 | switch (cmd) { |
256 | case SNDCTL_FM_LOAD_INSTR: | 256 | case SNDCTL_FM_LOAD_INSTR: |
257 | snd_printk("OPL3: Obsolete ioctl(SNDCTL_FM_LOAD_INSTR) used. Fix the program.\n"); | 257 | snd_printk(KERN_ERR "OPL3: " |
258 | "Obsolete ioctl(SNDCTL_FM_LOAD_INSTR) used. " | ||
259 | "Fix the program.\n"); | ||
258 | return -EINVAL; | 260 | return -EINVAL; |
259 | 261 | ||
260 | case SNDCTL_SYNTH_MEMAVL: | 262 | case SNDCTL_SYNTH_MEMAVL: |
diff --git a/sound/drivers/opl3/opl3_synth.c b/sound/drivers/opl3/opl3_synth.c index 962bb9c8b9c8..6d57b6441dec 100644 --- a/sound/drivers/opl3/opl3_synth.c +++ b/sound/drivers/opl3/opl3_synth.c | |||
@@ -168,7 +168,7 @@ int snd_opl3_ioctl(struct snd_hwdep * hw, struct file *file, | |||
168 | 168 | ||
169 | #ifdef CONFIG_SND_DEBUG | 169 | #ifdef CONFIG_SND_DEBUG |
170 | default: | 170 | default: |
171 | snd_printk("unknown IOCTL: 0x%x\n", cmd); | 171 | snd_printk(KERN_WARNING "unknown IOCTL: 0x%x\n", cmd); |
172 | #endif | 172 | #endif |
173 | } | 173 | } |
174 | return -ENOTTY; | 174 | return -ENOTTY; |
diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c index a4049eb94d35..b60cef257b58 100644 --- a/sound/drivers/pcsp/pcsp.c +++ b/sound/drivers/pcsp/pcsp.c | |||
@@ -57,7 +57,7 @@ static int __devinit snd_pcsp_create(struct snd_card *card) | |||
57 | else | 57 | else |
58 | min_div = MAX_DIV; | 58 | min_div = MAX_DIV; |
59 | #if PCSP_DEBUG | 59 | #if PCSP_DEBUG |
60 | printk("PCSP: lpj=%li, min_div=%i, res=%li\n", | 60 | printk(KERN_DEBUG "PCSP: lpj=%li, min_div=%i, res=%li\n", |
61 | loops_per_jiffy, min_div, tp.tv_nsec); | 61 | loops_per_jiffy, min_div, tp.tv_nsec); |
62 | #endif | 62 | #endif |
63 | 63 | ||
@@ -98,9 +98,9 @@ static int __devinit snd_card_pcsp_probe(int devnum, struct device *dev) | |||
98 | hrtimer_init(&pcsp_chip.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); | 98 | hrtimer_init(&pcsp_chip.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); |
99 | pcsp_chip.timer.function = pcsp_do_timer; | 99 | pcsp_chip.timer.function = pcsp_do_timer; |
100 | 100 | ||
101 | card = snd_card_new(index, id, THIS_MODULE, 0); | 101 | err = snd_card_create(index, id, THIS_MODULE, 0, &card); |
102 | if (!card) | 102 | if (err < 0) |
103 | return -ENOMEM; | 103 | return err; |
104 | 104 | ||
105 | err = snd_pcsp_create(card); | 105 | err = snd_pcsp_create(card); |
106 | if (err < 0) { | 106 | if (err < 0) { |
diff --git a/sound/drivers/portman2x4.c b/sound/drivers/portman2x4.c index b1c047ec19af..60158e2e0eaf 100644 --- a/sound/drivers/portman2x4.c +++ b/sound/drivers/portman2x4.c | |||
@@ -746,10 +746,10 @@ static int __devinit snd_portman_probe(struct platform_device *pdev) | |||
746 | if ((err = snd_portman_probe_port(p)) < 0) | 746 | if ((err = snd_portman_probe_port(p)) < 0) |
747 | return err; | 747 | return err; |
748 | 748 | ||
749 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 749 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); |
750 | if (card == NULL) { | 750 | if (err < 0) { |
751 | snd_printd("Cannot create card\n"); | 751 | snd_printd("Cannot create card\n"); |
752 | return -ENOMEM; | 752 | return err; |
753 | } | 753 | } |
754 | strcpy(card->driver, DRIVER_NAME); | 754 | strcpy(card->driver, DRIVER_NAME); |
755 | strcpy(card->shortname, CARD_NAME); | 755 | strcpy(card->shortname, CARD_NAME); |
diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c index d8aab9da97c2..b2b6d50c9425 100644 --- a/sound/drivers/serial-u16550.c +++ b/sound/drivers/serial-u16550.c | |||
@@ -241,7 +241,8 @@ static void snd_uart16550_io_loop(struct snd_uart16550 * uart) | |||
241 | snd_rawmidi_receive(uart->midi_input[substream], &c, 1); | 241 | snd_rawmidi_receive(uart->midi_input[substream], &c, 1); |
242 | 242 | ||
243 | if (status & UART_LSR_OE) | 243 | if (status & UART_LSR_OE) |
244 | snd_printk("%s: Overrun on device at 0x%lx\n", | 244 | snd_printk(KERN_WARNING |
245 | "%s: Overrun on device at 0x%lx\n", | ||
245 | uart->rmidi->name, uart->base); | 246 | uart->rmidi->name, uart->base); |
246 | } | 247 | } |
247 | 248 | ||
@@ -636,7 +637,8 @@ static int snd_uart16550_output_byte(struct snd_uart16550 *uart, | |||
636 | } | 637 | } |
637 | } else { | 638 | } else { |
638 | if (!snd_uart16550_write_buffer(uart, midi_byte)) { | 639 | if (!snd_uart16550_write_buffer(uart, midi_byte)) { |
639 | snd_printk("%s: Buffer overrun on device at 0x%lx\n", | 640 | snd_printk(KERN_WARNING |
641 | "%s: Buffer overrun on device at 0x%lx\n", | ||
640 | uart->rmidi->name, uart->base); | 642 | uart->rmidi->name, uart->base); |
641 | return 0; | 643 | return 0; |
642 | } | 644 | } |
@@ -815,7 +817,8 @@ static int __devinit snd_uart16550_create(struct snd_card *card, | |||
815 | if (irq >= 0 && irq != SNDRV_AUTO_IRQ) { | 817 | if (irq >= 0 && irq != SNDRV_AUTO_IRQ) { |
816 | if (request_irq(irq, snd_uart16550_interrupt, | 818 | if (request_irq(irq, snd_uart16550_interrupt, |
817 | IRQF_DISABLED, "Serial MIDI", uart)) { | 819 | IRQF_DISABLED, "Serial MIDI", uart)) { |
818 | snd_printk("irq %d busy. Using Polling.\n", irq); | 820 | snd_printk(KERN_WARNING |
821 | "irq %d busy. Using Polling.\n", irq); | ||
819 | } else { | 822 | } else { |
820 | uart->irq = irq; | 823 | uart->irq = irq; |
821 | } | 824 | } |
@@ -919,26 +922,29 @@ static int __devinit snd_serial_probe(struct platform_device *devptr) | |||
919 | case SNDRV_SERIAL_GENERIC: | 922 | case SNDRV_SERIAL_GENERIC: |
920 | break; | 923 | break; |
921 | default: | 924 | default: |
922 | snd_printk("Adaptor type is out of range 0-%d (%d)\n", | 925 | snd_printk(KERN_ERR |
926 | "Adaptor type is out of range 0-%d (%d)\n", | ||
923 | SNDRV_SERIAL_MAX_ADAPTOR, adaptor[dev]); | 927 | SNDRV_SERIAL_MAX_ADAPTOR, adaptor[dev]); |
924 | return -ENODEV; | 928 | return -ENODEV; |
925 | } | 929 | } |
926 | 930 | ||
927 | if (outs[dev] < 1 || outs[dev] > SNDRV_SERIAL_MAX_OUTS) { | 931 | if (outs[dev] < 1 || outs[dev] > SNDRV_SERIAL_MAX_OUTS) { |
928 | snd_printk("Count of outputs is out of range 1-%d (%d)\n", | 932 | snd_printk(KERN_ERR |
933 | "Count of outputs is out of range 1-%d (%d)\n", | ||
929 | SNDRV_SERIAL_MAX_OUTS, outs[dev]); | 934 | SNDRV_SERIAL_MAX_OUTS, outs[dev]); |
930 | return -ENODEV; | 935 | return -ENODEV; |
931 | } | 936 | } |
932 | 937 | ||
933 | if (ins[dev] < 1 || ins[dev] > SNDRV_SERIAL_MAX_INS) { | 938 | if (ins[dev] < 1 || ins[dev] > SNDRV_SERIAL_MAX_INS) { |
934 | snd_printk("Count of inputs is out of range 1-%d (%d)\n", | 939 | snd_printk(KERN_ERR |
940 | "Count of inputs is out of range 1-%d (%d)\n", | ||
935 | SNDRV_SERIAL_MAX_INS, ins[dev]); | 941 | SNDRV_SERIAL_MAX_INS, ins[dev]); |
936 | return -ENODEV; | 942 | return -ENODEV; |
937 | } | 943 | } |
938 | 944 | ||
939 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 945 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); |
940 | if (card == NULL) | 946 | if (err < 0) |
941 | return -ENOMEM; | 947 | return err; |
942 | 948 | ||
943 | strcpy(card->driver, "Serial"); | 949 | strcpy(card->driver, "Serial"); |
944 | strcpy(card->shortname, "Serial MIDI (UART16550A)"); | 950 | strcpy(card->shortname, "Serial MIDI (UART16550A)"); |
diff --git a/sound/drivers/virmidi.c b/sound/drivers/virmidi.c index f79e3614079d..0e631c3221e3 100644 --- a/sound/drivers/virmidi.c +++ b/sound/drivers/virmidi.c | |||
@@ -90,15 +90,17 @@ static int __devinit snd_virmidi_probe(struct platform_device *devptr) | |||
90 | int idx, err; | 90 | int idx, err; |
91 | int dev = devptr->id; | 91 | int dev = devptr->id; |
92 | 92 | ||
93 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, | 93 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, |
94 | sizeof(struct snd_card_virmidi)); | 94 | sizeof(struct snd_card_virmidi), &card); |
95 | if (card == NULL) | 95 | if (err < 0) |
96 | return -ENOMEM; | 96 | return err; |
97 | vmidi = (struct snd_card_virmidi *)card->private_data; | 97 | vmidi = (struct snd_card_virmidi *)card->private_data; |
98 | vmidi->card = card; | 98 | vmidi->card = card; |
99 | 99 | ||
100 | if (midi_devs[dev] > MAX_MIDI_DEVICES) { | 100 | if (midi_devs[dev] > MAX_MIDI_DEVICES) { |
101 | snd_printk("too much midi devices for virmidi %d: force to use %d\n", dev, MAX_MIDI_DEVICES); | 101 | snd_printk(KERN_WARNING |
102 | "too much midi devices for virmidi %d: " | ||
103 | "force to use %d\n", dev, MAX_MIDI_DEVICES); | ||
102 | midi_devs[dev] = MAX_MIDI_DEVICES; | 104 | midi_devs[dev] = MAX_MIDI_DEVICES; |
103 | } | 105 | } |
104 | for (idx = 0; idx < midi_devs[dev]; idx++) { | 106 | for (idx = 0; idx < midi_devs[dev]; idx++) { |
diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c index 14e3354be43a..19c6e376c7c7 100644 --- a/sound/drivers/vx/vx_core.c +++ b/sound/drivers/vx/vx_core.c | |||
@@ -688,7 +688,8 @@ int snd_vx_dsp_load(struct vx_core *chip, const struct firmware *dsp) | |||
688 | image = dsp->data + i; | 688 | image = dsp->data + i; |
689 | /* Wait DSP ready for a new read */ | 689 | /* Wait DSP ready for a new read */ |
690 | if ((err = vx_wait_isr_bit(chip, ISR_TX_EMPTY)) < 0) { | 690 | if ((err = vx_wait_isr_bit(chip, ISR_TX_EMPTY)) < 0) { |
691 | printk("dsp loading error at position %d\n", i); | 691 | printk(KERN_ERR |
692 | "dsp loading error at position %d\n", i); | ||
692 | return err; | 693 | return err; |
693 | } | 694 | } |
694 | cptr = image; | 695 | cptr = image; |
diff --git a/sound/drivers/vx/vx_hwdep.c b/sound/drivers/vx/vx_hwdep.c index 8d6362e2d4c9..46df8817c18f 100644 --- a/sound/drivers/vx/vx_hwdep.c +++ b/sound/drivers/vx/vx_hwdep.c | |||
@@ -119,16 +119,6 @@ void snd_vx_free_firmware(struct vx_core *chip) | |||
119 | 119 | ||
120 | #else /* old style firmware loading */ | 120 | #else /* old style firmware loading */ |
121 | 121 | ||
122 | static int vx_hwdep_open(struct snd_hwdep *hw, struct file *file) | ||
123 | { | ||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | static int vx_hwdep_release(struct snd_hwdep *hw, struct file *file) | ||
128 | { | ||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | static int vx_hwdep_dsp_status(struct snd_hwdep *hw, | 122 | static int vx_hwdep_dsp_status(struct snd_hwdep *hw, |
133 | struct snd_hwdep_dsp_status *info) | 123 | struct snd_hwdep_dsp_status *info) |
134 | { | 124 | { |
@@ -243,8 +233,6 @@ int snd_vx_setup_firmware(struct vx_core *chip) | |||
243 | 233 | ||
244 | hw->iface = SNDRV_HWDEP_IFACE_VX; | 234 | hw->iface = SNDRV_HWDEP_IFACE_VX; |
245 | hw->private_data = chip; | 235 | hw->private_data = chip; |
246 | hw->ops.open = vx_hwdep_open; | ||
247 | hw->ops.release = vx_hwdep_release; | ||
248 | hw->ops.dsp_status = vx_hwdep_dsp_status; | 236 | hw->ops.dsp_status = vx_hwdep_dsp_status; |
249 | hw->ops.dsp_load = vx_hwdep_dsp_load; | 237 | hw->ops.dsp_load = vx_hwdep_dsp_load; |
250 | hw->exclusive = 1; | 238 | hw->exclusive = 1; |
diff --git a/sound/drivers/vx/vx_uer.c b/sound/drivers/vx/vx_uer.c index 0e1ba9b47904..b0560fec6bba 100644 --- a/sound/drivers/vx/vx_uer.c +++ b/sound/drivers/vx/vx_uer.c | |||
@@ -103,7 +103,7 @@ static void vx_write_one_cbit(struct vx_core *chip, int index, int val) | |||
103 | * returns the frequency of UER, or 0 if not sync, | 103 | * returns the frequency of UER, or 0 if not sync, |
104 | * or a negative error code. | 104 | * or a negative error code. |
105 | */ | 105 | */ |
106 | static int vx_read_uer_status(struct vx_core *chip, int *mode) | 106 | static int vx_read_uer_status(struct vx_core *chip, unsigned int *mode) |
107 | { | 107 | { |
108 | int val, freq; | 108 | int val, freq; |
109 | 109 | ||
diff --git a/sound/i2c/Makefile b/sound/i2c/Makefile index 37970666a453..36879bf88700 100644 --- a/sound/i2c/Makefile +++ b/sound/i2c/Makefile | |||
@@ -7,8 +7,6 @@ snd-i2c-objs := i2c.o | |||
7 | snd-cs8427-objs := cs8427.o | 7 | snd-cs8427-objs := cs8427.o |
8 | snd-tea6330t-objs := tea6330t.o | 8 | snd-tea6330t-objs := tea6330t.o |
9 | 9 | ||
10 | obj-$(CONFIG_L3) += l3/ | ||
11 | |||
12 | obj-$(CONFIG_SND) += other/ | 10 | obj-$(CONFIG_SND) += other/ |
13 | 11 | ||
14 | # Toplevel Module Dependency | 12 | # Toplevel Module Dependency |
diff --git a/sound/i2c/l3/Makefile b/sound/i2c/l3/Makefile deleted file mode 100644 index 49455b8dcc04..000000000000 --- a/sound/i2c/l3/Makefile +++ /dev/null | |||
@@ -1,8 +0,0 @@ | |||
1 | # | ||
2 | # Makefile for ALSA | ||
3 | # | ||
4 | |||
5 | snd-uda1341-objs := uda1341.o | ||
6 | |||
7 | # Module Dependency | ||
8 | obj-$(CONFIG_SND_SA11XX_UDA1341) += snd-uda1341.o | ||
diff --git a/sound/i2c/l3/uda1341.c b/sound/i2c/l3/uda1341.c deleted file mode 100644 index 9840eb43648d..000000000000 --- a/sound/i2c/l3/uda1341.c +++ /dev/null | |||
@@ -1,935 +0,0 @@ | |||
1 | /* | ||
2 | * Philips UDA1341 mixer device driver | ||
3 | * Copyright (c) 2002 Tomas Kasparek <tomas.kasparek@seznam.cz> | ||
4 | * | ||
5 | * Portions are Copyright (C) 2000 Lernout & Hauspie Speech Products, N.V. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License. | ||
9 | * | ||
10 | * History: | ||
11 | * | ||
12 | * 2002-03-13 Tomas Kasparek initial release - based on uda1341.c from OSS | ||
13 | * 2002-03-28 Tomas Kasparek basic mixer is working (volume, bass, treble) | ||
14 | * 2002-03-30 Tomas Kasparek proc filesystem support, complete mixer and DSP | ||
15 | * features support | ||
16 | * 2002-04-12 Tomas Kasparek proc interface update, code cleanup | ||
17 | * 2002-05-12 Tomas Kasparek another code cleanup | ||
18 | */ | ||
19 | |||
20 | #include <linux/module.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/types.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/errno.h> | ||
25 | #include <linux/ioctl.h> | ||
26 | |||
27 | #include <asm/uaccess.h> | ||
28 | |||
29 | #include <sound/core.h> | ||
30 | #include <sound/control.h> | ||
31 | #include <sound/initval.h> | ||
32 | #include <sound/info.h> | ||
33 | |||
34 | #include <linux/l3/l3.h> | ||
35 | |||
36 | #include <sound/uda1341.h> | ||
37 | |||
38 | /* {{{ HW regs definition */ | ||
39 | |||
40 | #define STAT0 0x00 | ||
41 | #define STAT1 0x80 | ||
42 | #define STAT_MASK 0x80 | ||
43 | |||
44 | #define DATA0_0 0x00 | ||
45 | #define DATA0_1 0x40 | ||
46 | #define DATA0_2 0x80 | ||
47 | #define DATA_MASK 0xc0 | ||
48 | |||
49 | #define IS_DATA0(x) ((x) >= data0_0 && (x) <= data0_2) | ||
50 | #define IS_DATA1(x) ((x) == data1) | ||
51 | #define IS_STATUS(x) ((x) == stat0 || (x) == stat1) | ||
52 | #define IS_EXTEND(x) ((x) >= ext0 && (x) <= ext6) | ||
53 | |||
54 | /* }}} */ | ||
55 | |||
56 | |||
57 | static const char *peak_names[] = { | ||
58 | "before", | ||
59 | "after", | ||
60 | }; | ||
61 | |||
62 | static const char *filter_names[] = { | ||
63 | "flat", | ||
64 | "min", | ||
65 | "min", | ||
66 | "max", | ||
67 | }; | ||
68 | |||
69 | static const char *mixer_names[] = { | ||
70 | "double differential", | ||
71 | "input channel 1 (line in)", | ||
72 | "input channel 2 (microphone)", | ||
73 | "digital mixer", | ||
74 | }; | ||
75 | |||
76 | static const char *deemp_names[] = { | ||
77 | "none", | ||
78 | "32 kHz", | ||
79 | "44.1 kHz", | ||
80 | "48 kHz", | ||
81 | }; | ||
82 | |||
83 | enum uda1341_regs_names { | ||
84 | stat0, | ||
85 | stat1, | ||
86 | data0_0, | ||
87 | data0_1, | ||
88 | data0_2, | ||
89 | data1, | ||
90 | ext0, | ||
91 | ext1, | ||
92 | ext2, | ||
93 | empty, | ||
94 | ext4, | ||
95 | ext5, | ||
96 | ext6, | ||
97 | uda1341_reg_last, | ||
98 | }; | ||
99 | |||
100 | static const char *uda1341_reg_names[] = { | ||
101 | "stat 0 ", | ||
102 | "stat 1 ", | ||
103 | "data 00", | ||
104 | "data 01", | ||
105 | "data 02", | ||
106 | "data 1 ", | ||
107 | "ext 0", | ||
108 | "ext 1", | ||
109 | "ext 2", | ||
110 | "empty", | ||
111 | "ext 4", | ||
112 | "ext 5", | ||
113 | "ext 6", | ||
114 | }; | ||
115 | |||
116 | static const int uda1341_enum_items[] = { | ||
117 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
118 | 2, //peak - before/after | ||
119 | 4, //deemp - none/32/44.1/48 | ||
120 | 0, | ||
121 | 4, //filter - flat/min/min/max | ||
122 | 0, 0, 0, | ||
123 | 4, //mixer - differ/line/mic/mixer | ||
124 | 0, 0, 0, 0, 0, | ||
125 | }; | ||
126 | |||
127 | static const char ** uda1341_enum_names[] = { | ||
128 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
129 | peak_names, //peak - before/after | ||
130 | deemp_names, //deemp - none/32/44.1/48 | ||
131 | NULL, | ||
132 | filter_names, //filter - flat/min/min/max | ||
133 | NULL, NULL, NULL, | ||
134 | mixer_names, //mixer - differ/line/mic/mixer | ||
135 | NULL, NULL, NULL, NULL, NULL, | ||
136 | }; | ||
137 | |||
138 | typedef int uda1341_cfg[CMD_LAST]; | ||
139 | |||
140 | struct uda1341 { | ||
141 | int (*write) (struct l3_client *uda1341, unsigned short reg, unsigned short val); | ||
142 | int (*read) (struct l3_client *uda1341, unsigned short reg); | ||
143 | unsigned char regs[uda1341_reg_last]; | ||
144 | int active; | ||
145 | spinlock_t reg_lock; | ||
146 | struct snd_card *card; | ||
147 | uda1341_cfg cfg; | ||
148 | #ifdef CONFIG_PM | ||
149 | unsigned char suspend_regs[uda1341_reg_last]; | ||
150 | uda1341_cfg suspend_cfg; | ||
151 | #endif | ||
152 | }; | ||
153 | |||
154 | /* transfer 8bit integer into string with binary representation */ | ||
155 | static void int2str_bin8(uint8_t val, char *buf) | ||
156 | { | ||
157 | const int size = sizeof(val) * 8; | ||
158 | int i; | ||
159 | |||
160 | for (i= 0; i < size; i++){ | ||
161 | *(buf++) = (val >> (size - 1)) ? '1' : '0'; | ||
162 | val <<= 1; | ||
163 | } | ||
164 | *buf = '\0'; //end the string with zero | ||
165 | } | ||
166 | |||
167 | /* {{{ HW manipulation routines */ | ||
168 | |||
169 | static int snd_uda1341_codec_write(struct l3_client *clnt, unsigned short reg, unsigned short val) | ||
170 | { | ||
171 | struct uda1341 *uda = clnt->driver_data; | ||
172 | unsigned char buf[2] = { 0xc0, 0xe0 }; // for EXT addressing | ||
173 | int err = 0; | ||
174 | |||
175 | uda->regs[reg] = val; | ||
176 | |||
177 | if (uda->active) { | ||
178 | if (IS_DATA0(reg)) { | ||
179 | err = l3_write(clnt, UDA1341_DATA0, (const unsigned char *)&val, 1); | ||
180 | } else if (IS_DATA1(reg)) { | ||
181 | err = l3_write(clnt, UDA1341_DATA1, (const unsigned char *)&val, 1); | ||
182 | } else if (IS_STATUS(reg)) { | ||
183 | err = l3_write(clnt, UDA1341_STATUS, (const unsigned char *)&val, 1); | ||
184 | } else if (IS_EXTEND(reg)) { | ||
185 | buf[0] |= (reg - ext0) & 0x7; //EXT address | ||
186 | buf[1] |= val; //EXT data | ||
187 | err = l3_write(clnt, UDA1341_DATA0, (const unsigned char *)buf, 2); | ||
188 | } | ||
189 | } else | ||
190 | printk(KERN_ERR "UDA1341 codec not active!\n"); | ||
191 | return err; | ||
192 | } | ||
193 | |||
194 | static int snd_uda1341_codec_read(struct l3_client *clnt, unsigned short reg) | ||
195 | { | ||
196 | unsigned char val; | ||
197 | int err; | ||
198 | |||
199 | err = l3_read(clnt, reg, &val, 1); | ||
200 | if (err == 1) | ||
201 | // use just 6bits - the rest is address of the reg | ||
202 | return val & 63; | ||
203 | return err < 0 ? err : -EIO; | ||
204 | } | ||
205 | |||
206 | static inline int snd_uda1341_valid_reg(struct l3_client *clnt, unsigned short reg) | ||
207 | { | ||
208 | return reg < uda1341_reg_last; | ||
209 | } | ||
210 | |||
211 | static int snd_uda1341_update_bits(struct l3_client *clnt, unsigned short reg, | ||
212 | unsigned short mask, unsigned short shift, | ||
213 | unsigned short value, int flush) | ||
214 | { | ||
215 | int change; | ||
216 | unsigned short old, new; | ||
217 | struct uda1341 *uda = clnt->driver_data; | ||
218 | |||
219 | #if 0 | ||
220 | printk(KERN_DEBUG "update_bits: reg: %s mask: %d shift: %d val: %d\n", | ||
221 | uda1341_reg_names[reg], mask, shift, value); | ||
222 | #endif | ||
223 | |||
224 | if (!snd_uda1341_valid_reg(clnt, reg)) | ||
225 | return -EINVAL; | ||
226 | spin_lock(&uda->reg_lock); | ||
227 | old = uda->regs[reg]; | ||
228 | new = (old & ~(mask << shift)) | (value << shift); | ||
229 | change = old != new; | ||
230 | if (change) { | ||
231 | if (flush) uda->write(clnt, reg, new); | ||
232 | uda->regs[reg] = new; | ||
233 | } | ||
234 | spin_unlock(&uda->reg_lock); | ||
235 | return change; | ||
236 | } | ||
237 | |||
238 | static int snd_uda1341_cfg_write(struct l3_client *clnt, unsigned short what, | ||
239 | unsigned short value, int flush) | ||
240 | { | ||
241 | struct uda1341 *uda = clnt->driver_data; | ||
242 | int ret = 0; | ||
243 | #ifdef CONFIG_PM | ||
244 | int reg; | ||
245 | #endif | ||
246 | |||
247 | #if 0 | ||
248 | printk(KERN_DEBUG "cfg_write what: %d value: %d\n", what, value); | ||
249 | #endif | ||
250 | |||
251 | uda->cfg[what] = value; | ||
252 | |||
253 | switch(what) { | ||
254 | case CMD_RESET: | ||
255 | ret = snd_uda1341_update_bits(clnt, data0_2, 1, 2, 1, flush); // MUTE | ||
256 | ret = snd_uda1341_update_bits(clnt, stat0, 1, 6, 1, flush); // RESET | ||
257 | ret = snd_uda1341_update_bits(clnt, stat0, 1, 6, 0, flush); // RESTORE | ||
258 | uda->cfg[CMD_RESET]=0; | ||
259 | break; | ||
260 | case CMD_FS: | ||
261 | ret = snd_uda1341_update_bits(clnt, stat0, 3, 4, value, flush); | ||
262 | break; | ||
263 | case CMD_FORMAT: | ||
264 | ret = snd_uda1341_update_bits(clnt, stat0, 7, 1, value, flush); | ||
265 | break; | ||
266 | case CMD_OGAIN: | ||
267 | ret = snd_uda1341_update_bits(clnt, stat1, 1, 6, value, flush); | ||
268 | break; | ||
269 | case CMD_IGAIN: | ||
270 | ret = snd_uda1341_update_bits(clnt, stat1, 1, 5, value, flush); | ||
271 | break; | ||
272 | case CMD_DAC: | ||
273 | ret = snd_uda1341_update_bits(clnt, stat1, 1, 0, value, flush); | ||
274 | break; | ||
275 | case CMD_ADC: | ||
276 | ret = snd_uda1341_update_bits(clnt, stat1, 1, 1, value, flush); | ||
277 | break; | ||
278 | case CMD_VOLUME: | ||
279 | ret = snd_uda1341_update_bits(clnt, data0_0, 63, 0, value, flush); | ||
280 | break; | ||
281 | case CMD_BASS: | ||
282 | ret = snd_uda1341_update_bits(clnt, data0_1, 15, 2, value, flush); | ||
283 | break; | ||
284 | case CMD_TREBBLE: | ||
285 | ret = snd_uda1341_update_bits(clnt, data0_1, 3, 0, value, flush); | ||
286 | break; | ||
287 | case CMD_PEAK: | ||
288 | ret = snd_uda1341_update_bits(clnt, data0_2, 1, 5, value, flush); | ||
289 | break; | ||
290 | case CMD_DEEMP: | ||
291 | ret = snd_uda1341_update_bits(clnt, data0_2, 3, 3, value, flush); | ||
292 | break; | ||
293 | case CMD_MUTE: | ||
294 | ret = snd_uda1341_update_bits(clnt, data0_2, 1, 2, value, flush); | ||
295 | break; | ||
296 | case CMD_FILTER: | ||
297 | ret = snd_uda1341_update_bits(clnt, data0_2, 3, 0, value, flush); | ||
298 | break; | ||
299 | case CMD_CH1: | ||
300 | ret = snd_uda1341_update_bits(clnt, ext0, 31, 0, value, flush); | ||
301 | break; | ||
302 | case CMD_CH2: | ||
303 | ret = snd_uda1341_update_bits(clnt, ext1, 31, 0, value, flush); | ||
304 | break; | ||
305 | case CMD_MIC: | ||
306 | ret = snd_uda1341_update_bits(clnt, ext2, 7, 2, value, flush); | ||
307 | break; | ||
308 | case CMD_MIXER: | ||
309 | ret = snd_uda1341_update_bits(clnt, ext2, 3, 0, value, flush); | ||
310 | break; | ||
311 | case CMD_AGC: | ||
312 | ret = snd_uda1341_update_bits(clnt, ext4, 1, 4, value, flush); | ||
313 | break; | ||
314 | case CMD_IG: | ||
315 | ret = snd_uda1341_update_bits(clnt, ext4, 3, 0, value & 0x3, flush); | ||
316 | ret = snd_uda1341_update_bits(clnt, ext5, 31, 0, value >> 2, flush); | ||
317 | break; | ||
318 | case CMD_AGC_TIME: | ||
319 | ret = snd_uda1341_update_bits(clnt, ext6, 7, 2, value, flush); | ||
320 | break; | ||
321 | case CMD_AGC_LEVEL: | ||
322 | ret = snd_uda1341_update_bits(clnt, ext6, 3, 0, value, flush); | ||
323 | break; | ||
324 | #ifdef CONFIG_PM | ||
325 | case CMD_SUSPEND: | ||
326 | for (reg = stat0; reg < uda1341_reg_last; reg++) | ||
327 | uda->suspend_regs[reg] = uda->regs[reg]; | ||
328 | for (reg = 0; reg < CMD_LAST; reg++) | ||
329 | uda->suspend_cfg[reg] = uda->cfg[reg]; | ||
330 | break; | ||
331 | case CMD_RESUME: | ||
332 | for (reg = stat0; reg < uda1341_reg_last; reg++) | ||
333 | snd_uda1341_codec_write(clnt, reg, uda->suspend_regs[reg]); | ||
334 | for (reg = 0; reg < CMD_LAST; reg++) | ||
335 | uda->cfg[reg] = uda->suspend_cfg[reg]; | ||
336 | break; | ||
337 | #endif | ||
338 | default: | ||
339 | ret = -EINVAL; | ||
340 | break; | ||
341 | } | ||
342 | |||
343 | if (!uda->active) | ||
344 | printk(KERN_ERR "UDA1341 codec not active!\n"); | ||
345 | return ret; | ||
346 | } | ||
347 | |||
348 | /* }}} */ | ||
349 | |||
350 | /* {{{ Proc interface */ | ||
351 | #ifdef CONFIG_PROC_FS | ||
352 | |||
353 | static const char *format_names[] = { | ||
354 | "I2S-bus", | ||
355 | "LSB 16bits", | ||
356 | "LSB 18bits", | ||
357 | "LSB 20bits", | ||
358 | "MSB", | ||
359 | "in LSB 16bits/out MSB", | ||
360 | "in LSB 18bits/out MSB", | ||
361 | "in LSB 20bits/out MSB", | ||
362 | }; | ||
363 | |||
364 | static const char *fs_names[] = { | ||
365 | "512*fs", | ||
366 | "384*fs", | ||
367 | "256*fs", | ||
368 | "Unused - bad value!", | ||
369 | }; | ||
370 | |||
371 | static const char* bass_values[][16] = { | ||
372 | {"0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB", | ||
373 | "0 dB", "0 dB", "0 dB", "0 dB", "undefined", }, //flat | ||
374 | {"0 dB", "2 dB", "4 dB", "6 dB", "8 dB", "10 dB", "12 dB", "14 dB", "16 dB", "18 dB", "18 dB", | ||
375 | "18 dB", "18 dB", "18 dB", "18 dB", "undefined",}, // min | ||
376 | {"0 dB", "2 dB", "4 dB", "6 dB", "8 dB", "10 dB", "12 dB", "14 dB", "16 dB", "18 dB", "18 dB", | ||
377 | "18 dB", "18 dB", "18 dB", "18 dB", "undefined",}, // min | ||
378 | {"0 dB", "2 dB", "4 dB", "6 dB", "8 dB", "10 dB", "12 dB", "14 dB", "16 dB", "18 dB", "20 dB", | ||
379 | "22 dB", "24 dB", "24 dB", "24 dB", "undefined",}, // max | ||
380 | }; | ||
381 | |||
382 | static const char *mic_sens_value[] = { | ||
383 | "-3 dB", "0 dB", "3 dB", "9 dB", "15 dB", "21 dB", "27 dB", "not used", | ||
384 | }; | ||
385 | |||
386 | static const unsigned short AGC_atime[] = { | ||
387 | 11, 16, 11, 16, 21, 11, 16, 21, | ||
388 | }; | ||
389 | |||
390 | static const unsigned short AGC_dtime[] = { | ||
391 | 100, 100, 200, 200, 200, 400, 400, 400, | ||
392 | }; | ||
393 | |||
394 | static const char *AGC_level[] = { | ||
395 | "-9.0", "-11.5", "-15.0", "-17.5", | ||
396 | }; | ||
397 | |||
398 | static const char *ig_small_value[] = { | ||
399 | "-3.0", "-2.5", "-2.0", "-1.5", "-1.0", "-0.5", | ||
400 | }; | ||
401 | |||
402 | /* | ||
403 | * this was computed as peak_value[i] = pow((63-i)*1.42,1.013) | ||
404 | * | ||
405 | * UDA1341 datasheet on page 21: Peak value (dB) = (Peak level - 63.5)*5*log2 | ||
406 | * There is an table with these values [level]=value: [3]=-90.31, [7]=-84.29 | ||
407 | * [61]=-2.78, [62] = -1.48, [63] = 0.0 | ||
408 | * I tried to compute it, but using but even using logarithm with base either 10 or 2 | ||
409 | * i was'n able to get values in the table from the formula. So I constructed another | ||
410 | * formula (see above) to interpolate the values as good as possible. If there is some | ||
411 | * mistake, please contact me on tomas.kasparek@seznam.cz. Thanks. | ||
412 | * UDA1341TS datasheet is available at: | ||
413 | * http://www-us9.semiconductors.com/acrobat/datasheets/UDA1341TS_3.pdf | ||
414 | */ | ||
415 | static const char *peak_value[] = { | ||
416 | "-INF dB", "N.A.", "N.A", "90.31 dB", "N.A.", "N.A.", "N.A.", "-84.29 dB", | ||
417 | "-82.65 dB", "-81.13 dB", "-79.61 dB", "-78.09 dB", "-76.57 dB", "-75.05 dB", "-73.53 dB", | ||
418 | "-72.01 dB", "-70.49 dB", "-68.97 dB", "-67.45 dB", "-65.93 dB", "-64.41 dB", "-62.90 dB", | ||
419 | "-61.38 dB", "-59.86 dB", "-58.35 dB", "-56.83 dB", "-55.32 dB", "-53.80 dB", "-52.29 dB", | ||
420 | "-50.78 dB", "-49.26 dB", "-47.75 dB", "-46.24 dB", "-44.73 dB", "-43.22 dB", "-41.71 dB", | ||
421 | "-40.20 dB", "-38.69 dB", "-37.19 dB", "-35.68 dB", "-34.17 dB", "-32.67 dB", "-31.17 dB", | ||
422 | "-29.66 dB", "-28.16 dB", "-26.66 dB", "-25.16 dB", "-23.66 dB", "-22.16 dB", "-20.67 dB", | ||
423 | "-19.17 dB", "-17.68 dB", "-16.19 dB", "-14.70 dB", "-13.21 dB", "-11.72 dB", "-10.24 dB", | ||
424 | "-8.76 dB", "-7.28 dB", "-5.81 dB", "-4.34 dB", "-2.88 dB", "-1.43 dB", "0.00 dB", | ||
425 | }; | ||
426 | |||
427 | static void snd_uda1341_proc_read(struct snd_info_entry *entry, | ||
428 | struct snd_info_buffer *buffer) | ||
429 | { | ||
430 | struct l3_client *clnt = entry->private_data; | ||
431 | struct uda1341 *uda = clnt->driver_data; | ||
432 | int peak; | ||
433 | |||
434 | peak = snd_uda1341_codec_read(clnt, UDA1341_DATA1); | ||
435 | if (peak < 0) | ||
436 | peak = 0; | ||
437 | |||
438 | snd_iprintf(buffer, "%s\n\n", uda->card->longname); | ||
439 | |||
440 | // for information about computed values see UDA1341TS datasheet pages 15 - 21 | ||
441 | snd_iprintf(buffer, "DAC power : %s\n", uda->cfg[CMD_DAC] ? "on" : "off"); | ||
442 | snd_iprintf(buffer, "ADC power : %s\n", uda->cfg[CMD_ADC] ? "on" : "off"); | ||
443 | snd_iprintf(buffer, "Clock frequency : %s\n", fs_names[uda->cfg[CMD_FS]]); | ||
444 | snd_iprintf(buffer, "Data format : %s\n\n", format_names[uda->cfg[CMD_FORMAT]]); | ||
445 | |||
446 | snd_iprintf(buffer, "Filter mode : %s\n", filter_names[uda->cfg[CMD_FILTER]]); | ||
447 | snd_iprintf(buffer, "Mixer mode : %s\n", mixer_names[uda->cfg[CMD_MIXER]]); | ||
448 | snd_iprintf(buffer, "De-emphasis : %s\n", deemp_names[uda->cfg[CMD_DEEMP]]); | ||
449 | snd_iprintf(buffer, "Peak detection pos. : %s\n", uda->cfg[CMD_PEAK] ? "after" : "before"); | ||
450 | snd_iprintf(buffer, "Peak value : %s\n\n", peak_value[peak]); | ||
451 | |||
452 | snd_iprintf(buffer, "Automatic Gain Ctrl : %s\n", uda->cfg[CMD_AGC] ? "on" : "off"); | ||
453 | snd_iprintf(buffer, "AGC attack time : %d ms\n", AGC_atime[uda->cfg[CMD_AGC_TIME]]); | ||
454 | snd_iprintf(buffer, "AGC decay time : %d ms\n", AGC_dtime[uda->cfg[CMD_AGC_TIME]]); | ||
455 | snd_iprintf(buffer, "AGC output level : %s dB\n\n", AGC_level[uda->cfg[CMD_AGC_LEVEL]]); | ||
456 | |||
457 | snd_iprintf(buffer, "Mute : %s\n", uda->cfg[CMD_MUTE] ? "on" : "off"); | ||
458 | |||
459 | if (uda->cfg[CMD_VOLUME] == 0) | ||
460 | snd_iprintf(buffer, "Volume : 0 dB\n"); | ||
461 | else if (uda->cfg[CMD_VOLUME] < 62) | ||
462 | snd_iprintf(buffer, "Volume : %d dB\n", -1*uda->cfg[CMD_VOLUME] +1); | ||
463 | else | ||
464 | snd_iprintf(buffer, "Volume : -INF dB\n"); | ||
465 | snd_iprintf(buffer, "Bass : %s\n", bass_values[uda->cfg[CMD_FILTER]][uda->cfg[CMD_BASS]]); | ||
466 | snd_iprintf(buffer, "Trebble : %d dB\n", uda->cfg[CMD_FILTER] ? 2*uda->cfg[CMD_TREBBLE] : 0); | ||
467 | snd_iprintf(buffer, "Input Gain (6dB) : %s\n", uda->cfg[CMD_IGAIN] ? "on" : "off"); | ||
468 | snd_iprintf(buffer, "Output Gain (6dB) : %s\n", uda->cfg[CMD_OGAIN] ? "on" : "off"); | ||
469 | snd_iprintf(buffer, "Mic sensitivity : %s\n", mic_sens_value[uda->cfg[CMD_MIC]]); | ||
470 | |||
471 | |||
472 | if(uda->cfg[CMD_CH1] < 31) | ||
473 | snd_iprintf(buffer, "Mixer gain channel 1: -%d.%c dB\n", | ||
474 | ((uda->cfg[CMD_CH1] >> 1) * 3) + (uda->cfg[CMD_CH1] & 1), | ||
475 | uda->cfg[CMD_CH1] & 1 ? '5' : '0'); | ||
476 | else | ||
477 | snd_iprintf(buffer, "Mixer gain channel 1: -INF dB\n"); | ||
478 | if(uda->cfg[CMD_CH2] < 31) | ||
479 | snd_iprintf(buffer, "Mixer gain channel 2: -%d.%c dB\n", | ||
480 | ((uda->cfg[CMD_CH2] >> 1) * 3) + (uda->cfg[CMD_CH2] & 1), | ||
481 | uda->cfg[CMD_CH2] & 1 ? '5' : '0'); | ||
482 | else | ||
483 | snd_iprintf(buffer, "Mixer gain channel 2: -INF dB\n"); | ||
484 | |||
485 | if(uda->cfg[CMD_IG] > 5) | ||
486 | snd_iprintf(buffer, "Input Amp. Gain ch 2: %d.%c dB\n", | ||
487 | (uda->cfg[CMD_IG] >> 1) -3, uda->cfg[CMD_IG] & 1 ? '5' : '0'); | ||
488 | else | ||
489 | snd_iprintf(buffer, "Input Amp. Gain ch 2: %s dB\n", ig_small_value[uda->cfg[CMD_IG]]); | ||
490 | } | ||
491 | |||
492 | static void snd_uda1341_proc_regs_read(struct snd_info_entry *entry, | ||
493 | struct snd_info_buffer *buffer) | ||
494 | { | ||
495 | struct l3_client *clnt = entry->private_data; | ||
496 | struct uda1341 *uda = clnt->driver_data; | ||
497 | int reg; | ||
498 | char buf[12]; | ||
499 | |||
500 | for (reg = 0; reg < uda1341_reg_last; reg ++) { | ||
501 | if (reg == empty) | ||
502 | continue; | ||
503 | int2str_bin8(uda->regs[reg], buf); | ||
504 | snd_iprintf(buffer, "%s = %s\n", uda1341_reg_names[reg], buf); | ||
505 | } | ||
506 | |||
507 | int2str_bin8(snd_uda1341_codec_read(clnt, UDA1341_DATA1), buf); | ||
508 | snd_iprintf(buffer, "DATA1 = %s\n", buf); | ||
509 | } | ||
510 | #endif /* CONFIG_PROC_FS */ | ||
511 | |||
512 | static void __devinit snd_uda1341_proc_init(struct snd_card *card, struct l3_client *clnt) | ||
513 | { | ||
514 | struct snd_info_entry *entry; | ||
515 | |||
516 | if (! snd_card_proc_new(card, "uda1341", &entry)) | ||
517 | snd_info_set_text_ops(entry, clnt, snd_uda1341_proc_read); | ||
518 | if (! snd_card_proc_new(card, "uda1341-regs", &entry)) | ||
519 | snd_info_set_text_ops(entry, clnt, snd_uda1341_proc_regs_read); | ||
520 | } | ||
521 | |||
522 | /* }}} */ | ||
523 | |||
524 | /* {{{ Mixer controls setting */ | ||
525 | |||
526 | /* {{{ UDA1341 single functions */ | ||
527 | |||
528 | #define UDA1341_SINGLE(xname, where, reg, shift, mask, invert) \ | ||
529 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_uda1341_info_single, \ | ||
530 | .get = snd_uda1341_get_single, .put = snd_uda1341_put_single, \ | ||
531 | .private_value = where | (reg << 5) | (shift << 9) | (mask << 12) | (invert << 18) \ | ||
532 | } | ||
533 | |||
534 | static int snd_uda1341_info_single(struct snd_kcontrol *kcontrol, | ||
535 | struct snd_ctl_elem_info *uinfo) | ||
536 | { | ||
537 | int mask = (kcontrol->private_value >> 12) & 63; | ||
538 | |||
539 | uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
540 | uinfo->count = 1; | ||
541 | uinfo->value.integer.min = 0; | ||
542 | uinfo->value.integer.max = mask; | ||
543 | return 0; | ||
544 | } | ||
545 | |||
546 | static int snd_uda1341_get_single(struct snd_kcontrol *kcontrol, | ||
547 | struct snd_ctl_elem_value *ucontrol) | ||
548 | { | ||
549 | struct l3_client *clnt = snd_kcontrol_chip(kcontrol); | ||
550 | struct uda1341 *uda = clnt->driver_data; | ||
551 | int where = kcontrol->private_value & 31; | ||
552 | int mask = (kcontrol->private_value >> 12) & 63; | ||
553 | int invert = (kcontrol->private_value >> 18) & 1; | ||
554 | |||
555 | ucontrol->value.integer.value[0] = uda->cfg[where]; | ||
556 | if (invert) | ||
557 | ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; | ||
558 | |||
559 | return 0; | ||
560 | } | ||
561 | |||
562 | static int snd_uda1341_put_single(struct snd_kcontrol *kcontrol, | ||
563 | struct snd_ctl_elem_value *ucontrol) | ||
564 | { | ||
565 | struct l3_client *clnt = snd_kcontrol_chip(kcontrol); | ||
566 | struct uda1341 *uda = clnt->driver_data; | ||
567 | int where = kcontrol->private_value & 31; | ||
568 | int reg = (kcontrol->private_value >> 5) & 15; | ||
569 | int shift = (kcontrol->private_value >> 9) & 7; | ||
570 | int mask = (kcontrol->private_value >> 12) & 63; | ||
571 | int invert = (kcontrol->private_value >> 18) & 1; | ||
572 | unsigned short val; | ||
573 | |||
574 | val = (ucontrol->value.integer.value[0] & mask); | ||
575 | if (invert) | ||
576 | val = mask - val; | ||
577 | |||
578 | uda->cfg[where] = val; | ||
579 | return snd_uda1341_update_bits(clnt, reg, mask, shift, val, FLUSH); | ||
580 | } | ||
581 | |||
582 | /* }}} */ | ||
583 | |||
584 | /* {{{ UDA1341 enum functions */ | ||
585 | |||
586 | #define UDA1341_ENUM(xname, where, reg, shift, mask, invert) \ | ||
587 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_uda1341_info_enum, \ | ||
588 | .get = snd_uda1341_get_enum, .put = snd_uda1341_put_enum, \ | ||
589 | .private_value = where | (reg << 5) | (shift << 9) | (mask << 12) | (invert << 18) \ | ||
590 | } | ||
591 | |||
592 | static int snd_uda1341_info_enum(struct snd_kcontrol *kcontrol, | ||
593 | struct snd_ctl_elem_info *uinfo) | ||
594 | { | ||
595 | int where = kcontrol->private_value & 31; | ||
596 | const char **texts; | ||
597 | |||
598 | // this register we don't handle this way | ||
599 | if (!uda1341_enum_items[where]) | ||
600 | return -EINVAL; | ||
601 | |||
602 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
603 | uinfo->count = 1; | ||
604 | uinfo->value.enumerated.items = uda1341_enum_items[where]; | ||
605 | |||
606 | if (uinfo->value.enumerated.item >= uda1341_enum_items[where]) | ||
607 | uinfo->value.enumerated.item = uda1341_enum_items[where] - 1; | ||
608 | |||
609 | texts = uda1341_enum_names[where]; | ||
610 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | ||
611 | return 0; | ||
612 | } | ||
613 | |||
614 | static int snd_uda1341_get_enum(struct snd_kcontrol *kcontrol, | ||
615 | struct snd_ctl_elem_value *ucontrol) | ||
616 | { | ||
617 | struct l3_client *clnt = snd_kcontrol_chip(kcontrol); | ||
618 | struct uda1341 *uda = clnt->driver_data; | ||
619 | int where = kcontrol->private_value & 31; | ||
620 | |||
621 | ucontrol->value.enumerated.item[0] = uda->cfg[where]; | ||
622 | return 0; | ||
623 | } | ||
624 | |||
625 | static int snd_uda1341_put_enum(struct snd_kcontrol *kcontrol, | ||
626 | struct snd_ctl_elem_value *ucontrol) | ||
627 | { | ||
628 | struct l3_client *clnt = snd_kcontrol_chip(kcontrol); | ||
629 | struct uda1341 *uda = clnt->driver_data; | ||
630 | int where = kcontrol->private_value & 31; | ||
631 | int reg = (kcontrol->private_value >> 5) & 15; | ||
632 | int shift = (kcontrol->private_value >> 9) & 7; | ||
633 | int mask = (kcontrol->private_value >> 12) & 63; | ||
634 | |||
635 | uda->cfg[where] = (ucontrol->value.enumerated.item[0] & mask); | ||
636 | |||
637 | return snd_uda1341_update_bits(clnt, reg, mask, shift, uda->cfg[where], FLUSH); | ||
638 | } | ||
639 | |||
640 | /* }}} */ | ||
641 | |||
642 | /* {{{ UDA1341 2regs functions */ | ||
643 | |||
644 | #define UDA1341_2REGS(xname, where, reg_1, reg_2, shift_1, shift_2, mask_1, mask_2, invert) \ | ||
645 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), .info = snd_uda1341_info_2regs, \ | ||
646 | .get = snd_uda1341_get_2regs, .put = snd_uda1341_put_2regs, \ | ||
647 | .private_value = where | (reg_1 << 5) | (reg_2 << 9) | (shift_1 << 13) | (shift_2 << 16) | \ | ||
648 | (mask_1 << 19) | (mask_2 << 25) | (invert << 31) \ | ||
649 | } | ||
650 | |||
651 | |||
652 | static int snd_uda1341_info_2regs(struct snd_kcontrol *kcontrol, | ||
653 | struct snd_ctl_elem_info *uinfo) | ||
654 | { | ||
655 | int mask_1 = (kcontrol->private_value >> 19) & 63; | ||
656 | int mask_2 = (kcontrol->private_value >> 25) & 63; | ||
657 | int mask; | ||
658 | |||
659 | mask = (mask_2 + 1) * (mask_1 + 1) - 1; | ||
660 | uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
661 | uinfo->count = 1; | ||
662 | uinfo->value.integer.min = 0; | ||
663 | uinfo->value.integer.max = mask; | ||
664 | return 0; | ||
665 | } | ||
666 | |||
667 | static int snd_uda1341_get_2regs(struct snd_kcontrol *kcontrol, | ||
668 | struct snd_ctl_elem_value *ucontrol) | ||
669 | { | ||
670 | struct l3_client *clnt = snd_kcontrol_chip(kcontrol); | ||
671 | struct uda1341 *uda = clnt->driver_data; | ||
672 | int where = kcontrol->private_value & 31; | ||
673 | int mask_1 = (kcontrol->private_value >> 19) & 63; | ||
674 | int mask_2 = (kcontrol->private_value >> 25) & 63; | ||
675 | int invert = (kcontrol->private_value >> 31) & 1; | ||
676 | int mask; | ||
677 | |||
678 | mask = (mask_2 + 1) * (mask_1 + 1) - 1; | ||
679 | |||
680 | ucontrol->value.integer.value[0] = uda->cfg[where]; | ||
681 | if (invert) | ||
682 | ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; | ||
683 | return 0; | ||
684 | } | ||
685 | |||
686 | static int snd_uda1341_put_2regs(struct snd_kcontrol *kcontrol, | ||
687 | struct snd_ctl_elem_value *ucontrol) | ||
688 | { | ||
689 | struct l3_client *clnt = snd_kcontrol_chip(kcontrol); | ||
690 | struct uda1341 *uda = clnt->driver_data; | ||
691 | int where = kcontrol->private_value & 31; | ||
692 | int reg_1 = (kcontrol->private_value >> 5) & 15; | ||
693 | int reg_2 = (kcontrol->private_value >> 9) & 15; | ||
694 | int shift_1 = (kcontrol->private_value >> 13) & 7; | ||
695 | int shift_2 = (kcontrol->private_value >> 16) & 7; | ||
696 | int mask_1 = (kcontrol->private_value >> 19) & 63; | ||
697 | int mask_2 = (kcontrol->private_value >> 25) & 63; | ||
698 | int invert = (kcontrol->private_value >> 31) & 1; | ||
699 | int mask; | ||
700 | unsigned short val1, val2, val; | ||
701 | |||
702 | val = ucontrol->value.integer.value[0]; | ||
703 | |||
704 | mask = (mask_2 + 1) * (mask_1 + 1) - 1; | ||
705 | |||
706 | val1 = val & mask_1; | ||
707 | val2 = (val / (mask_1 + 1)) & mask_2; | ||
708 | |||
709 | if (invert) { | ||
710 | val1 = mask_1 - val1; | ||
711 | val2 = mask_2 - val2; | ||
712 | } | ||
713 | |||
714 | uda->cfg[where] = invert ? mask - val : val; | ||
715 | |||
716 | //FIXME - return value | ||
717 | snd_uda1341_update_bits(clnt, reg_1, mask_1, shift_1, val1, FLUSH); | ||
718 | return snd_uda1341_update_bits(clnt, reg_2, mask_2, shift_2, val2, FLUSH); | ||
719 | } | ||
720 | |||
721 | /* }}} */ | ||
722 | |||
723 | static struct snd_kcontrol_new snd_uda1341_controls[] = { | ||
724 | UDA1341_SINGLE("Master Playback Switch", CMD_MUTE, data0_2, 2, 1, 1), | ||
725 | UDA1341_SINGLE("Master Playback Volume", CMD_VOLUME, data0_0, 0, 63, 1), | ||
726 | |||
727 | UDA1341_SINGLE("Bass Playback Volume", CMD_BASS, data0_1, 2, 15, 0), | ||
728 | UDA1341_SINGLE("Treble Playback Volume", CMD_TREBBLE, data0_1, 0, 3, 0), | ||
729 | |||
730 | UDA1341_SINGLE("Input Gain Switch", CMD_IGAIN, stat1, 5, 1, 0), | ||
731 | UDA1341_SINGLE("Output Gain Switch", CMD_OGAIN, stat1, 6, 1, 0), | ||
732 | |||
733 | UDA1341_SINGLE("Mixer Gain Channel 1 Volume", CMD_CH1, ext0, 0, 31, 1), | ||
734 | UDA1341_SINGLE("Mixer Gain Channel 2 Volume", CMD_CH2, ext1, 0, 31, 1), | ||
735 | |||
736 | UDA1341_SINGLE("Mic Sensitivity Volume", CMD_MIC, ext2, 2, 7, 0), | ||
737 | |||
738 | UDA1341_SINGLE("AGC Output Level", CMD_AGC_LEVEL, ext6, 0, 3, 0), | ||
739 | UDA1341_SINGLE("AGC Time Constant", CMD_AGC_TIME, ext6, 2, 7, 0), | ||
740 | UDA1341_SINGLE("AGC Time Constant Switch", CMD_AGC, ext4, 4, 1, 0), | ||
741 | |||
742 | UDA1341_SINGLE("DAC Power", CMD_DAC, stat1, 0, 1, 0), | ||
743 | UDA1341_SINGLE("ADC Power", CMD_ADC, stat1, 1, 1, 0), | ||
744 | |||
745 | UDA1341_ENUM("Peak detection", CMD_PEAK, data0_2, 5, 1, 0), | ||
746 | UDA1341_ENUM("De-emphasis", CMD_DEEMP, data0_2, 3, 3, 0), | ||
747 | UDA1341_ENUM("Mixer mode", CMD_MIXER, ext2, 0, 3, 0), | ||
748 | UDA1341_ENUM("Filter mode", CMD_FILTER, data0_2, 0, 3, 0), | ||
749 | |||
750 | UDA1341_2REGS("Gain Input Amplifier Gain (channel 2)", CMD_IG, ext4, ext5, 0, 0, 3, 31, 0), | ||
751 | }; | ||
752 | |||
753 | static void uda1341_free(struct l3_client *clnt) | ||
754 | { | ||
755 | l3_detach_client(clnt); // calls kfree for driver_data (struct uda1341) | ||
756 | kfree(clnt); | ||
757 | } | ||
758 | |||
759 | static int uda1341_dev_free(struct snd_device *device) | ||
760 | { | ||
761 | struct l3_client *clnt = device->device_data; | ||
762 | uda1341_free(clnt); | ||
763 | return 0; | ||
764 | } | ||
765 | |||
766 | int __init snd_chip_uda1341_mixer_new(struct snd_card *card, struct l3_client **clntp) | ||
767 | { | ||
768 | static struct snd_device_ops ops = { | ||
769 | .dev_free = uda1341_dev_free, | ||
770 | }; | ||
771 | struct l3_client *clnt; | ||
772 | int idx, err; | ||
773 | |||
774 | if (snd_BUG_ON(!card)) | ||
775 | return -EINVAL; | ||
776 | |||
777 | clnt = kzalloc(sizeof(*clnt), GFP_KERNEL); | ||
778 | if (clnt == NULL) | ||
779 | return -ENOMEM; | ||
780 | |||
781 | if ((err = l3_attach_client(clnt, "l3-bit-sa1100-gpio", UDA1341_ALSA_NAME))) { | ||
782 | kfree(clnt); | ||
783 | return err; | ||
784 | } | ||
785 | |||
786 | for (idx = 0; idx < ARRAY_SIZE(snd_uda1341_controls); idx++) { | ||
787 | if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_uda1341_controls[idx], clnt))) < 0) { | ||
788 | uda1341_free(clnt); | ||
789 | return err; | ||
790 | } | ||
791 | } | ||
792 | |||
793 | if ((err = snd_device_new(card, SNDRV_DEV_CODEC, clnt, &ops)) < 0) { | ||
794 | uda1341_free(clnt); | ||
795 | return err; | ||
796 | } | ||
797 | |||
798 | *clntp = clnt; | ||
799 | strcpy(card->mixername, "UDA1341TS Mixer"); | ||
800 | ((struct uda1341 *)clnt->driver_data)->card = card; | ||
801 | |||
802 | snd_uda1341_proc_init(card, clnt); | ||
803 | |||
804 | return 0; | ||
805 | } | ||
806 | |||
807 | /* }}} */ | ||
808 | |||
809 | /* {{{ L3 operations */ | ||
810 | |||
811 | static int uda1341_attach(struct l3_client *clnt) | ||
812 | { | ||
813 | struct uda1341 *uda; | ||
814 | |||
815 | uda = kzalloc(sizeof(*uda), 0, GFP_KERNEL); | ||
816 | if (!uda) | ||
817 | return -ENOMEM; | ||
818 | |||
819 | /* init fixed parts of my copy of registers */ | ||
820 | uda->regs[stat0] = STAT0; | ||
821 | uda->regs[stat1] = STAT1; | ||
822 | |||
823 | uda->regs[data0_0] = DATA0_0; | ||
824 | uda->regs[data0_1] = DATA0_1; | ||
825 | uda->regs[data0_2] = DATA0_2; | ||
826 | |||
827 | uda->write = snd_uda1341_codec_write; | ||
828 | uda->read = snd_uda1341_codec_read; | ||
829 | |||
830 | spin_lock_init(&uda->reg_lock); | ||
831 | |||
832 | clnt->driver_data = uda; | ||
833 | return 0; | ||
834 | } | ||
835 | |||
836 | static void uda1341_detach(struct l3_client *clnt) | ||
837 | { | ||
838 | kfree(clnt->driver_data); | ||
839 | } | ||
840 | |||
841 | static int | ||
842 | uda1341_command(struct l3_client *clnt, int cmd, void *arg) | ||
843 | { | ||
844 | if (cmd != CMD_READ_REG) | ||
845 | return snd_uda1341_cfg_write(clnt, cmd, (int) arg, FLUSH); | ||
846 | |||
847 | return snd_uda1341_codec_read(clnt, (int) arg); | ||
848 | } | ||
849 | |||
850 | static int uda1341_open(struct l3_client *clnt) | ||
851 | { | ||
852 | struct uda1341 *uda = clnt->driver_data; | ||
853 | |||
854 | uda->active = 1; | ||
855 | |||
856 | /* init default configuration */ | ||
857 | snd_uda1341_cfg_write(clnt, CMD_RESET, 0, REGS_ONLY); | ||
858 | snd_uda1341_cfg_write(clnt, CMD_FS, F256, FLUSH); // unknown state after reset | ||
859 | snd_uda1341_cfg_write(clnt, CMD_FORMAT, LSB16, FLUSH); // unknown state after reset | ||
860 | snd_uda1341_cfg_write(clnt, CMD_OGAIN, ON, FLUSH); // default off after reset | ||
861 | snd_uda1341_cfg_write(clnt, CMD_IGAIN, ON, FLUSH); // default off after reset | ||
862 | snd_uda1341_cfg_write(clnt, CMD_DAC, ON, FLUSH); // ??? default value after reset | ||
863 | snd_uda1341_cfg_write(clnt, CMD_ADC, ON, FLUSH); // ??? default value after reset | ||
864 | snd_uda1341_cfg_write(clnt, CMD_VOLUME, 20, FLUSH); // default 0dB after reset | ||
865 | snd_uda1341_cfg_write(clnt, CMD_BASS, 0, REGS_ONLY); // default value after reset | ||
866 | snd_uda1341_cfg_write(clnt, CMD_TREBBLE, 0, REGS_ONLY); // default value after reset | ||
867 | snd_uda1341_cfg_write(clnt, CMD_PEAK, AFTER, REGS_ONLY);// default value after reset | ||
868 | snd_uda1341_cfg_write(clnt, CMD_DEEMP, NONE, REGS_ONLY);// default value after reset | ||
869 | //at this moment should be QMUTED by h3600_audio_init | ||
870 | snd_uda1341_cfg_write(clnt, CMD_MUTE, OFF, REGS_ONLY); // default value after reset | ||
871 | snd_uda1341_cfg_write(clnt, CMD_FILTER, MAX, FLUSH); // defaul flat after reset | ||
872 | snd_uda1341_cfg_write(clnt, CMD_CH1, 31, FLUSH); // default value after reset | ||
873 | snd_uda1341_cfg_write(clnt, CMD_CH2, 4, FLUSH); // default value after reset | ||
874 | snd_uda1341_cfg_write(clnt, CMD_MIC, 4, FLUSH); // default 0dB after reset | ||
875 | snd_uda1341_cfg_write(clnt, CMD_MIXER, MIXER, FLUSH); // default doub.dif.mode | ||
876 | snd_uda1341_cfg_write(clnt, CMD_AGC, OFF, FLUSH); // default value after reset | ||
877 | snd_uda1341_cfg_write(clnt, CMD_IG, 0, FLUSH); // unknown state after reset | ||
878 | snd_uda1341_cfg_write(clnt, CMD_AGC_TIME, 0, FLUSH); // default value after reset | ||
879 | snd_uda1341_cfg_write(clnt, CMD_AGC_LEVEL, 0, FLUSH); // default value after reset | ||
880 | |||
881 | return 0; | ||
882 | } | ||
883 | |||
884 | static void uda1341_close(struct l3_client *clnt) | ||
885 | { | ||
886 | struct uda1341 *uda = clnt->driver_data; | ||
887 | |||
888 | uda->active = 0; | ||
889 | } | ||
890 | |||
891 | /* }}} */ | ||
892 | |||
893 | /* {{{ Module and L3 initialization */ | ||
894 | |||
895 | static struct l3_ops uda1341_ops = { | ||
896 | .open = uda1341_open, | ||
897 | .command = uda1341_command, | ||
898 | .close = uda1341_close, | ||
899 | }; | ||
900 | |||
901 | static struct l3_driver uda1341_driver = { | ||
902 | .name = UDA1341_ALSA_NAME, | ||
903 | .attach_client = uda1341_attach, | ||
904 | .detach_client = uda1341_detach, | ||
905 | .ops = &uda1341_ops, | ||
906 | .owner = THIS_MODULE, | ||
907 | }; | ||
908 | |||
909 | static int __init uda1341_init(void) | ||
910 | { | ||
911 | return l3_add_driver(&uda1341_driver); | ||
912 | } | ||
913 | |||
914 | static void __exit uda1341_exit(void) | ||
915 | { | ||
916 | l3_del_driver(&uda1341_driver); | ||
917 | } | ||
918 | |||
919 | module_init(uda1341_init); | ||
920 | module_exit(uda1341_exit); | ||
921 | |||
922 | MODULE_AUTHOR("Tomas Kasparek <tomas.kasparek@seznam.cz>"); | ||
923 | MODULE_LICENSE("GPL"); | ||
924 | MODULE_DESCRIPTION("Philips UDA1341 CODEC driver for ALSA"); | ||
925 | MODULE_SUPPORTED_DEVICE("{{UDA1341,UDA1341TS}}"); | ||
926 | |||
927 | EXPORT_SYMBOL(snd_chip_uda1341_mixer_new); | ||
928 | |||
929 | /* }}} */ | ||
930 | |||
931 | /* | ||
932 | * Local variables: | ||
933 | * indent-tabs-mode: t | ||
934 | * End: | ||
935 | */ | ||
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig index ce0aa044e274..c5c9a9218ff6 100644 --- a/sound/isa/Kconfig +++ b/sound/isa/Kconfig | |||
@@ -56,8 +56,8 @@ config SND_AD1848 | |||
56 | Say Y here to include support for AD1848 (Analog Devices) or | 56 | Say Y here to include support for AD1848 (Analog Devices) or |
57 | CS4248 (Cirrus Logic - Crystal Semiconductors) chips. | 57 | CS4248 (Cirrus Logic - Crystal Semiconductors) chips. |
58 | 58 | ||
59 | For newer chips from Cirrus Logic, use the CS4231, CS4232 or | 59 | For newer chips from Cirrus Logic, use the CS4231 or CS4232+ |
60 | CS4236+ drivers. | 60 | drivers. |
61 | 61 | ||
62 | To compile this driver as a module, choose M here: the module | 62 | To compile this driver as a module, choose M here: the module |
63 | will be called snd-ad1848. | 63 | will be called snd-ad1848. |
@@ -94,6 +94,8 @@ config SND_CMI8330 | |||
94 | tristate "C-Media CMI8330" | 94 | tristate "C-Media CMI8330" |
95 | select SND_WSS_LIB | 95 | select SND_WSS_LIB |
96 | select SND_SB16_DSP | 96 | select SND_SB16_DSP |
97 | select SND_OPL3_LIB | ||
98 | select SND_MPU401_UART | ||
97 | help | 99 | help |
98 | Say Y here to include support for soundcards based on the | 100 | Say Y here to include support for soundcards based on the |
99 | C-Media CMI8330 chip. | 101 | C-Media CMI8330 chip. |
@@ -112,26 +114,15 @@ config SND_CS4231 | |||
112 | To compile this driver as a module, choose M here: the module | 114 | To compile this driver as a module, choose M here: the module |
113 | will be called snd-cs4231. | 115 | will be called snd-cs4231. |
114 | 116 | ||
115 | config SND_CS4232 | ||
116 | tristate "Generic Cirrus Logic CS4232 driver" | ||
117 | select SND_OPL3_LIB | ||
118 | select SND_MPU401_UART | ||
119 | select SND_WSS_LIB | ||
120 | help | ||
121 | Say Y here to include support for CS4232 chips from Cirrus | ||
122 | Logic - Crystal Semiconductors. | ||
123 | |||
124 | To compile this driver as a module, choose M here: the module | ||
125 | will be called snd-cs4232. | ||
126 | |||
127 | config SND_CS4236 | 117 | config SND_CS4236 |
128 | tristate "Generic Cirrus Logic CS4236+ driver" | 118 | tristate "Generic Cirrus Logic CS4232/CS4236+ driver" |
129 | select SND_OPL3_LIB | 119 | select SND_OPL3_LIB |
130 | select SND_MPU401_UART | 120 | select SND_MPU401_UART |
131 | select SND_WSS_LIB | 121 | select SND_WSS_LIB |
132 | help | 122 | help |
133 | Say Y to include support for CS4235,CS4236,CS4237B,CS4238B, | 123 | Say Y to include support for CS4232,CS4235,CS4236,CS4237B, |
134 | CS4239 chips from Cirrus Logic - Crystal Semiconductors. | 124 | CS4238B,CS4239 chips from Cirrus Logic - Crystal |
125 | Semiconductors. | ||
135 | 126 | ||
136 | To compile this driver as a module, choose M here: the module | 127 | To compile this driver as a module, choose M here: the module |
137 | will be called snd-cs4236. | 128 | will be called snd-cs4236. |
@@ -377,14 +368,17 @@ config SND_SGALAXY | |||
377 | will be called snd-sgalaxy. | 368 | will be called snd-sgalaxy. |
378 | 369 | ||
379 | config SND_SSCAPE | 370 | config SND_SSCAPE |
380 | tristate "Ensoniq SoundScape PnP driver" | 371 | tristate "Ensoniq SoundScape driver" |
381 | select SND_HWDEP | 372 | select SND_HWDEP |
382 | select SND_MPU401_UART | 373 | select SND_MPU401_UART |
383 | select SND_WSS_LIB | 374 | select SND_WSS_LIB |
384 | help | 375 | help |
385 | Say Y here to include support for Ensoniq SoundScape PnP | 376 | Say Y here to include support for Ensoniq SoundScape |
386 | soundcards. | 377 | soundcards. |
387 | 378 | ||
379 | The PCM audio is supported on SoundScape Classic, Elite, PnP | ||
380 | and VIVO cards. The MIDI support is very experimental. | ||
381 | |||
388 | To compile this driver as a module, choose M here: the module | 382 | To compile this driver as a module, choose M here: the module |
389 | will be called snd-sscape. | 383 | will be called snd-sscape. |
390 | 384 | ||
@@ -411,5 +405,36 @@ config SND_WAVEFRONT_FIRMWARE_IN_KERNEL | |||
411 | you need to install the firmware files from the | 405 | you need to install the firmware files from the |
412 | alsa-firmware package. | 406 | alsa-firmware package. |
413 | 407 | ||
408 | config SND_MSND_PINNACLE | ||
409 | tristate "Turtle Beach MultiSound Pinnacle/Fiji driver" | ||
410 | depends on X86 && EXPERIMENTAL | ||
411 | select FW_LOADER | ||
412 | select SND_MPU401_UART | ||
413 | select SND_PCM | ||
414 | help | ||
415 | Say Y to include support for Turtle Beach MultiSound Pinnacle/ | ||
416 | Fiji soundcards. | ||
417 | |||
418 | To compile this driver as a module, choose M here: the module | ||
419 | will be called snd-msnd-pinnacle. | ||
420 | |||
421 | config SND_MSND_CLASSIC | ||
422 | tristate "Support for Turtle Beach MultiSound Classic, Tahiti, Monterey" | ||
423 | depends on X86 && EXPERIMENTAL | ||
424 | select FW_LOADER | ||
425 | select SND_MPU401_UART | ||
426 | select SND_PCM | ||
427 | help | ||
428 | Say M here if you have a Turtle Beach MultiSound Classic, Tahiti or | ||
429 | Monterey (not for the Pinnacle or Fiji). | ||
430 | |||
431 | See <file:Documentation/sound/oss/MultiSound> for important information | ||
432 | about this driver. Note that it has been discontinued, but the | ||
433 | Voyetra Turtle Beach knowledge base entry for it is still available | ||
434 | at <http://www.turtlebeach.com/site/kb_ftp/790.asp>. | ||
435 | |||
436 | To compile this driver as a module, choose M here: the module | ||
437 | will be called snd-msnd-classic. | ||
438 | |||
414 | endif # SND_ISA | 439 | endif # SND_ISA |
415 | 440 | ||
diff --git a/sound/isa/Makefile b/sound/isa/Makefile index 63af13d901a5..b906b9a1a81e 100644 --- a/sound/isa/Makefile +++ b/sound/isa/Makefile | |||
@@ -26,5 +26,5 @@ obj-$(CONFIG_SND_SC6000) += snd-sc6000.o | |||
26 | obj-$(CONFIG_SND_SGALAXY) += snd-sgalaxy.o | 26 | obj-$(CONFIG_SND_SGALAXY) += snd-sgalaxy.o |
27 | obj-$(CONFIG_SND_SSCAPE) += snd-sscape.o | 27 | obj-$(CONFIG_SND_SSCAPE) += snd-sscape.o |
28 | 28 | ||
29 | obj-$(CONFIG_SND) += ad1816a/ ad1848/ cs423x/ es1688/ gus/ opti9xx/ \ | 29 | obj-$(CONFIG_SND) += ad1816a/ ad1848/ cs423x/ es1688/ gus/ msnd/ opti9xx/ \ |
30 | sb/ wavefront/ wss/ | 30 | sb/ wavefront/ wss/ |
diff --git a/sound/isa/ad1816a/ad1816a.c b/sound/isa/ad1816a/ad1816a.c index 77524244a846..bbcbf92a8ebe 100644 --- a/sound/isa/ad1816a/ad1816a.c +++ b/sound/isa/ad1816a/ad1816a.c | |||
@@ -156,10 +156,12 @@ static int __devinit snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard | |||
156 | struct snd_card_ad1816a *acard; | 156 | struct snd_card_ad1816a *acard; |
157 | struct snd_ad1816a *chip; | 157 | struct snd_ad1816a *chip; |
158 | struct snd_opl3 *opl3; | 158 | struct snd_opl3 *opl3; |
159 | struct snd_timer *timer; | ||
159 | 160 | ||
160 | if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE, | 161 | error = snd_card_create(index[dev], id[dev], THIS_MODULE, |
161 | sizeof(struct snd_card_ad1816a))) == NULL) | 162 | sizeof(struct snd_card_ad1816a), &card); |
162 | return -ENOMEM; | 163 | if (error < 0) |
164 | return error; | ||
163 | acard = (struct snd_card_ad1816a *)card->private_data; | 165 | acard = (struct snd_card_ad1816a *)card->private_data; |
164 | 166 | ||
165 | if ((error = snd_card_ad1816a_pnp(dev, acard, pcard, pid))) { | 167 | if ((error = snd_card_ad1816a_pnp(dev, acard, pcard, pid))) { |
@@ -194,6 +196,12 @@ static int __devinit snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard | |||
194 | return error; | 196 | return error; |
195 | } | 197 | } |
196 | 198 | ||
199 | error = snd_ad1816a_timer(chip, 0, &timer); | ||
200 | if (error < 0) { | ||
201 | snd_card_free(card); | ||
202 | return error; | ||
203 | } | ||
204 | |||
197 | if (mpu_port[dev] > 0) { | 205 | if (mpu_port[dev] > 0) { |
198 | if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, | 206 | if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, |
199 | mpu_port[dev], 0, mpu_irq[dev], IRQF_DISABLED, | 207 | mpu_port[dev], 0, mpu_irq[dev], IRQF_DISABLED, |
@@ -207,11 +215,8 @@ static int __devinit snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard | |||
207 | OPL3_HW_AUTO, 0, &opl3) < 0) { | 215 | OPL3_HW_AUTO, 0, &opl3) < 0) { |
208 | printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx.\n", fm_port[dev], fm_port[dev] + 2); | 216 | printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx.\n", fm_port[dev], fm_port[dev] + 2); |
209 | } else { | 217 | } else { |
210 | if ((error = snd_opl3_timer_new(opl3, 1, 2)) < 0) { | 218 | error = snd_opl3_hwdep_new(opl3, 0, 1, NULL); |
211 | snd_card_free(card); | 219 | if (error < 0) { |
212 | return error; | ||
213 | } | ||
214 | if ((error = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) { | ||
215 | snd_card_free(card); | 220 | snd_card_free(card); |
216 | return error; | 221 | return error; |
217 | } | 222 | } |
diff --git a/sound/isa/ad1816a/ad1816a_lib.c b/sound/isa/ad1816a/ad1816a_lib.c index 3bfca7c59baf..05aef8b97e96 100644 --- a/sound/isa/ad1816a/ad1816a_lib.c +++ b/sound/isa/ad1816a/ad1816a_lib.c | |||
@@ -37,7 +37,7 @@ static inline int snd_ad1816a_busy_wait(struct snd_ad1816a *chip) | |||
37 | if (inb(AD1816A_REG(AD1816A_CHIP_STATUS)) & AD1816A_READY) | 37 | if (inb(AD1816A_REG(AD1816A_CHIP_STATUS)) & AD1816A_READY) |
38 | return 0; | 38 | return 0; |
39 | 39 | ||
40 | snd_printk("chip busy.\n"); | 40 | snd_printk(KERN_WARNING "chip busy.\n"); |
41 | return -EBUSY; | 41 | return -EBUSY; |
42 | } | 42 | } |
43 | 43 | ||
@@ -196,7 +196,7 @@ static int snd_ad1816a_trigger(struct snd_ad1816a *chip, unsigned char what, | |||
196 | spin_unlock(&chip->lock); | 196 | spin_unlock(&chip->lock); |
197 | break; | 197 | break; |
198 | default: | 198 | default: |
199 | snd_printk("invalid trigger mode 0x%x.\n", what); | 199 | snd_printk(KERN_WARNING "invalid trigger mode 0x%x.\n", what); |
200 | error = -EINVAL; | 200 | error = -EINVAL; |
201 | } | 201 | } |
202 | 202 | ||
@@ -377,7 +377,6 @@ static struct snd_pcm_hardware snd_ad1816a_capture = { | |||
377 | .fifo_size = 0, | 377 | .fifo_size = 0, |
378 | }; | 378 | }; |
379 | 379 | ||
380 | #if 0 /* not used now */ | ||
381 | static int snd_ad1816a_timer_close(struct snd_timer *timer) | 380 | static int snd_ad1816a_timer_close(struct snd_timer *timer) |
382 | { | 381 | { |
383 | struct snd_ad1816a *chip = snd_timer_chip(timer); | 382 | struct snd_ad1816a *chip = snd_timer_chip(timer); |
@@ -442,8 +441,6 @@ static struct snd_timer_hardware snd_ad1816a_timer_table = { | |||
442 | .start = snd_ad1816a_timer_start, | 441 | .start = snd_ad1816a_timer_start, |
443 | .stop = snd_ad1816a_timer_stop, | 442 | .stop = snd_ad1816a_timer_stop, |
444 | }; | 443 | }; |
445 | #endif /* not used now */ | ||
446 | |||
447 | 444 | ||
448 | static int snd_ad1816a_playback_open(struct snd_pcm_substream *substream) | 445 | static int snd_ad1816a_playback_open(struct snd_pcm_substream *substream) |
449 | { | 446 | { |
@@ -568,7 +565,7 @@ static const char __devinit *snd_ad1816a_chip_id(struct snd_ad1816a *chip) | |||
568 | case AD1816A_HW_AD1815: return "AD1815"; | 565 | case AD1816A_HW_AD1815: return "AD1815"; |
569 | case AD1816A_HW_AD18MAX10: return "AD18max10"; | 566 | case AD1816A_HW_AD18MAX10: return "AD18max10"; |
570 | default: | 567 | default: |
571 | snd_printk("Unknown chip version %d:%d.\n", | 568 | snd_printk(KERN_WARNING "Unknown chip version %d:%d.\n", |
572 | chip->version, chip->hardware); | 569 | chip->version, chip->hardware); |
573 | return "AD1816A - unknown"; | 570 | return "AD1816A - unknown"; |
574 | } | 571 | } |
@@ -687,7 +684,6 @@ int __devinit snd_ad1816a_pcm(struct snd_ad1816a *chip, int device, struct snd_p | |||
687 | return 0; | 684 | return 0; |
688 | } | 685 | } |
689 | 686 | ||
690 | #if 0 /* not used now */ | ||
691 | int __devinit snd_ad1816a_timer(struct snd_ad1816a *chip, int device, struct snd_timer **rtimer) | 687 | int __devinit snd_ad1816a_timer(struct snd_ad1816a *chip, int device, struct snd_timer **rtimer) |
692 | { | 688 | { |
693 | struct snd_timer *timer; | 689 | struct snd_timer *timer; |
@@ -709,7 +705,6 @@ int __devinit snd_ad1816a_timer(struct snd_ad1816a *chip, int device, struct snd | |||
709 | *rtimer = timer; | 705 | *rtimer = timer; |
710 | return 0; | 706 | return 0; |
711 | } | 707 | } |
712 | #endif /* not used now */ | ||
713 | 708 | ||
714 | /* | 709 | /* |
715 | * | 710 | * |
diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c index 223a6c038819..4beeb6f98e0e 100644 --- a/sound/isa/ad1848/ad1848.c +++ b/sound/isa/ad1848/ad1848.c | |||
@@ -91,9 +91,9 @@ static int __devinit snd_ad1848_probe(struct device *dev, unsigned int n) | |||
91 | struct snd_pcm *pcm; | 91 | struct snd_pcm *pcm; |
92 | int error; | 92 | int error; |
93 | 93 | ||
94 | card = snd_card_new(index[n], id[n], THIS_MODULE, 0); | 94 | error = snd_card_create(index[n], id[n], THIS_MODULE, 0, &card); |
95 | if (!card) | 95 | if (error < 0) |
96 | return -EINVAL; | 96 | return error; |
97 | 97 | ||
98 | error = snd_wss_create(card, port[n], -1, irq[n], dma1[n], -1, | 98 | error = snd_wss_create(card, port[n], -1, irq[n], dma1[n], -1, |
99 | thinkpad[n] ? WSS_HW_THINKPAD : WSS_HW_DETECT, | 99 | thinkpad[n] ? WSS_HW_THINKPAD : WSS_HW_DETECT, |
diff --git a/sound/isa/adlib.c b/sound/isa/adlib.c index 374b7177e111..7465ae036e0b 100644 --- a/sound/isa/adlib.c +++ b/sound/isa/adlib.c | |||
@@ -53,10 +53,10 @@ static int __devinit snd_adlib_probe(struct device *dev, unsigned int n) | |||
53 | struct snd_opl3 *opl3; | 53 | struct snd_opl3 *opl3; |
54 | int error; | 54 | int error; |
55 | 55 | ||
56 | card = snd_card_new(index[n], id[n], THIS_MODULE, 0); | 56 | error = snd_card_create(index[n], id[n], THIS_MODULE, 0, &card); |
57 | if (!card) { | 57 | if (error < 0) { |
58 | dev_err(dev, "could not create card\n"); | 58 | dev_err(dev, "could not create card\n"); |
59 | return -EINVAL; | 59 | return error; |
60 | } | 60 | } |
61 | 61 | ||
62 | card->private_data = request_region(port[n], 4, CRD_NAME); | 62 | card->private_data = request_region(port[n], 4, CRD_NAME); |
diff --git a/sound/isa/als100.c b/sound/isa/als100.c index f1ce30f379c9..5fd52e4d7079 100644 --- a/sound/isa/als100.c +++ b/sound/isa/als100.c | |||
@@ -163,9 +163,10 @@ static int __devinit snd_card_als100_probe(int dev, | |||
163 | struct snd_card_als100 *acard; | 163 | struct snd_card_als100 *acard; |
164 | struct snd_opl3 *opl3; | 164 | struct snd_opl3 *opl3; |
165 | 165 | ||
166 | if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE, | 166 | error = snd_card_create(index[dev], id[dev], THIS_MODULE, |
167 | sizeof(struct snd_card_als100))) == NULL) | 167 | sizeof(struct snd_card_als100), &card); |
168 | return -ENOMEM; | 168 | if (error < 0) |
169 | return error; | ||
169 | acard = card->private_data; | 170 | acard = card->private_data; |
170 | 171 | ||
171 | if ((error = snd_card_als100_pnp(dev, acard, pcard, pid))) { | 172 | if ((error = snd_card_als100_pnp(dev, acard, pcard, pid))) { |
diff --git a/sound/isa/azt2320.c b/sound/isa/azt2320.c index 3e74d1a3928e..f7aa637b0d18 100644 --- a/sound/isa/azt2320.c +++ b/sound/isa/azt2320.c | |||
@@ -184,9 +184,10 @@ static int __devinit snd_card_azt2320_probe(int dev, | |||
184 | struct snd_wss *chip; | 184 | struct snd_wss *chip; |
185 | struct snd_opl3 *opl3; | 185 | struct snd_opl3 *opl3; |
186 | 186 | ||
187 | if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE, | 187 | error = snd_card_create(index[dev], id[dev], THIS_MODULE, |
188 | sizeof(struct snd_card_azt2320))) == NULL) | 188 | sizeof(struct snd_card_azt2320), &card); |
189 | return -ENOMEM; | 189 | if (error < 0) |
190 | return error; | ||
190 | acard = (struct snd_card_azt2320 *)card->private_data; | 191 | acard = (struct snd_card_azt2320 *)card->private_data; |
191 | 192 | ||
192 | if ((error = snd_card_azt2320_pnp(dev, acard, pcard, pid))) { | 193 | if ((error = snd_card_azt2320_pnp(dev, acard, pcard, pid))) { |
diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c index e49aec700a55..de83608719ea 100644 --- a/sound/isa/cmi8330.c +++ b/sound/isa/cmi8330.c | |||
@@ -31,11 +31,11 @@ | |||
31 | * To quickly load the module, | 31 | * To quickly load the module, |
32 | * | 32 | * |
33 | * modprobe -a snd-cmi8330 sbport=0x220 sbirq=5 sbdma8=1 | 33 | * modprobe -a snd-cmi8330 sbport=0x220 sbirq=5 sbdma8=1 |
34 | * sbdma16=5 wssport=0x530 wssirq=11 wssdma=0 | 34 | * sbdma16=5 wssport=0x530 wssirq=11 wssdma=0 fmport=0x388 |
35 | * | 35 | * |
36 | * This card has two mixers and two PCM devices. I've cheesed it such | 36 | * This card has two mixers and two PCM devices. I've cheesed it such |
37 | * that recording and playback can be done through the same device. | 37 | * that recording and playback can be done through the same device. |
38 | * The driver "magically" routes the capturing to the AD1848 codec, | 38 | * The driver "magically" routes the capturing to the CMI8330 codec, |
39 | * and playback to the SB16 codec. This allows for full-duplex mode | 39 | * and playback to the SB16 codec. This allows for full-duplex mode |
40 | * to some extent. | 40 | * to some extent. |
41 | * The utilities in alsa-utils are aware of both devices, so passing | 41 | * The utilities in alsa-utils are aware of both devices, so passing |
@@ -51,6 +51,8 @@ | |||
51 | #include <linux/moduleparam.h> | 51 | #include <linux/moduleparam.h> |
52 | #include <sound/core.h> | 52 | #include <sound/core.h> |
53 | #include <sound/wss.h> | 53 | #include <sound/wss.h> |
54 | #include <sound/opl3.h> | ||
55 | #include <sound/mpu401.h> | ||
54 | #include <sound/sb.h> | 56 | #include <sound/sb.h> |
55 | #include <sound/initval.h> | 57 | #include <sound/initval.h> |
56 | 58 | ||
@@ -79,6 +81,9 @@ static int sbdma16[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; | |||
79 | static long wssport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; | 81 | static long wssport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; |
80 | static int wssirq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; | 82 | static int wssirq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; |
81 | static int wssdma[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; | 83 | static int wssdma[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; |
84 | static long fmport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; | ||
85 | static long mpuport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; | ||
86 | static int mpuirq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; | ||
82 | 87 | ||
83 | module_param_array(index, int, NULL, 0444); | 88 | module_param_array(index, int, NULL, 0444); |
84 | MODULE_PARM_DESC(index, "Index value for CMI8330 soundcard."); | 89 | MODULE_PARM_DESC(index, "Index value for CMI8330 soundcard."); |
@@ -107,6 +112,12 @@ MODULE_PARM_DESC(wssirq, "IRQ # for CMI8330 WSS driver."); | |||
107 | module_param_array(wssdma, int, NULL, 0444); | 112 | module_param_array(wssdma, int, NULL, 0444); |
108 | MODULE_PARM_DESC(wssdma, "DMA for CMI8330 WSS driver."); | 113 | MODULE_PARM_DESC(wssdma, "DMA for CMI8330 WSS driver."); |
109 | 114 | ||
115 | module_param_array(fmport, long, NULL, 0444); | ||
116 | MODULE_PARM_DESC(fmport, "FM port # for CMI8330 driver."); | ||
117 | module_param_array(mpuport, long, NULL, 0444); | ||
118 | MODULE_PARM_DESC(mpuport, "MPU-401 port # for CMI8330 driver."); | ||
119 | module_param_array(mpuirq, int, NULL, 0444); | ||
120 | MODULE_PARM_DESC(mpuirq, "IRQ # for CMI8330 MPU-401 port."); | ||
110 | #ifdef CONFIG_PNP | 121 | #ifdef CONFIG_PNP |
111 | static int isa_registered; | 122 | static int isa_registered; |
112 | static int pnp_registered; | 123 | static int pnp_registered; |
@@ -149,6 +160,7 @@ struct snd_cmi8330 { | |||
149 | #ifdef CONFIG_PNP | 160 | #ifdef CONFIG_PNP |
150 | struct pnp_dev *cap; | 161 | struct pnp_dev *cap; |
151 | struct pnp_dev *play; | 162 | struct pnp_dev *play; |
163 | struct pnp_dev *mpu; | ||
152 | #endif | 164 | #endif |
153 | struct snd_card *card; | 165 | struct snd_card *card; |
154 | struct snd_wss *wss; | 166 | struct snd_wss *wss; |
@@ -165,7 +177,7 @@ struct snd_cmi8330 { | |||
165 | #ifdef CONFIG_PNP | 177 | #ifdef CONFIG_PNP |
166 | 178 | ||
167 | static struct pnp_card_device_id snd_cmi8330_pnpids[] = { | 179 | static struct pnp_card_device_id snd_cmi8330_pnpids[] = { |
168 | { .id = "CMI0001", .devs = { { "@@@0001" }, { "@X@0001" } } }, | 180 | { .id = "CMI0001", .devs = { { "@@@0001" }, { "@X@0001" }, { "@H@0001" } } }, |
169 | { .id = "" } | 181 | { .id = "" } |
170 | }; | 182 | }; |
171 | 183 | ||
@@ -219,8 +231,10 @@ WSS_SINGLE("3D Control - Switch", 0, | |||
219 | CMI8330_RMUX3D, 5, 1, 1), | 231 | CMI8330_RMUX3D, 5, 1, 1), |
220 | WSS_SINGLE("PC Speaker Playback Volume", 0, | 232 | WSS_SINGLE("PC Speaker Playback Volume", 0, |
221 | CMI8330_OUTPUTVOL, 3, 3, 0), | 233 | CMI8330_OUTPUTVOL, 3, 3, 0), |
222 | WSS_SINGLE("FM Playback Switch", 0, | 234 | WSS_DOUBLE("FM Playback Switch", 0, |
223 | CMI8330_RECMUX, 3, 1, 1), | 235 | CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), |
236 | WSS_DOUBLE("FM Playback Volume", 0, | ||
237 | CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1), | ||
224 | WSS_SINGLE(SNDRV_CTL_NAME_IEC958("Input ", CAPTURE, SWITCH), 0, | 238 | WSS_SINGLE(SNDRV_CTL_NAME_IEC958("Input ", CAPTURE, SWITCH), 0, |
225 | CMI8330_RMUX3D, 7, 1, 1), | 239 | CMI8330_RMUX3D, 7, 1, 1), |
226 | WSS_SINGLE(SNDRV_CTL_NAME_IEC958("Input ", PLAYBACK, SWITCH), 0, | 240 | WSS_SINGLE(SNDRV_CTL_NAME_IEC958("Input ", PLAYBACK, SWITCH), 0, |
@@ -323,16 +337,21 @@ static int __devinit snd_cmi8330_pnp(int dev, struct snd_cmi8330 *acard, | |||
323 | if (acard->play == NULL) | 337 | if (acard->play == NULL) |
324 | return -EBUSY; | 338 | return -EBUSY; |
325 | 339 | ||
340 | acard->mpu = pnp_request_card_device(card, id->devs[2].id, NULL); | ||
341 | if (acard->play == NULL) | ||
342 | return -EBUSY; | ||
343 | |||
326 | pdev = acard->cap; | 344 | pdev = acard->cap; |
327 | 345 | ||
328 | err = pnp_activate_dev(pdev); | 346 | err = pnp_activate_dev(pdev); |
329 | if (err < 0) { | 347 | if (err < 0) { |
330 | snd_printk(KERN_ERR "CMI8330/C3D (AD1848) PnP configure failure\n"); | 348 | snd_printk(KERN_ERR "CMI8330/C3D PnP configure failure\n"); |
331 | return -EBUSY; | 349 | return -EBUSY; |
332 | } | 350 | } |
333 | wssport[dev] = pnp_port_start(pdev, 0); | 351 | wssport[dev] = pnp_port_start(pdev, 0); |
334 | wssdma[dev] = pnp_dma(pdev, 0); | 352 | wssdma[dev] = pnp_dma(pdev, 0); |
335 | wssirq[dev] = pnp_irq(pdev, 0); | 353 | wssirq[dev] = pnp_irq(pdev, 0); |
354 | fmport[dev] = pnp_port_start(pdev, 1); | ||
336 | 355 | ||
337 | /* allocate SB16 resources */ | 356 | /* allocate SB16 resources */ |
338 | pdev = acard->play; | 357 | pdev = acard->play; |
@@ -347,6 +366,17 @@ static int __devinit snd_cmi8330_pnp(int dev, struct snd_cmi8330 *acard, | |||
347 | sbdma16[dev] = pnp_dma(pdev, 1); | 366 | sbdma16[dev] = pnp_dma(pdev, 1); |
348 | sbirq[dev] = pnp_irq(pdev, 0); | 367 | sbirq[dev] = pnp_irq(pdev, 0); |
349 | 368 | ||
369 | /* allocate MPU-401 resources */ | ||
370 | pdev = acard->mpu; | ||
371 | |||
372 | err = pnp_activate_dev(pdev); | ||
373 | if (err < 0) { | ||
374 | snd_printk(KERN_ERR | ||
375 | "CMI8330/C3D (MPU-401) PnP configure failure\n"); | ||
376 | return -EBUSY; | ||
377 | } | ||
378 | mpuport[dev] = pnp_port_start(pdev, 0); | ||
379 | mpuirq[dev] = pnp_irq(pdev, 0); | ||
350 | return 0; | 380 | return 0; |
351 | } | 381 | } |
352 | #endif | 382 | #endif |
@@ -467,26 +497,29 @@ static int snd_cmi8330_resume(struct snd_card *card) | |||
467 | 497 | ||
468 | #define PFX "cmi8330: " | 498 | #define PFX "cmi8330: " |
469 | 499 | ||
470 | static struct snd_card *snd_cmi8330_card_new(int dev) | 500 | static int snd_cmi8330_card_new(int dev, struct snd_card **cardp) |
471 | { | 501 | { |
472 | struct snd_card *card; | 502 | struct snd_card *card; |
473 | struct snd_cmi8330 *acard; | 503 | struct snd_cmi8330 *acard; |
504 | int err; | ||
474 | 505 | ||
475 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, | 506 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, |
476 | sizeof(struct snd_cmi8330)); | 507 | sizeof(struct snd_cmi8330), &card); |
477 | if (card == NULL) { | 508 | if (err < 0) { |
478 | snd_printk(KERN_ERR PFX "could not get a new card\n"); | 509 | snd_printk(KERN_ERR PFX "could not get a new card\n"); |
479 | return NULL; | 510 | return err; |
480 | } | 511 | } |
481 | acard = card->private_data; | 512 | acard = card->private_data; |
482 | acard->card = card; | 513 | acard->card = card; |
483 | return card; | 514 | *cardp = card; |
515 | return 0; | ||
484 | } | 516 | } |
485 | 517 | ||
486 | static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev) | 518 | static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev) |
487 | { | 519 | { |
488 | struct snd_cmi8330 *acard; | 520 | struct snd_cmi8330 *acard; |
489 | int i, err; | 521 | int i, err; |
522 | struct snd_opl3 *opl3; | ||
490 | 523 | ||
491 | acard = card->private_data; | 524 | acard = card->private_data; |
492 | err = snd_wss_create(card, wssport[dev] + 4, -1, | 525 | err = snd_wss_create(card, wssport[dev] + 4, -1, |
@@ -494,11 +527,11 @@ static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev) | |||
494 | wssdma[dev], -1, | 527 | wssdma[dev], -1, |
495 | WSS_HW_DETECT, 0, &acard->wss); | 528 | WSS_HW_DETECT, 0, &acard->wss); |
496 | if (err < 0) { | 529 | if (err < 0) { |
497 | snd_printk(KERN_ERR PFX "(AD1848) device busy??\n"); | 530 | snd_printk(KERN_ERR PFX "(CMI8330) device busy??\n"); |
498 | return err; | 531 | return err; |
499 | } | 532 | } |
500 | if (acard->wss->hardware != WSS_HW_CMI8330) { | 533 | if (acard->wss->hardware != WSS_HW_CMI8330) { |
501 | snd_printk(KERN_ERR PFX "(AD1848) not found during probe\n"); | 534 | snd_printk(KERN_ERR PFX "(CMI8330) not found during probe\n"); |
502 | return -ENODEV; | 535 | return -ENODEV; |
503 | } | 536 | } |
504 | 537 | ||
@@ -530,6 +563,27 @@ static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev) | |||
530 | snd_printk(KERN_ERR PFX "failed to create pcms\n"); | 563 | snd_printk(KERN_ERR PFX "failed to create pcms\n"); |
531 | return err; | 564 | return err; |
532 | } | 565 | } |
566 | if (fmport[dev] != SNDRV_AUTO_PORT) { | ||
567 | if (snd_opl3_create(card, | ||
568 | fmport[dev], fmport[dev] + 2, | ||
569 | OPL3_HW_AUTO, 0, &opl3) < 0) { | ||
570 | snd_printk(KERN_ERR PFX | ||
571 | "no OPL device at 0x%lx-0x%lx ?\n", | ||
572 | fmport[dev], fmport[dev] + 2); | ||
573 | } else { | ||
574 | err = snd_opl3_hwdep_new(opl3, 0, 1, NULL); | ||
575 | if (err < 0) | ||
576 | return err; | ||
577 | } | ||
578 | } | ||
579 | |||
580 | if (mpuport[dev] != SNDRV_AUTO_PORT) { | ||
581 | if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, | ||
582 | mpuport[dev], 0, mpuirq[dev], | ||
583 | IRQF_DISABLED, NULL) < 0) | ||
584 | printk(KERN_ERR PFX "no MPU-401 device at 0x%lx.\n", | ||
585 | mpuport[dev]); | ||
586 | } | ||
533 | 587 | ||
534 | strcpy(card->driver, "CMI8330/C3D"); | 588 | strcpy(card->driver, "CMI8330/C3D"); |
535 | strcpy(card->shortname, "C-Media CMI8330/C3D"); | 589 | strcpy(card->shortname, "C-Media CMI8330/C3D"); |
@@ -564,9 +618,9 @@ static int __devinit snd_cmi8330_isa_probe(struct device *pdev, | |||
564 | struct snd_card *card; | 618 | struct snd_card *card; |
565 | int err; | 619 | int err; |
566 | 620 | ||
567 | card = snd_cmi8330_card_new(dev); | 621 | err = snd_cmi8330_card_new(dev, &card); |
568 | if (! card) | 622 | if (err < 0) |
569 | return -ENOMEM; | 623 | return err; |
570 | snd_card_set_dev(card, pdev); | 624 | snd_card_set_dev(card, pdev); |
571 | if ((err = snd_cmi8330_probe(card, dev)) < 0) { | 625 | if ((err = snd_cmi8330_probe(card, dev)) < 0) { |
572 | snd_card_free(card); | 626 | snd_card_free(card); |
@@ -628,9 +682,9 @@ static int __devinit snd_cmi8330_pnp_detect(struct pnp_card_link *pcard, | |||
628 | if (dev >= SNDRV_CARDS) | 682 | if (dev >= SNDRV_CARDS) |
629 | return -ENODEV; | 683 | return -ENODEV; |
630 | 684 | ||
631 | card = snd_cmi8330_card_new(dev); | 685 | res = snd_cmi8330_card_new(dev, &card); |
632 | if (! card) | 686 | if (res < 0) |
633 | return -ENOMEM; | 687 | return res; |
634 | if ((res = snd_cmi8330_pnp(dev, card->private_data, pcard, pid)) < 0) { | 688 | if ((res = snd_cmi8330_pnp(dev, card->private_data, pcard, pid)) < 0) { |
635 | snd_printk(KERN_ERR PFX "PnP detection failed\n"); | 689 | snd_printk(KERN_ERR PFX "PnP detection failed\n"); |
636 | snd_card_free(card); | 690 | snd_card_free(card); |
diff --git a/sound/isa/cs423x/Makefile b/sound/isa/cs423x/Makefile index 5870ca21ab59..6d397e8d54ac 100644 --- a/sound/isa/cs423x/Makefile +++ b/sound/isa/cs423x/Makefile | |||
@@ -3,13 +3,11 @@ | |||
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-cs4236-lib-objs := cs4236_lib.o | ||
7 | snd-cs4231-objs := cs4231.o | 6 | snd-cs4231-objs := cs4231.o |
8 | snd-cs4232-objs := cs4232.o | 7 | snd-cs4236-objs := cs4236.o cs4236_lib.o |
9 | snd-cs4236-objs := cs4236.o | ||
10 | 8 | ||
11 | # Toplevel Module Dependency | 9 | # Toplevel Module Dependency |
12 | obj-$(CONFIG_SND_CS4231) += snd-cs4231.o | 10 | obj-$(CONFIG_SND_CS4231) += snd-cs4231.o |
13 | obj-$(CONFIG_SND_CS4232) += snd-cs4232.o | 11 | obj-$(CONFIG_SND_CS4236) += snd-cs4236.o |
14 | obj-$(CONFIG_SND_CS4236) += snd-cs4236.o snd-cs4236-lib.o | 12 | |
15 | 13 | ||
diff --git a/sound/isa/cs423x/cs4231.c b/sound/isa/cs423x/cs4231.c index f019d449e2d6..cb9153e75b82 100644 --- a/sound/isa/cs423x/cs4231.c +++ b/sound/isa/cs423x/cs4231.c | |||
@@ -95,9 +95,9 @@ static int __devinit snd_cs4231_probe(struct device *dev, unsigned int n) | |||
95 | struct snd_pcm *pcm; | 95 | struct snd_pcm *pcm; |
96 | int error; | 96 | int error; |
97 | 97 | ||
98 | card = snd_card_new(index[n], id[n], THIS_MODULE, 0); | 98 | error = snd_card_create(index[n], id[n], THIS_MODULE, 0, &card); |
99 | if (!card) | 99 | if (error < 0) |
100 | return -EINVAL; | 100 | return error; |
101 | 101 | ||
102 | error = snd_wss_create(card, port[n], -1, irq[n], dma1[n], dma2[n], | 102 | error = snd_wss_create(card, port[n], -1, irq[n], dma1[n], dma2[n], |
103 | WSS_HW_DETECT, 0, &chip); | 103 | WSS_HW_DETECT, 0, &chip); |
diff --git a/sound/isa/cs423x/cs4232.c b/sound/isa/cs423x/cs4232.c deleted file mode 100644 index 9fad2e6c0c2c..000000000000 --- a/sound/isa/cs423x/cs4232.c +++ /dev/null | |||
@@ -1,2 +0,0 @@ | |||
1 | #define CS4232 | ||
2 | #include "cs4236.c" | ||
diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c index 019c9401663e..a076a6ce8071 100644 --- a/sound/isa/cs423x/cs4236.c +++ b/sound/isa/cs423x/cs4236.c | |||
@@ -33,17 +33,14 @@ | |||
33 | 33 | ||
34 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); | 34 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
35 | MODULE_LICENSE("GPL"); | 35 | MODULE_LICENSE("GPL"); |
36 | #ifdef CS4232 | 36 | MODULE_DESCRIPTION("Cirrus Logic CS4232-9"); |
37 | MODULE_DESCRIPTION("Cirrus Logic CS4232"); | ||
38 | MODULE_SUPPORTED_DEVICE("{{Turtle Beach,TBS-2000}," | 37 | MODULE_SUPPORTED_DEVICE("{{Turtle Beach,TBS-2000}," |
39 | "{Turtle Beach,Tropez Plus}," | 38 | "{Turtle Beach,Tropez Plus}," |
40 | "{SIC CrystalWave 32}," | 39 | "{SIC CrystalWave 32}," |
41 | "{Hewlett Packard,Omnibook 5500}," | 40 | "{Hewlett Packard,Omnibook 5500}," |
42 | "{TerraTec,Maestro 32/96}," | 41 | "{TerraTec,Maestro 32/96}," |
43 | "{Philips,PCA70PS}}"); | 42 | "{Philips,PCA70PS}}," |
44 | #else | 43 | "{{Crystal Semiconductors,CS4235}," |
45 | MODULE_DESCRIPTION("Cirrus Logic CS4235-9"); | ||
46 | MODULE_SUPPORTED_DEVICE("{{Crystal Semiconductors,CS4235}," | ||
47 | "{Crystal Semiconductors,CS4236}," | 44 | "{Crystal Semiconductors,CS4236}," |
48 | "{Crystal Semiconductors,CS4237}," | 45 | "{Crystal Semiconductors,CS4237}," |
49 | "{Crystal Semiconductors,CS4238}," | 46 | "{Crystal Semiconductors,CS4238}," |
@@ -70,15 +67,11 @@ MODULE_SUPPORTED_DEVICE("{{Crystal Semiconductors,CS4235}," | |||
70 | "{Typhoon Soundsystem,CS4236B}," | 67 | "{Typhoon Soundsystem,CS4236B}," |
71 | "{Turtle Beach,Malibu}," | 68 | "{Turtle Beach,Malibu}," |
72 | "{Unknown,Digital PC 5000 Onboard}}"); | 69 | "{Unknown,Digital PC 5000 Onboard}}"); |
73 | #endif | ||
74 | 70 | ||
75 | #ifdef CS4232 | 71 | MODULE_ALIAS("snd_cs4232"); |
76 | #define IDENT "CS4232" | 72 | |
77 | #define DEV_NAME "cs4232" | 73 | #define IDENT "CS4232+" |
78 | #else | 74 | #define DEV_NAME "cs4232+" |
79 | #define IDENT "CS4236+" | ||
80 | #define DEV_NAME "cs4236" | ||
81 | #endif | ||
82 | 75 | ||
83 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ | 76 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ |
84 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ | 77 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ |
@@ -128,9 +121,7 @@ MODULE_PARM_DESC(dma2, "DMA2 # for " IDENT " driver."); | |||
128 | #ifdef CONFIG_PNP | 121 | #ifdef CONFIG_PNP |
129 | static int isa_registered; | 122 | static int isa_registered; |
130 | static int pnpc_registered; | 123 | static int pnpc_registered; |
131 | #ifdef CS4232 | ||
132 | static int pnp_registered; | 124 | static int pnp_registered; |
133 | #endif | ||
134 | #endif /* CONFIG_PNP */ | 125 | #endif /* CONFIG_PNP */ |
135 | 126 | ||
136 | struct snd_card_cs4236 { | 127 | struct snd_card_cs4236 { |
@@ -145,11 +136,10 @@ struct snd_card_cs4236 { | |||
145 | 136 | ||
146 | #ifdef CONFIG_PNP | 137 | #ifdef CONFIG_PNP |
147 | 138 | ||
148 | #ifdef CS4232 | ||
149 | /* | 139 | /* |
150 | * PNP BIOS | 140 | * PNP BIOS |
151 | */ | 141 | */ |
152 | static const struct pnp_device_id snd_cs4232_pnpbiosids[] = { | 142 | static const struct pnp_device_id snd_cs423x_pnpbiosids[] = { |
153 | { .id = "CSC0100" }, | 143 | { .id = "CSC0100" }, |
154 | { .id = "CSC0000" }, | 144 | { .id = "CSC0000" }, |
155 | /* Guillemot Turtlebeach something appears to be cs4232 compatible | 145 | /* Guillemot Turtlebeach something appears to be cs4232 compatible |
@@ -157,10 +147,8 @@ static const struct pnp_device_id snd_cs4232_pnpbiosids[] = { | |||
157 | { .id = "GIM0100" }, | 147 | { .id = "GIM0100" }, |
158 | { .id = "" } | 148 | { .id = "" } |
159 | }; | 149 | }; |
160 | MODULE_DEVICE_TABLE(pnp, snd_cs4232_pnpbiosids); | 150 | MODULE_DEVICE_TABLE(pnp, snd_cs423x_pnpbiosids); |
161 | #endif /* CS4232 */ | ||
162 | 151 | ||
163 | #ifdef CS4232 | ||
164 | #define CS423X_ISAPNP_DRIVER "cs4232_isapnp" | 152 | #define CS423X_ISAPNP_DRIVER "cs4232_isapnp" |
165 | static struct pnp_card_device_id snd_cs423x_pnpids[] = { | 153 | static struct pnp_card_device_id snd_cs423x_pnpids[] = { |
166 | /* Philips PCA70PS */ | 154 | /* Philips PCA70PS */ |
@@ -179,12 +167,6 @@ static struct pnp_card_device_id snd_cs423x_pnpids[] = { | |||
179 | { .id = "CSCf032", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, | 167 | { .id = "CSCf032", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, |
180 | /* Netfinity 3000 on-board soundcard */ | 168 | /* Netfinity 3000 on-board soundcard */ |
181 | { .id = "CSCe825", .devs = { { "CSC0100" }, { "CSC0110" }, { "CSC010f" } } }, | 169 | { .id = "CSCe825", .devs = { { "CSC0100" }, { "CSC0110" }, { "CSC010f" } } }, |
182 | /* --- */ | ||
183 | { .id = "" } /* end */ | ||
184 | }; | ||
185 | #else /* CS4236 */ | ||
186 | #define CS423X_ISAPNP_DRIVER "cs4236_isapnp" | ||
187 | static struct pnp_card_device_id snd_cs423x_pnpids[] = { | ||
188 | /* Intel Marlin Spike Motherboard - CS4235 */ | 170 | /* Intel Marlin Spike Motherboard - CS4235 */ |
189 | { .id = "CSC0225", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, | 171 | { .id = "CSC0225", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, |
190 | /* Intel Marlin Spike Motherboard (#2) - CS4235 */ | 172 | /* Intel Marlin Spike Motherboard (#2) - CS4235 */ |
@@ -266,7 +248,6 @@ static struct pnp_card_device_id snd_cs423x_pnpids[] = { | |||
266 | /* --- */ | 248 | /* --- */ |
267 | { .id = "" } /* end */ | 249 | { .id = "" } /* end */ |
268 | }; | 250 | }; |
269 | #endif | ||
270 | 251 | ||
271 | MODULE_DEVICE_TABLE(pnp_card, snd_cs423x_pnpids); | 252 | MODULE_DEVICE_TABLE(pnp_card, snd_cs423x_pnpids); |
272 | 253 | ||
@@ -323,17 +304,19 @@ static int __devinit snd_cs423x_pnp_init_mpu(int dev, struct pnp_dev *pdev) | |||
323 | return 0; | 304 | return 0; |
324 | } | 305 | } |
325 | 306 | ||
326 | #ifdef CS4232 | 307 | static int __devinit snd_card_cs423x_pnp(int dev, struct snd_card_cs4236 *acard, |
327 | static int __devinit snd_card_cs4232_pnp(int dev, struct snd_card_cs4236 *acard, | 308 | struct pnp_dev *pdev, |
328 | struct pnp_dev *pdev) | 309 | struct pnp_dev *cdev) |
329 | { | 310 | { |
330 | acard->wss = pdev; | 311 | acard->wss = pdev; |
331 | if (snd_cs423x_pnp_init_wss(dev, acard->wss) < 0) | 312 | if (snd_cs423x_pnp_init_wss(dev, acard->wss) < 0) |
332 | return -EBUSY; | 313 | return -EBUSY; |
333 | cport[dev] = -1; | 314 | if (cdev) |
315 | cport[dev] = pnp_port_start(cdev, 0); | ||
316 | else | ||
317 | cport[dev] = -1; | ||
334 | return 0; | 318 | return 0; |
335 | } | 319 | } |
336 | #endif | ||
337 | 320 | ||
338 | static int __devinit snd_card_cs423x_pnpc(int dev, struct snd_card_cs4236 *acard, | 321 | static int __devinit snd_card_cs423x_pnpc(int dev, struct snd_card_cs4236 *acard, |
339 | struct pnp_card_link *card, | 322 | struct pnp_card_link *card, |
@@ -382,16 +365,18 @@ static void snd_card_cs4236_free(struct snd_card *card) | |||
382 | release_and_free_resource(acard->res_sb_port); | 365 | release_and_free_resource(acard->res_sb_port); |
383 | } | 366 | } |
384 | 367 | ||
385 | static struct snd_card *snd_cs423x_card_new(int dev) | 368 | static int snd_cs423x_card_new(int dev, struct snd_card **cardp) |
386 | { | 369 | { |
387 | struct snd_card *card; | 370 | struct snd_card *card; |
371 | int err; | ||
388 | 372 | ||
389 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, | 373 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, |
390 | sizeof(struct snd_card_cs4236)); | 374 | sizeof(struct snd_card_cs4236), &card); |
391 | if (card == NULL) | 375 | if (err < 0) |
392 | return NULL; | 376 | return err; |
393 | card->private_free = snd_card_cs4236_free; | 377 | card->private_free = snd_card_cs4236_free; |
394 | return card; | 378 | *cardp = card; |
379 | return 0; | ||
395 | } | 380 | } |
396 | 381 | ||
397 | static int __devinit snd_cs423x_probe(struct snd_card *card, int dev) | 382 | static int __devinit snd_cs423x_probe(struct snd_card *card, int dev) |
@@ -409,40 +394,39 @@ static int __devinit snd_cs423x_probe(struct snd_card *card, int dev) | |||
409 | return -EBUSY; | 394 | return -EBUSY; |
410 | } | 395 | } |
411 | 396 | ||
412 | #ifdef CS4232 | ||
413 | err = snd_wss_create(card, port[dev], cport[dev], | 397 | err = snd_wss_create(card, port[dev], cport[dev], |
414 | irq[dev], | 398 | irq[dev], |
415 | dma1[dev], dma2[dev], | 399 | dma1[dev], dma2[dev], |
416 | WSS_HW_DETECT, 0, &chip); | 400 | WSS_HW_DETECT3, 0, &chip); |
417 | if (err < 0) | ||
418 | return err; | ||
419 | acard->chip = chip; | ||
420 | |||
421 | err = snd_wss_pcm(chip, 0, &pcm); | ||
422 | if (err < 0) | ||
423 | return err; | ||
424 | |||
425 | err = snd_wss_mixer(chip); | ||
426 | if (err < 0) | 401 | if (err < 0) |
427 | return err; | 402 | return err; |
428 | 403 | if (chip->hardware & WSS_HW_CS4236B_MASK) { | |
429 | #else /* CS4236 */ | 404 | snd_wss_free(chip); |
430 | err = snd_cs4236_create(card, | 405 | err = snd_cs4236_create(card, |
431 | port[dev], cport[dev], | 406 | port[dev], cport[dev], |
432 | irq[dev], dma1[dev], dma2[dev], | 407 | irq[dev], dma1[dev], dma2[dev], |
433 | WSS_HW_DETECT, 0, &chip); | 408 | WSS_HW_DETECT, 0, &chip); |
434 | if (err < 0) | 409 | if (err < 0) |
435 | return err; | 410 | return err; |
436 | acard->chip = chip; | 411 | acard->chip = chip; |
437 | 412 | ||
438 | err = snd_cs4236_pcm(chip, 0, &pcm); | 413 | err = snd_cs4236_pcm(chip, 0, &pcm); |
439 | if (err < 0) | 414 | if (err < 0) |
440 | return err; | 415 | return err; |
441 | 416 | ||
442 | err = snd_cs4236_mixer(chip); | 417 | err = snd_cs4236_mixer(chip); |
443 | if (err < 0) | 418 | if (err < 0) |
444 | return err; | 419 | return err; |
445 | #endif | 420 | } else { |
421 | acard->chip = chip; | ||
422 | err = snd_wss_pcm(chip, 0, &pcm); | ||
423 | if (err < 0) | ||
424 | return err; | ||
425 | |||
426 | err = snd_wss_mixer(chip); | ||
427 | if (err < 0) | ||
428 | return err; | ||
429 | } | ||
446 | strcpy(card->driver, pcm->name); | 430 | strcpy(card->driver, pcm->name); |
447 | strcpy(card->shortname, pcm->name); | 431 | strcpy(card->shortname, pcm->name); |
448 | sprintf(card->longname, "%s at 0x%lx, irq %i, dma %i", | 432 | sprintf(card->longname, "%s at 0x%lx, irq %i, dma %i", |
@@ -512,9 +496,9 @@ static int __devinit snd_cs423x_isa_probe(struct device *pdev, | |||
512 | struct snd_card *card; | 496 | struct snd_card *card; |
513 | int err; | 497 | int err; |
514 | 498 | ||
515 | card = snd_cs423x_card_new(dev); | 499 | err = snd_cs423x_card_new(dev, &card); |
516 | if (! card) | 500 | if (err < 0) |
517 | return -ENOMEM; | 501 | return err; |
518 | snd_card_set_dev(card, pdev); | 502 | snd_card_set_dev(card, pdev); |
519 | if ((err = snd_cs423x_probe(card, dev)) < 0) { | 503 | if ((err = snd_cs423x_probe(card, dev)) < 0) { |
520 | snd_card_free(card); | 504 | snd_card_free(card); |
@@ -577,13 +561,14 @@ static struct isa_driver cs423x_isa_driver = { | |||
577 | 561 | ||
578 | 562 | ||
579 | #ifdef CONFIG_PNP | 563 | #ifdef CONFIG_PNP |
580 | #ifdef CS4232 | 564 | static int __devinit snd_cs423x_pnpbios_detect(struct pnp_dev *pdev, |
581 | static int __devinit snd_cs4232_pnpbios_detect(struct pnp_dev *pdev, | ||
582 | const struct pnp_device_id *id) | 565 | const struct pnp_device_id *id) |
583 | { | 566 | { |
584 | static int dev; | 567 | static int dev; |
585 | int err; | 568 | int err; |
586 | struct snd_card *card; | 569 | struct snd_card *card; |
570 | struct pnp_dev *cdev; | ||
571 | char cid[PNP_ID_LEN]; | ||
587 | 572 | ||
588 | if (pnp_device_is_isapnp(pdev)) | 573 | if (pnp_device_is_isapnp(pdev)) |
589 | return -ENOENT; /* we have another procedure - card */ | 574 | return -ENOENT; /* we have another procedure - card */ |
@@ -594,10 +579,19 @@ static int __devinit snd_cs4232_pnpbios_detect(struct pnp_dev *pdev, | |||
594 | if (dev >= SNDRV_CARDS) | 579 | if (dev >= SNDRV_CARDS) |
595 | return -ENODEV; | 580 | return -ENODEV; |
596 | 581 | ||
597 | card = snd_cs423x_card_new(dev); | 582 | /* prepare second id */ |
598 | if (! card) | 583 | strcpy(cid, pdev->id[0].id); |
599 | return -ENOMEM; | 584 | cid[5] = '1'; |
600 | if ((err = snd_card_cs4232_pnp(dev, card->private_data, pdev)) < 0) { | 585 | cdev = NULL; |
586 | list_for_each_entry(cdev, &(pdev->protocol->devices), protocol_list) { | ||
587 | if (!strcmp(cdev->id[0].id, cid)) | ||
588 | break; | ||
589 | } | ||
590 | err = snd_cs423x_card_new(dev, &card); | ||
591 | if (err < 0) | ||
592 | return err; | ||
593 | err = snd_card_cs423x_pnp(dev, card->private_data, pdev, cdev); | ||
594 | if (err < 0) { | ||
601 | printk(KERN_ERR "PnP BIOS detection failed for " IDENT "\n"); | 595 | printk(KERN_ERR "PnP BIOS detection failed for " IDENT "\n"); |
602 | snd_card_free(card); | 596 | snd_card_free(card); |
603 | return err; | 597 | return err; |
@@ -612,35 +606,34 @@ static int __devinit snd_cs4232_pnpbios_detect(struct pnp_dev *pdev, | |||
612 | return 0; | 606 | return 0; |
613 | } | 607 | } |
614 | 608 | ||
615 | static void __devexit snd_cs4232_pnp_remove(struct pnp_dev * pdev) | 609 | static void __devexit snd_cs423x_pnp_remove(struct pnp_dev *pdev) |
616 | { | 610 | { |
617 | snd_card_free(pnp_get_drvdata(pdev)); | 611 | snd_card_free(pnp_get_drvdata(pdev)); |
618 | pnp_set_drvdata(pdev, NULL); | 612 | pnp_set_drvdata(pdev, NULL); |
619 | } | 613 | } |
620 | 614 | ||
621 | #ifdef CONFIG_PM | 615 | #ifdef CONFIG_PM |
622 | static int snd_cs4232_pnp_suspend(struct pnp_dev *pdev, pm_message_t state) | 616 | static int snd_cs423x_pnp_suspend(struct pnp_dev *pdev, pm_message_t state) |
623 | { | 617 | { |
624 | return snd_cs423x_suspend(pnp_get_drvdata(pdev)); | 618 | return snd_cs423x_suspend(pnp_get_drvdata(pdev)); |
625 | } | 619 | } |
626 | 620 | ||
627 | static int snd_cs4232_pnp_resume(struct pnp_dev *pdev) | 621 | static int snd_cs423x_pnp_resume(struct pnp_dev *pdev) |
628 | { | 622 | { |
629 | return snd_cs423x_resume(pnp_get_drvdata(pdev)); | 623 | return snd_cs423x_resume(pnp_get_drvdata(pdev)); |
630 | } | 624 | } |
631 | #endif | 625 | #endif |
632 | 626 | ||
633 | static struct pnp_driver cs4232_pnp_driver = { | 627 | static struct pnp_driver cs423x_pnp_driver = { |
634 | .name = "cs4232-pnpbios", | 628 | .name = "cs423x-pnpbios", |
635 | .id_table = snd_cs4232_pnpbiosids, | 629 | .id_table = snd_cs423x_pnpbiosids, |
636 | .probe = snd_cs4232_pnpbios_detect, | 630 | .probe = snd_cs423x_pnpbios_detect, |
637 | .remove = __devexit_p(snd_cs4232_pnp_remove), | 631 | .remove = __devexit_p(snd_cs423x_pnp_remove), |
638 | #ifdef CONFIG_PM | 632 | #ifdef CONFIG_PM |
639 | .suspend = snd_cs4232_pnp_suspend, | 633 | .suspend = snd_cs423x_pnp_suspend, |
640 | .resume = snd_cs4232_pnp_resume, | 634 | .resume = snd_cs423x_pnp_resume, |
641 | #endif | 635 | #endif |
642 | }; | 636 | }; |
643 | #endif /* CS4232 */ | ||
644 | 637 | ||
645 | static int __devinit snd_cs423x_pnpc_detect(struct pnp_card_link *pcard, | 638 | static int __devinit snd_cs423x_pnpc_detect(struct pnp_card_link *pcard, |
646 | const struct pnp_card_device_id *pid) | 639 | const struct pnp_card_device_id *pid) |
@@ -656,9 +649,9 @@ static int __devinit snd_cs423x_pnpc_detect(struct pnp_card_link *pcard, | |||
656 | if (dev >= SNDRV_CARDS) | 649 | if (dev >= SNDRV_CARDS) |
657 | return -ENODEV; | 650 | return -ENODEV; |
658 | 651 | ||
659 | card = snd_cs423x_card_new(dev); | 652 | res = snd_cs423x_card_new(dev, &card); |
660 | if (! card) | 653 | if (res < 0) |
661 | return -ENOMEM; | 654 | return res; |
662 | if ((res = snd_card_cs423x_pnpc(dev, card->private_data, pcard, pid)) < 0) { | 655 | if ((res = snd_card_cs423x_pnpc(dev, card->private_data, pcard, pid)) < 0) { |
663 | printk(KERN_ERR "isapnp detection failed and probing for " IDENT | 656 | printk(KERN_ERR "isapnp detection failed and probing for " IDENT |
664 | " is not supported\n"); | 657 | " is not supported\n"); |
@@ -714,18 +707,14 @@ static int __init alsa_card_cs423x_init(void) | |||
714 | #ifdef CONFIG_PNP | 707 | #ifdef CONFIG_PNP |
715 | if (!err) | 708 | if (!err) |
716 | isa_registered = 1; | 709 | isa_registered = 1; |
717 | #ifdef CS4232 | 710 | err = pnp_register_driver(&cs423x_pnp_driver); |
718 | err = pnp_register_driver(&cs4232_pnp_driver); | ||
719 | if (!err) | 711 | if (!err) |
720 | pnp_registered = 1; | 712 | pnp_registered = 1; |
721 | #endif | ||
722 | err = pnp_register_card_driver(&cs423x_pnpc_driver); | 713 | err = pnp_register_card_driver(&cs423x_pnpc_driver); |
723 | if (!err) | 714 | if (!err) |
724 | pnpc_registered = 1; | 715 | pnpc_registered = 1; |
725 | #ifdef CS4232 | ||
726 | if (pnp_registered) | 716 | if (pnp_registered) |
727 | err = 0; | 717 | err = 0; |
728 | #endif | ||
729 | if (isa_registered) | 718 | if (isa_registered) |
730 | err = 0; | 719 | err = 0; |
731 | #endif | 720 | #endif |
@@ -737,10 +726,8 @@ static void __exit alsa_card_cs423x_exit(void) | |||
737 | #ifdef CONFIG_PNP | 726 | #ifdef CONFIG_PNP |
738 | if (pnpc_registered) | 727 | if (pnpc_registered) |
739 | pnp_unregister_card_driver(&cs423x_pnpc_driver); | 728 | pnp_unregister_card_driver(&cs423x_pnpc_driver); |
740 | #ifdef CS4232 | ||
741 | if (pnp_registered) | 729 | if (pnp_registered) |
742 | pnp_unregister_driver(&cs4232_pnp_driver); | 730 | pnp_unregister_driver(&cs423x_pnp_driver); |
743 | #endif | ||
744 | if (isa_registered) | 731 | if (isa_registered) |
745 | #endif | 732 | #endif |
746 | isa_unregister_driver(&cs423x_isa_driver); | 733 | isa_unregister_driver(&cs423x_isa_driver); |
diff --git a/sound/isa/cs423x/cs4236_lib.c b/sound/isa/cs423x/cs4236_lib.c index 6a85fdc53b60..38835f31298b 100644 --- a/sound/isa/cs423x/cs4236_lib.c +++ b/sound/isa/cs423x/cs4236_lib.c | |||
@@ -88,10 +88,6 @@ | |||
88 | #include <sound/wss.h> | 88 | #include <sound/wss.h> |
89 | #include <sound/asoundef.h> | 89 | #include <sound/asoundef.h> |
90 | 90 | ||
91 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); | ||
92 | MODULE_DESCRIPTION("Routines for control of CS4235/4236B/4237B/4238B/4239 chips"); | ||
93 | MODULE_LICENSE("GPL"); | ||
94 | |||
95 | /* | 91 | /* |
96 | * | 92 | * |
97 | */ | 93 | */ |
@@ -286,7 +282,8 @@ int snd_cs4236_create(struct snd_card *card, | |||
286 | if (hardware == WSS_HW_DETECT) | 282 | if (hardware == WSS_HW_DETECT) |
287 | hardware = WSS_HW_DETECT3; | 283 | hardware = WSS_HW_DETECT3; |
288 | if (cport < 0x100) { | 284 | if (cport < 0x100) { |
289 | snd_printk("please, specify control port for CS4236+ chips\n"); | 285 | snd_printk(KERN_ERR "please, specify control port " |
286 | "for CS4236+ chips\n"); | ||
290 | return -ENODEV; | 287 | return -ENODEV; |
291 | } | 288 | } |
292 | err = snd_wss_create(card, port, cport, | 289 | err = snd_wss_create(card, port, cport, |
@@ -295,7 +292,8 @@ int snd_cs4236_create(struct snd_card *card, | |||
295 | return err; | 292 | return err; |
296 | 293 | ||
297 | if (!(chip->hardware & WSS_HW_CS4236B_MASK)) { | 294 | if (!(chip->hardware & WSS_HW_CS4236B_MASK)) { |
298 | snd_printk("CS4236+: MODE3 and extended registers not available, hardware=0x%x\n",chip->hardware); | 295 | snd_printk(KERN_ERR "CS4236+: MODE3 and extended registers " |
296 | "not available, hardware=0x%x\n", chip->hardware); | ||
299 | snd_device_free(card, chip); | 297 | snd_device_free(card, chip); |
300 | return -ENODEV; | 298 | return -ENODEV; |
301 | } | 299 | } |
@@ -303,16 +301,19 @@ int snd_cs4236_create(struct snd_card *card, | |||
303 | { | 301 | { |
304 | int idx; | 302 | int idx; |
305 | for (idx = 0; idx < 8; idx++) | 303 | for (idx = 0; idx < 8; idx++) |
306 | snd_printk("CD%i = 0x%x\n", idx, inb(chip->cport + idx)); | 304 | snd_printk(KERN_DEBUG "CD%i = 0x%x\n", |
305 | idx, inb(chip->cport + idx)); | ||
307 | for (idx = 0; idx < 9; idx++) | 306 | for (idx = 0; idx < 9; idx++) |
308 | snd_printk("C%i = 0x%x\n", idx, snd_cs4236_ctrl_in(chip, idx)); | 307 | snd_printk(KERN_DEBUG "C%i = 0x%x\n", |
308 | idx, snd_cs4236_ctrl_in(chip, idx)); | ||
309 | } | 309 | } |
310 | #endif | 310 | #endif |
311 | ver1 = snd_cs4236_ctrl_in(chip, 1); | 311 | ver1 = snd_cs4236_ctrl_in(chip, 1); |
312 | ver2 = snd_cs4236_ext_in(chip, CS4236_VERSION); | 312 | ver2 = snd_cs4236_ext_in(chip, CS4236_VERSION); |
313 | snd_printdd("CS4236: [0x%lx] C1 (version) = 0x%x, ext = 0x%x\n", cport, ver1, ver2); | 313 | snd_printdd("CS4236: [0x%lx] C1 (version) = 0x%x, ext = 0x%x\n", cport, ver1, ver2); |
314 | if (ver1 != ver2) { | 314 | if (ver1 != ver2) { |
315 | snd_printk("CS4236+ chip detected, but control port 0x%lx is not valid\n", cport); | 315 | snd_printk(KERN_ERR "CS4236+ chip detected, but " |
316 | "control port 0x%lx is not valid\n", cport); | ||
316 | snd_device_free(card, chip); | 317 | snd_device_free(card, chip); |
317 | return -ENODEV; | 318 | return -ENODEV; |
318 | } | 319 | } |
@@ -883,7 +884,8 @@ static int snd_cs4236_get_iec958_switch(struct snd_kcontrol *kcontrol, struct sn | |||
883 | spin_lock_irqsave(&chip->reg_lock, flags); | 884 | spin_lock_irqsave(&chip->reg_lock, flags); |
884 | ucontrol->value.integer.value[0] = chip->image[CS4231_ALT_FEATURE_1] & 0x02 ? 1 : 0; | 885 | ucontrol->value.integer.value[0] = chip->image[CS4231_ALT_FEATURE_1] & 0x02 ? 1 : 0; |
885 | #if 0 | 886 | #if 0 |
886 | printk("get valid: ALT = 0x%x, C3 = 0x%x, C4 = 0x%x, C5 = 0x%x, C6 = 0x%x, C8 = 0x%x\n", | 887 | printk(KERN_DEBUG "get valid: ALT = 0x%x, C3 = 0x%x, C4 = 0x%x, " |
888 | "C5 = 0x%x, C6 = 0x%x, C8 = 0x%x\n", | ||
887 | snd_wss_in(chip, CS4231_ALT_FEATURE_1), | 889 | snd_wss_in(chip, CS4231_ALT_FEATURE_1), |
888 | snd_cs4236_ctrl_in(chip, 3), | 890 | snd_cs4236_ctrl_in(chip, 3), |
889 | snd_cs4236_ctrl_in(chip, 4), | 891 | snd_cs4236_ctrl_in(chip, 4), |
@@ -920,7 +922,8 @@ static int snd_cs4236_put_iec958_switch(struct snd_kcontrol *kcontrol, struct sn | |||
920 | mutex_unlock(&chip->mce_mutex); | 922 | mutex_unlock(&chip->mce_mutex); |
921 | 923 | ||
922 | #if 0 | 924 | #if 0 |
923 | printk("set valid: ALT = 0x%x, C3 = 0x%x, C4 = 0x%x, C5 = 0x%x, C6 = 0x%x, C8 = 0x%x\n", | 925 | printk(KERN_DEBUG "set valid: ALT = 0x%x, C3 = 0x%x, C4 = 0x%x, " |
926 | "C5 = 0x%x, C6 = 0x%x, C8 = 0x%x\n", | ||
924 | snd_wss_in(chip, CS4231_ALT_FEATURE_1), | 927 | snd_wss_in(chip, CS4231_ALT_FEATURE_1), |
925 | snd_cs4236_ctrl_in(chip, 3), | 928 | snd_cs4236_ctrl_in(chip, 3), |
926 | snd_cs4236_ctrl_in(chip, 4), | 929 | snd_cs4236_ctrl_in(chip, 4), |
@@ -1015,23 +1018,3 @@ int snd_cs4236_mixer(struct snd_wss *chip) | |||
1015 | } | 1018 | } |
1016 | return 0; | 1019 | return 0; |
1017 | } | 1020 | } |
1018 | |||
1019 | EXPORT_SYMBOL(snd_cs4236_create); | ||
1020 | EXPORT_SYMBOL(snd_cs4236_pcm); | ||
1021 | EXPORT_SYMBOL(snd_cs4236_mixer); | ||
1022 | |||
1023 | /* | ||
1024 | * INIT part | ||
1025 | */ | ||
1026 | |||
1027 | static int __init alsa_cs4236_init(void) | ||
1028 | { | ||
1029 | return 0; | ||
1030 | } | ||
1031 | |||
1032 | static void __exit alsa_cs4236_exit(void) | ||
1033 | { | ||
1034 | } | ||
1035 | |||
1036 | module_init(alsa_cs4236_init) | ||
1037 | module_exit(alsa_cs4236_exit) | ||
diff --git a/sound/isa/dt019x.c b/sound/isa/dt019x.c index a0242c3b613e..80f5b1af9be8 100644 --- a/sound/isa/dt019x.c +++ b/sound/isa/dt019x.c | |||
@@ -150,9 +150,10 @@ static int __devinit snd_card_dt019x_probe(int dev, struct pnp_card_link *pcard, | |||
150 | struct snd_card_dt019x *acard; | 150 | struct snd_card_dt019x *acard; |
151 | struct snd_opl3 *opl3; | 151 | struct snd_opl3 *opl3; |
152 | 152 | ||
153 | if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE, | 153 | error = snd_card_create(index[dev], id[dev], THIS_MODULE, |
154 | sizeof(struct snd_card_dt019x))) == NULL) | 154 | sizeof(struct snd_card_dt019x), &card); |
155 | return -ENOMEM; | 155 | if (error < 0) |
156 | return error; | ||
156 | acard = card->private_data; | 157 | acard = card->private_data; |
157 | 158 | ||
158 | snd_card_set_dev(card, &pcard->card->dev); | 159 | snd_card_set_dev(card, &pcard->card->dev); |
diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c index b46377139cf8..442b081cafb7 100644 --- a/sound/isa/es1688/es1688.c +++ b/sound/isa/es1688/es1688.c | |||
@@ -49,6 +49,7 @@ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ | |||
49 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ | 49 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ |
50 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */ | 50 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */ |
51 | static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240,0x260 */ | 51 | static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240,0x260 */ |
52 | static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* Usually 0x388 */ | ||
52 | static long mpu_port[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -1}; | 53 | static long mpu_port[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -1}; |
53 | static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,10 */ | 54 | static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,10 */ |
54 | static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,10 */ | 55 | static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,10 */ |
@@ -65,6 +66,8 @@ MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver."); | |||
65 | module_param_array(mpu_port, long, NULL, 0444); | 66 | module_param_array(mpu_port, long, NULL, 0444); |
66 | MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " CRD_NAME " driver."); | 67 | MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " CRD_NAME " driver."); |
67 | module_param_array(irq, int, NULL, 0444); | 68 | module_param_array(irq, int, NULL, 0444); |
69 | module_param_array(fm_port, long, NULL, 0444); | ||
70 | MODULE_PARM_DESC(fm_port, "FM port # for ES1688 driver."); | ||
68 | MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver."); | 71 | MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver."); |
69 | module_param_array(mpu_irq, int, NULL, 0444); | 72 | module_param_array(mpu_irq, int, NULL, 0444); |
70 | MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " CRD_NAME " driver."); | 73 | MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " CRD_NAME " driver."); |
@@ -122,9 +125,9 @@ static int __devinit snd_es1688_probe(struct device *dev, unsigned int n) | |||
122 | struct snd_pcm *pcm; | 125 | struct snd_pcm *pcm; |
123 | int error; | 126 | int error; |
124 | 127 | ||
125 | card = snd_card_new(index[n], id[n], THIS_MODULE, 0); | 128 | error = snd_card_create(index[n], id[n], THIS_MODULE, 0, &card); |
126 | if (!card) | 129 | if (error < 0) |
127 | return -EINVAL; | 130 | return error; |
128 | 131 | ||
129 | error = snd_es1688_legacy_create(card, dev, n, &chip); | 132 | error = snd_es1688_legacy_create(card, dev, n, &chip); |
130 | if (error < 0) | 133 | if (error < 0) |
@@ -143,13 +146,19 @@ static int __devinit snd_es1688_probe(struct device *dev, unsigned int n) | |||
143 | sprintf(card->longname, "%s at 0x%lx, irq %i, dma %i", pcm->name, | 146 | sprintf(card->longname, "%s at 0x%lx, irq %i, dma %i", pcm->name, |
144 | chip->port, chip->irq, chip->dma8); | 147 | chip->port, chip->irq, chip->dma8); |
145 | 148 | ||
146 | if (snd_opl3_create(card, chip->port, chip->port + 2, | 149 | if (fm_port[n] == SNDRV_AUTO_PORT) |
147 | OPL3_HW_OPL3, 0, &opl3) < 0) | 150 | fm_port[n] = port[n]; /* share the same port */ |
148 | dev_warn(dev, "opl3 not detected at 0x%lx\n", chip->port); | 151 | |
149 | else { | 152 | if (fm_port[n] > 0) { |
150 | error = snd_opl3_hwdep_new(opl3, 0, 1, NULL); | 153 | if (snd_opl3_create(card, fm_port[n], fm_port[n] + 2, |
151 | if (error < 0) | 154 | OPL3_HW_OPL3, 0, &opl3) < 0) |
152 | goto out; | 155 | dev_warn(dev, |
156 | "opl3 not detected at 0x%lx\n", fm_port[n]); | ||
157 | else { | ||
158 | error = snd_opl3_hwdep_new(opl3, 0, 1, NULL); | ||
159 | if (error < 0) | ||
160 | goto out; | ||
161 | } | ||
153 | } | 162 | } |
154 | 163 | ||
155 | if (mpu_irq[n] >= 0 && mpu_irq[n] != SNDRV_AUTO_IRQ && | 164 | if (mpu_irq[n] >= 0 && mpu_irq[n] != SNDRV_AUTO_IRQ && |
diff --git a/sound/isa/es1688/es1688_lib.c b/sound/isa/es1688/es1688_lib.c index 4fbb508a817f..4c6e14f87f2d 100644 --- a/sound/isa/es1688/es1688_lib.c +++ b/sound/isa/es1688/es1688_lib.c | |||
@@ -45,7 +45,7 @@ static int snd_es1688_dsp_command(struct snd_es1688 *chip, unsigned char val) | |||
45 | return 1; | 45 | return 1; |
46 | } | 46 | } |
47 | #ifdef CONFIG_SND_DEBUG | 47 | #ifdef CONFIG_SND_DEBUG |
48 | printk("snd_es1688_dsp_command: timeout (0x%x)\n", val); | 48 | printk(KERN_DEBUG "snd_es1688_dsp_command: timeout (0x%x)\n", val); |
49 | #endif | 49 | #endif |
50 | return 0; | 50 | return 0; |
51 | } | 51 | } |
@@ -167,13 +167,16 @@ static int snd_es1688_probe(struct snd_es1688 *chip) | |||
167 | hw = ES1688_HW_AUTO; | 167 | hw = ES1688_HW_AUTO; |
168 | switch (chip->version & 0xfff0) { | 168 | switch (chip->version & 0xfff0) { |
169 | case 0x4880: | 169 | case 0x4880: |
170 | snd_printk("[0x%lx] ESS: AudioDrive ES488 detected, but driver is in another place\n", chip->port); | 170 | snd_printk(KERN_ERR "[0x%lx] ESS: AudioDrive ES488 detected, " |
171 | "but driver is in another place\n", chip->port); | ||
171 | return -ENODEV; | 172 | return -ENODEV; |
172 | case 0x6880: | 173 | case 0x6880: |
173 | hw = (chip->version & 0x0f) >= 8 ? ES1688_HW_1688 : ES1688_HW_688; | 174 | hw = (chip->version & 0x0f) >= 8 ? ES1688_HW_1688 : ES1688_HW_688; |
174 | break; | 175 | break; |
175 | default: | 176 | default: |
176 | snd_printk("[0x%lx] ESS: unknown AudioDrive chip with version 0x%x (Jazz16 soundcard?)\n", chip->port, chip->version); | 177 | snd_printk(KERN_ERR "[0x%lx] ESS: unknown AudioDrive chip " |
178 | "with version 0x%x (Jazz16 soundcard?)\n", | ||
179 | chip->port, chip->version); | ||
177 | return -ENODEV; | 180 | return -ENODEV; |
178 | } | 181 | } |
179 | 182 | ||
@@ -223,7 +226,7 @@ static int snd_es1688_init(struct snd_es1688 * chip, int enable) | |||
223 | } | 226 | } |
224 | } | 227 | } |
225 | #if 0 | 228 | #if 0 |
226 | snd_printk("mpu cfg = 0x%x\n", cfg); | 229 | snd_printk(KERN_DEBUG "mpu cfg = 0x%x\n", cfg); |
227 | #endif | 230 | #endif |
228 | spin_lock_irqsave(&chip->reg_lock, flags); | 231 | spin_lock_irqsave(&chip->reg_lock, flags); |
229 | snd_es1688_mixer_write(chip, 0x40, cfg); | 232 | snd_es1688_mixer_write(chip, 0x40, cfg); |
@@ -237,7 +240,9 @@ static int snd_es1688_init(struct snd_es1688 * chip, int enable) | |||
237 | cfg = 0xf0; /* enable only DMA counter interrupt */ | 240 | cfg = 0xf0; /* enable only DMA counter interrupt */ |
238 | irq_bits = irqs[chip->irq & 0x0f]; | 241 | irq_bits = irqs[chip->irq & 0x0f]; |
239 | if (irq_bits < 0) { | 242 | if (irq_bits < 0) { |
240 | snd_printk("[0x%lx] ESS: bad IRQ %d for ES1688 chip!!\n", chip->port, chip->irq); | 243 | snd_printk(KERN_ERR "[0x%lx] ESS: bad IRQ %d " |
244 | "for ES1688 chip!!\n", | ||
245 | chip->port, chip->irq); | ||
241 | #if 0 | 246 | #if 0 |
242 | irq_bits = 0; | 247 | irq_bits = 0; |
243 | cfg = 0x10; | 248 | cfg = 0x10; |
@@ -250,7 +255,8 @@ static int snd_es1688_init(struct snd_es1688 * chip, int enable) | |||
250 | cfg = 0xf0; /* extended mode DMA enable */ | 255 | cfg = 0xf0; /* extended mode DMA enable */ |
251 | dma = chip->dma8; | 256 | dma = chip->dma8; |
252 | if (dma > 3 || dma == 2) { | 257 | if (dma > 3 || dma == 2) { |
253 | snd_printk("[0x%lx] ESS: bad DMA channel %d for ES1688 chip!!\n", chip->port, dma); | 258 | snd_printk(KERN_ERR "[0x%lx] ESS: bad DMA channel %d " |
259 | "for ES1688 chip!!\n", chip->port, dma); | ||
254 | #if 0 | 260 | #if 0 |
255 | dma_bits = 0; | 261 | dma_bits = 0; |
256 | cfg = 0x00; /* disable all DMA */ | 262 | cfg = 0x00; /* disable all DMA */ |
@@ -341,8 +347,9 @@ static int snd_es1688_trigger(struct snd_es1688 *chip, int cmd, unsigned char va | |||
341 | return -EINVAL; /* something is wrong */ | 347 | return -EINVAL; /* something is wrong */ |
342 | } | 348 | } |
343 | #if 0 | 349 | #if 0 |
344 | printk("trigger: val = 0x%x, value = 0x%x\n", val, value); | 350 | printk(KERN_DEBUG "trigger: val = 0x%x, value = 0x%x\n", val, value); |
345 | printk("trigger: pointer = 0x%x\n", snd_dma_pointer(chip->dma8, chip->dma_size)); | 351 | printk(KERN_DEBUG "trigger: pointer = 0x%x\n", |
352 | snd_dma_pointer(chip->dma8, chip->dma_size)); | ||
346 | #endif | 353 | #endif |
347 | snd_es1688_write(chip, 0xb8, (val & 0xf0) | value); | 354 | snd_es1688_write(chip, 0xb8, (val & 0xf0) | value); |
348 | spin_unlock(&chip->reg_lock); | 355 | spin_unlock(&chip->reg_lock); |
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c index 90498e4ca260..8cfbff73a835 100644 --- a/sound/isa/es18xx.c +++ b/sound/isa/es18xx.c | |||
@@ -2125,10 +2125,10 @@ static int __devinit snd_audiodrive_pnpc(int dev, struct snd_audiodrive *acard, | |||
2125 | #define is_isapnp_selected(dev) 0 | 2125 | #define is_isapnp_selected(dev) 0 |
2126 | #endif | 2126 | #endif |
2127 | 2127 | ||
2128 | static struct snd_card *snd_es18xx_card_new(int dev) | 2128 | static int snd_es18xx_card_new(int dev, struct snd_card **cardp) |
2129 | { | 2129 | { |
2130 | return snd_card_new(index[dev], id[dev], THIS_MODULE, | 2130 | return snd_card_create(index[dev], id[dev], THIS_MODULE, |
2131 | sizeof(struct snd_audiodrive)); | 2131 | sizeof(struct snd_audiodrive), cardp); |
2132 | } | 2132 | } |
2133 | 2133 | ||
2134 | static int __devinit snd_audiodrive_probe(struct snd_card *card, int dev) | 2134 | static int __devinit snd_audiodrive_probe(struct snd_card *card, int dev) |
@@ -2197,9 +2197,9 @@ static int __devinit snd_es18xx_isa_probe1(int dev, struct device *devptr) | |||
2197 | struct snd_card *card; | 2197 | struct snd_card *card; |
2198 | int err; | 2198 | int err; |
2199 | 2199 | ||
2200 | card = snd_es18xx_card_new(dev); | 2200 | err = snd_es18xx_card_new(dev, &card); |
2201 | if (! card) | 2201 | if (err < 0) |
2202 | return -ENOMEM; | 2202 | return err; |
2203 | snd_card_set_dev(card, devptr); | 2203 | snd_card_set_dev(card, devptr); |
2204 | if ((err = snd_audiodrive_probe(card, dev)) < 0) { | 2204 | if ((err = snd_audiodrive_probe(card, dev)) < 0) { |
2205 | snd_card_free(card); | 2205 | snd_card_free(card); |
@@ -2303,9 +2303,9 @@ static int __devinit snd_audiodrive_pnp_detect(struct pnp_dev *pdev, | |||
2303 | if (dev >= SNDRV_CARDS) | 2303 | if (dev >= SNDRV_CARDS) |
2304 | return -ENODEV; | 2304 | return -ENODEV; |
2305 | 2305 | ||
2306 | card = snd_es18xx_card_new(dev); | 2306 | err = snd_es18xx_card_new(dev, &card); |
2307 | if (! card) | 2307 | if (err < 0) |
2308 | return -ENOMEM; | 2308 | return err; |
2309 | if ((err = snd_audiodrive_pnp(dev, card->private_data, pdev)) < 0) { | 2309 | if ((err = snd_audiodrive_pnp(dev, card->private_data, pdev)) < 0) { |
2310 | snd_card_free(card); | 2310 | snd_card_free(card); |
2311 | return err; | 2311 | return err; |
@@ -2362,9 +2362,9 @@ static int __devinit snd_audiodrive_pnpc_detect(struct pnp_card_link *pcard, | |||
2362 | if (dev >= SNDRV_CARDS) | 2362 | if (dev >= SNDRV_CARDS) |
2363 | return -ENODEV; | 2363 | return -ENODEV; |
2364 | 2364 | ||
2365 | card = snd_es18xx_card_new(dev); | 2365 | res = snd_es18xx_card_new(dev, &card); |
2366 | if (! card) | 2366 | if (res < 0) |
2367 | return -ENOMEM; | 2367 | return res; |
2368 | 2368 | ||
2369 | if ((res = snd_audiodrive_pnpc(dev, card->private_data, pcard, pid)) < 0) { | 2369 | if ((res = snd_audiodrive_pnpc(dev, card->private_data, pcard, pid)) < 0) { |
2370 | snd_card_free(card); | 2370 | snd_card_free(card); |
diff --git a/sound/isa/gus/gus_dma.c b/sound/isa/gus/gus_dma.c index f45f6116c77a..36c27c832360 100644 --- a/sound/isa/gus/gus_dma.c +++ b/sound/isa/gus/gus_dma.c | |||
@@ -45,7 +45,8 @@ static void snd_gf1_dma_program(struct snd_gus_card * gus, | |||
45 | unsigned char dma_cmd; | 45 | unsigned char dma_cmd; |
46 | unsigned int address_high; | 46 | unsigned int address_high; |
47 | 47 | ||
48 | // snd_printk("dma_transfer: addr=0x%x, buf=0x%lx, count=0x%x\n", addr, (long) buf, count); | 48 | snd_printdd("dma_transfer: addr=0x%x, buf=0x%lx, count=0x%x\n", |
49 | addr, buf_addr, count); | ||
49 | 50 | ||
50 | if (gus->gf1.dma1 > 3) { | 51 | if (gus->gf1.dma1 > 3) { |
51 | if (gus->gf1.enh_mode) { | 52 | if (gus->gf1.enh_mode) { |
@@ -77,7 +78,8 @@ static void snd_gf1_dma_program(struct snd_gus_card * gus, | |||
77 | snd_gf1_dma_ack(gus); | 78 | snd_gf1_dma_ack(gus); |
78 | snd_dma_program(gus->gf1.dma1, buf_addr, count, dma_cmd & SNDRV_GF1_DMA_READ ? DMA_MODE_READ : DMA_MODE_WRITE); | 79 | snd_dma_program(gus->gf1.dma1, buf_addr, count, dma_cmd & SNDRV_GF1_DMA_READ ? DMA_MODE_READ : DMA_MODE_WRITE); |
79 | #if 0 | 80 | #if 0 |
80 | snd_printk("address = 0x%x, count = 0x%x, dma_cmd = 0x%x\n", address << 1, count, dma_cmd); | 81 | snd_printk(KERN_DEBUG "address = 0x%x, count = 0x%x, dma_cmd = 0x%x\n", |
82 | address << 1, count, dma_cmd); | ||
81 | #endif | 83 | #endif |
82 | spin_lock_irqsave(&gus->reg_lock, flags); | 84 | spin_lock_irqsave(&gus->reg_lock, flags); |
83 | if (gus->gf1.enh_mode) { | 85 | if (gus->gf1.enh_mode) { |
@@ -142,7 +144,9 @@ static void snd_gf1_dma_interrupt(struct snd_gus_card * gus) | |||
142 | snd_gf1_dma_program(gus, block->addr, block->buf_addr, block->count, (unsigned short) block->cmd); | 144 | snd_gf1_dma_program(gus, block->addr, block->buf_addr, block->count, (unsigned short) block->cmd); |
143 | kfree(block); | 145 | kfree(block); |
144 | #if 0 | 146 | #if 0 |
145 | printk("program dma (IRQ) - addr = 0x%x, buffer = 0x%lx, count = 0x%x, cmd = 0x%x\n", addr, (long) buffer, count, cmd); | 147 | snd_printd(KERN_DEBUG "program dma (IRQ) - " |
148 | "addr = 0x%x, buffer = 0x%lx, count = 0x%x, cmd = 0x%x\n", | ||
149 | block->addr, block->buf_addr, block->count, block->cmd); | ||
146 | #endif | 150 | #endif |
147 | } | 151 | } |
148 | 152 | ||
@@ -203,13 +207,16 @@ int snd_gf1_dma_transfer_block(struct snd_gus_card * gus, | |||
203 | } | 207 | } |
204 | *block = *__block; | 208 | *block = *__block; |
205 | block->next = NULL; | 209 | block->next = NULL; |
206 | #if 0 | 210 | |
207 | printk("addr = 0x%x, buffer = 0x%lx, count = 0x%x, cmd = 0x%x\n", block->addr, (long) block->buffer, block->count, block->cmd); | 211 | snd_printdd("addr = 0x%x, buffer = 0x%lx, count = 0x%x, cmd = 0x%x\n", |
208 | #endif | 212 | block->addr, (long) block->buffer, block->count, |
209 | #if 0 | 213 | block->cmd); |
210 | printk("gus->gf1.dma_data_pcm_last = 0x%lx\n", (long)gus->gf1.dma_data_pcm_last); | 214 | |
211 | printk("gus->gf1.dma_data_pcm = 0x%lx\n", (long)gus->gf1.dma_data_pcm); | 215 | snd_printdd("gus->gf1.dma_data_pcm_last = 0x%lx\n", |
212 | #endif | 216 | (long)gus->gf1.dma_data_pcm_last); |
217 | snd_printdd("gus->gf1.dma_data_pcm = 0x%lx\n", | ||
218 | (long)gus->gf1.dma_data_pcm); | ||
219 | |||
213 | spin_lock_irqsave(&gus->dma_lock, flags); | 220 | spin_lock_irqsave(&gus->dma_lock, flags); |
214 | if (synth) { | 221 | if (synth) { |
215 | if (gus->gf1.dma_data_synth_last) { | 222 | if (gus->gf1.dma_data_synth_last) { |
diff --git a/sound/isa/gus/gus_irq.c b/sound/isa/gus/gus_irq.c index 041894ddd014..2055aff71b50 100644 --- a/sound/isa/gus/gus_irq.c +++ b/sound/isa/gus/gus_irq.c | |||
@@ -41,7 +41,7 @@ __again: | |||
41 | if (status == 0) | 41 | if (status == 0) |
42 | return IRQ_RETVAL(handled); | 42 | return IRQ_RETVAL(handled); |
43 | handled = 1; | 43 | handled = 1; |
44 | // snd_printk("IRQ: status = 0x%x\n", status); | 44 | /* snd_printk(KERN_DEBUG "IRQ: status = 0x%x\n", status); */ |
45 | if (status & 0x02) { | 45 | if (status & 0x02) { |
46 | STAT_ADD(gus->gf1.interrupt_stat_midi_in); | 46 | STAT_ADD(gus->gf1.interrupt_stat_midi_in); |
47 | if (gus->gf1.interrupt_handler_midi_in) | 47 | if (gus->gf1.interrupt_handler_midi_in) |
@@ -65,7 +65,9 @@ __again: | |||
65 | continue; /* multi request */ | 65 | continue; /* multi request */ |
66 | already |= _current_; /* mark request */ | 66 | already |= _current_; /* mark request */ |
67 | #if 0 | 67 | #if 0 |
68 | printk("voice = %i, voice_status = 0x%x, voice_verify = %i\n", voice, voice_status, inb(GUSP(gus, GF1PAGE))); | 68 | printk(KERN_DEBUG "voice = %i, voice_status = 0x%x, " |
69 | "voice_verify = %i\n", | ||
70 | voice, voice_status, inb(GUSP(gus, GF1PAGE))); | ||
69 | #endif | 71 | #endif |
70 | pvoice = &gus->gf1.voices[voice]; | 72 | pvoice = &gus->gf1.voices[voice]; |
71 | if (pvoice->use) { | 73 | if (pvoice->use) { |
diff --git a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c index 38510aeb21c6..edb11eefdfe3 100644 --- a/sound/isa/gus/gus_pcm.c +++ b/sound/isa/gus/gus_pcm.c | |||
@@ -82,7 +82,10 @@ static int snd_gf1_pcm_block_change(struct snd_pcm_substream *substream, | |||
82 | 82 | ||
83 | count += offset & 31; | 83 | count += offset & 31; |
84 | offset &= ~31; | 84 | offset &= ~31; |
85 | // snd_printk("block change - offset = 0x%x, count = 0x%x\n", offset, count); | 85 | /* |
86 | snd_printk(KERN_DEBUG "block change - offset = 0x%x, count = 0x%x\n", | ||
87 | offset, count); | ||
88 | */ | ||
86 | memset(&block, 0, sizeof(block)); | 89 | memset(&block, 0, sizeof(block)); |
87 | block.cmd = SNDRV_GF1_DMA_IRQ; | 90 | block.cmd = SNDRV_GF1_DMA_IRQ; |
88 | if (snd_pcm_format_unsigned(runtime->format)) | 91 | if (snd_pcm_format_unsigned(runtime->format)) |
@@ -135,7 +138,11 @@ static void snd_gf1_pcm_trigger_up(struct snd_pcm_substream *substream) | |||
135 | curr = begin + (pcmp->bpos * pcmp->block_size) / runtime->channels; | 138 | curr = begin + (pcmp->bpos * pcmp->block_size) / runtime->channels; |
136 | end = curr + (pcmp->block_size / runtime->channels); | 139 | end = curr + (pcmp->block_size / runtime->channels); |
137 | end -= snd_pcm_format_width(runtime->format) == 16 ? 2 : 1; | 140 | end -= snd_pcm_format_width(runtime->format) == 16 ? 2 : 1; |
138 | // snd_printk("init: curr=0x%x, begin=0x%x, end=0x%x, ctrl=0x%x, ramp=0x%x, rate=0x%x\n", curr, begin, end, voice_ctrl, ramp_ctrl, rate); | 141 | /* |
142 | snd_printk(KERN_DEBUG "init: curr=0x%x, begin=0x%x, end=0x%x, " | ||
143 | "ctrl=0x%x, ramp=0x%x, rate=0x%x\n", | ||
144 | curr, begin, end, voice_ctrl, ramp_ctrl, rate); | ||
145 | */ | ||
139 | pan = runtime->channels == 2 ? (!voice ? 1 : 14) : 8; | 146 | pan = runtime->channels == 2 ? (!voice ? 1 : 14) : 8; |
140 | vol = !voice ? gus->gf1.pcm_volume_level_left : gus->gf1.pcm_volume_level_right; | 147 | vol = !voice ? gus->gf1.pcm_volume_level_left : gus->gf1.pcm_volume_level_right; |
141 | spin_lock_irqsave(&gus->reg_lock, flags); | 148 | spin_lock_irqsave(&gus->reg_lock, flags); |
@@ -205,9 +212,11 @@ static void snd_gf1_pcm_interrupt_wave(struct snd_gus_card * gus, | |||
205 | ramp_ctrl = (snd_gf1_read8(gus, SNDRV_GF1_VB_VOLUME_CONTROL) & ~0xa4) | 0x03; | 212 | ramp_ctrl = (snd_gf1_read8(gus, SNDRV_GF1_VB_VOLUME_CONTROL) & ~0xa4) | 0x03; |
206 | #if 0 | 213 | #if 0 |
207 | snd_gf1_select_voice(gus, pvoice->number); | 214 | snd_gf1_select_voice(gus, pvoice->number); |
208 | printk("position = 0x%x\n", (snd_gf1_read_addr(gus, SNDRV_GF1_VA_CURRENT, voice_ctrl & 4) >> 4)); | 215 | printk(KERN_DEBUG "position = 0x%x\n", |
216 | (snd_gf1_read_addr(gus, SNDRV_GF1_VA_CURRENT, voice_ctrl & 4) >> 4)); | ||
209 | snd_gf1_select_voice(gus, pcmp->pvoices[1]->number); | 217 | snd_gf1_select_voice(gus, pcmp->pvoices[1]->number); |
210 | printk("position = 0x%x\n", (snd_gf1_read_addr(gus, SNDRV_GF1_VA_CURRENT, voice_ctrl & 4) >> 4)); | 218 | printk(KERN_DEBUG "position = 0x%x\n", |
219 | (snd_gf1_read_addr(gus, SNDRV_GF1_VA_CURRENT, voice_ctrl & 4) >> 4)); | ||
211 | snd_gf1_select_voice(gus, pvoice->number); | 220 | snd_gf1_select_voice(gus, pvoice->number); |
212 | #endif | 221 | #endif |
213 | pcmp->bpos++; | 222 | pcmp->bpos++; |
@@ -299,7 +308,11 @@ static int snd_gf1_pcm_poke_block(struct snd_gus_card *gus, unsigned char *buf, | |||
299 | unsigned int len; | 308 | unsigned int len; |
300 | unsigned long flags; | 309 | unsigned long flags; |
301 | 310 | ||
302 | // printk("poke block; buf = 0x%x, pos = %i, count = %i, port = 0x%x\n", (int)buf, pos, count, gus->gf1.port); | 311 | /* |
312 | printk(KERN_DEBUG | ||
313 | "poke block; buf = 0x%x, pos = %i, count = %i, port = 0x%x\n", | ||
314 | (int)buf, pos, count, gus->gf1.port); | ||
315 | */ | ||
303 | while (count > 0) { | 316 | while (count > 0) { |
304 | len = count; | 317 | len = count; |
305 | if (len > 512) /* limit, to allow IRQ */ | 318 | if (len > 512) /* limit, to allow IRQ */ |
@@ -680,7 +693,8 @@ static int snd_gf1_pcm_playback_open(struct snd_pcm_substream *substream) | |||
680 | runtime->private_free = snd_gf1_pcm_playback_free; | 693 | runtime->private_free = snd_gf1_pcm_playback_free; |
681 | 694 | ||
682 | #if 0 | 695 | #if 0 |
683 | printk("playback.buffer = 0x%lx, gf1.pcm_buffer = 0x%lx\n", (long) pcm->playback.buffer, (long) gus->gf1.pcm_buffer); | 696 | printk(KERN_DEBUG "playback.buffer = 0x%lx, gf1.pcm_buffer = 0x%lx\n", |
697 | (long) pcm->playback.buffer, (long) gus->gf1.pcm_buffer); | ||
684 | #endif | 698 | #endif |
685 | if ((err = snd_gf1_dma_init(gus)) < 0) | 699 | if ((err = snd_gf1_dma_init(gus)) < 0) |
686 | return err; | 700 | return err; |
diff --git a/sound/isa/gus/gus_uart.c b/sound/isa/gus/gus_uart.c index f0af3f79b08b..21cc42e4c4be 100644 --- a/sound/isa/gus/gus_uart.c +++ b/sound/isa/gus/gus_uart.c | |||
@@ -129,8 +129,14 @@ static int snd_gf1_uart_input_open(struct snd_rawmidi_substream *substream) | |||
129 | } | 129 | } |
130 | spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); | 130 | spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); |
131 | #if 0 | 131 | #if 0 |
132 | snd_printk("read init - enable = %i, cmd = 0x%x, stat = 0x%x\n", gus->uart_enable, gus->gf1.uart_cmd, snd_gf1_uart_stat(gus)); | 132 | snd_printk(KERN_DEBUG |
133 | snd_printk("[0x%x] reg (ctrl/status) = 0x%x, reg (data) = 0x%x (page = 0x%x)\n", gus->gf1.port + 0x100, inb(gus->gf1.port + 0x100), inb(gus->gf1.port + 0x101), inb(gus->gf1.port + 0x102)); | 133 | "read init - enable = %i, cmd = 0x%x, stat = 0x%x\n", |
134 | gus->uart_enable, gus->gf1.uart_cmd, snd_gf1_uart_stat(gus)); | ||
135 | snd_printk(KERN_DEBUG | ||
136 | "[0x%x] reg (ctrl/status) = 0x%x, reg (data) = 0x%x " | ||
137 | "(page = 0x%x)\n", | ||
138 | gus->gf1.port + 0x100, inb(gus->gf1.port + 0x100), | ||
139 | inb(gus->gf1.port + 0x101), inb(gus->gf1.port + 0x102)); | ||
134 | #endif | 140 | #endif |
135 | return 0; | 141 | return 0; |
136 | } | 142 | } |
diff --git a/sound/isa/gus/gusclassic.c b/sound/isa/gus/gusclassic.c index 426532a4d730..086b8f0e0f94 100644 --- a/sound/isa/gus/gusclassic.c +++ b/sound/isa/gus/gusclassic.c | |||
@@ -148,9 +148,9 @@ static int __devinit snd_gusclassic_probe(struct device *dev, unsigned int n) | |||
148 | struct snd_gus_card *gus; | 148 | struct snd_gus_card *gus; |
149 | int error; | 149 | int error; |
150 | 150 | ||
151 | card = snd_card_new(index[n], id[n], THIS_MODULE, 0); | 151 | error = snd_card_create(index[n], id[n], THIS_MODULE, 0, &card); |
152 | if (!card) | 152 | if (error < 0) |
153 | return -EINVAL; | 153 | return error; |
154 | 154 | ||
155 | if (pcm_channels[n] < 2) | 155 | if (pcm_channels[n] < 2) |
156 | pcm_channels[n] = 2; | 156 | pcm_channels[n] = 2; |
diff --git a/sound/isa/gus/gusextreme.c b/sound/isa/gus/gusextreme.c index 7ad4c3b41a84..180a8dea6bd9 100644 --- a/sound/isa/gus/gusextreme.c +++ b/sound/isa/gus/gusextreme.c | |||
@@ -241,9 +241,9 @@ static int __devinit snd_gusextreme_probe(struct device *dev, unsigned int n) | |||
241 | struct snd_opl3 *opl3; | 241 | struct snd_opl3 *opl3; |
242 | int error; | 242 | int error; |
243 | 243 | ||
244 | card = snd_card_new(index[n], id[n], THIS_MODULE, 0); | 244 | error = snd_card_create(index[n], id[n], THIS_MODULE, 0, &card); |
245 | if (!card) | 245 | if (error < 0) |
246 | return -EINVAL; | 246 | return error; |
247 | 247 | ||
248 | if (mpu_port[n] == SNDRV_AUTO_PORT) | 248 | if (mpu_port[n] == SNDRV_AUTO_PORT) |
249 | mpu_port[n] = 0; | 249 | mpu_port[n] = 0; |
diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c index f94c1976e632..f26eac8d8110 100644 --- a/sound/isa/gus/gusmax.c +++ b/sound/isa/gus/gusmax.c | |||
@@ -214,10 +214,10 @@ static int __devinit snd_gusmax_probe(struct device *pdev, unsigned int dev) | |||
214 | struct snd_wss *wss; | 214 | struct snd_wss *wss; |
215 | struct snd_gusmax *maxcard; | 215 | struct snd_gusmax *maxcard; |
216 | 216 | ||
217 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, | 217 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, |
218 | sizeof(struct snd_gusmax)); | 218 | sizeof(struct snd_gusmax), &card); |
219 | if (card == NULL) | 219 | if (err < 0) |
220 | return -ENOMEM; | 220 | return err; |
221 | card->private_free = snd_gusmax_free; | 221 | card->private_free = snd_gusmax_free; |
222 | maxcard = (struct snd_gusmax *)card->private_data; | 222 | maxcard = (struct snd_gusmax *)card->private_data; |
223 | maxcard->card = card; | 223 | maxcard->card = card; |
diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c index 5faecfb602d3..534a6eced2b8 100644 --- a/sound/isa/gus/interwave.c +++ b/sound/isa/gus/interwave.c | |||
@@ -170,7 +170,7 @@ static void snd_interwave_i2c_setlines(struct snd_i2c_bus *bus, int ctrl, int da | |||
170 | unsigned long port = bus->private_value; | 170 | unsigned long port = bus->private_value; |
171 | 171 | ||
172 | #if 0 | 172 | #if 0 |
173 | printk("i2c_setlines - 0x%lx <- %i,%i\n", port, ctrl, data); | 173 | printk(KERN_DEBUG "i2c_setlines - 0x%lx <- %i,%i\n", port, ctrl, data); |
174 | #endif | 174 | #endif |
175 | outb((data << 1) | ctrl, port); | 175 | outb((data << 1) | ctrl, port); |
176 | udelay(10); | 176 | udelay(10); |
@@ -183,7 +183,7 @@ static int snd_interwave_i2c_getclockline(struct snd_i2c_bus *bus) | |||
183 | 183 | ||
184 | res = inb(port) & 1; | 184 | res = inb(port) & 1; |
185 | #if 0 | 185 | #if 0 |
186 | printk("i2c_getclockline - 0x%lx -> %i\n", port, res); | 186 | printk(KERN_DEBUG "i2c_getclockline - 0x%lx -> %i\n", port, res); |
187 | #endif | 187 | #endif |
188 | return res; | 188 | return res; |
189 | } | 189 | } |
@@ -197,7 +197,7 @@ static int snd_interwave_i2c_getdataline(struct snd_i2c_bus *bus, int ack) | |||
197 | udelay(10); | 197 | udelay(10); |
198 | res = (inb(port) & 2) >> 1; | 198 | res = (inb(port) & 2) >> 1; |
199 | #if 0 | 199 | #if 0 |
200 | printk("i2c_getdataline - 0x%lx -> %i\n", port, res); | 200 | printk(KERN_DEBUG "i2c_getdataline - 0x%lx -> %i\n", port, res); |
201 | #endif | 201 | #endif |
202 | return res; | 202 | return res; |
203 | } | 203 | } |
@@ -342,7 +342,8 @@ static void __devinit snd_interwave_bank_sizes(struct snd_gus_card * gus, int *s | |||
342 | snd_gf1_poke(gus, local, d); | 342 | snd_gf1_poke(gus, local, d); |
343 | snd_gf1_poke(gus, local + 1, d + 1); | 343 | snd_gf1_poke(gus, local + 1, d + 1); |
344 | #if 0 | 344 | #if 0 |
345 | printk("d = 0x%x, local = 0x%x, local + 1 = 0x%x, idx << 22 = 0x%x\n", | 345 | printk(KERN_DEBUG "d = 0x%x, local = 0x%x, " |
346 | "local + 1 = 0x%x, idx << 22 = 0x%x\n", | ||
346 | d, | 347 | d, |
347 | snd_gf1_peek(gus, local), | 348 | snd_gf1_peek(gus, local), |
348 | snd_gf1_peek(gus, local + 1), | 349 | snd_gf1_peek(gus, local + 1), |
@@ -356,7 +357,8 @@ static void __devinit snd_interwave_bank_sizes(struct snd_gus_card * gus, int *s | |||
356 | } | 357 | } |
357 | } | 358 | } |
358 | #if 0 | 359 | #if 0 |
359 | printk("sizes: %i %i %i %i\n", sizes[0], sizes[1], sizes[2], sizes[3]); | 360 | printk(KERN_DEBUG "sizes: %i %i %i %i\n", |
361 | sizes[0], sizes[1], sizes[2], sizes[3]); | ||
360 | #endif | 362 | #endif |
361 | } | 363 | } |
362 | 364 | ||
@@ -410,12 +412,12 @@ static void __devinit snd_interwave_detect_memory(struct snd_gus_card * gus) | |||
410 | lmct = (psizes[3] << 24) | (psizes[2] << 16) | | 412 | lmct = (psizes[3] << 24) | (psizes[2] << 16) | |
411 | (psizes[1] << 8) | psizes[0]; | 413 | (psizes[1] << 8) | psizes[0]; |
412 | #if 0 | 414 | #if 0 |
413 | printk("lmct = 0x%08x\n", lmct); | 415 | printk(KERN_DEBUG "lmct = 0x%08x\n", lmct); |
414 | #endif | 416 | #endif |
415 | for (i = 0; i < ARRAY_SIZE(lmc); i++) | 417 | for (i = 0; i < ARRAY_SIZE(lmc); i++) |
416 | if (lmct == lmc[i]) { | 418 | if (lmct == lmc[i]) { |
417 | #if 0 | 419 | #if 0 |
418 | printk("found !!! %i\n", i); | 420 | printk(KERN_DEBUG "found !!! %i\n", i); |
419 | #endif | 421 | #endif |
420 | snd_gf1_write16(gus, SNDRV_GF1_GW_MEMORY_CONFIG, (snd_gf1_look16(gus, SNDRV_GF1_GW_MEMORY_CONFIG) & 0xfff0) | i); | 422 | snd_gf1_write16(gus, SNDRV_GF1_GW_MEMORY_CONFIG, (snd_gf1_look16(gus, SNDRV_GF1_GW_MEMORY_CONFIG) & 0xfff0) | i); |
421 | snd_interwave_bank_sizes(gus, psizes); | 423 | snd_interwave_bank_sizes(gus, psizes); |
@@ -626,20 +628,22 @@ static void snd_interwave_free(struct snd_card *card) | |||
626 | free_irq(iwcard->irq, (void *)iwcard); | 628 | free_irq(iwcard->irq, (void *)iwcard); |
627 | } | 629 | } |
628 | 630 | ||
629 | static struct snd_card *snd_interwave_card_new(int dev) | 631 | static int snd_interwave_card_new(int dev, struct snd_card **cardp) |
630 | { | 632 | { |
631 | struct snd_card *card; | 633 | struct snd_card *card; |
632 | struct snd_interwave *iwcard; | 634 | struct snd_interwave *iwcard; |
635 | int err; | ||
633 | 636 | ||
634 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, | 637 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, |
635 | sizeof(struct snd_interwave)); | 638 | sizeof(struct snd_interwave), &card); |
636 | if (card == NULL) | 639 | if (err < 0) |
637 | return NULL; | 640 | return err; |
638 | iwcard = card->private_data; | 641 | iwcard = card->private_data; |
639 | iwcard->card = card; | 642 | iwcard->card = card; |
640 | iwcard->irq = -1; | 643 | iwcard->irq = -1; |
641 | card->private_free = snd_interwave_free; | 644 | card->private_free = snd_interwave_free; |
642 | return card; | 645 | *cardp = card; |
646 | return 0; | ||
643 | } | 647 | } |
644 | 648 | ||
645 | static int __devinit snd_interwave_probe(struct snd_card *card, int dev) | 649 | static int __devinit snd_interwave_probe(struct snd_card *card, int dev) |
@@ -778,9 +782,9 @@ static int __devinit snd_interwave_isa_probe1(int dev, struct device *devptr) | |||
778 | struct snd_card *card; | 782 | struct snd_card *card; |
779 | int err; | 783 | int err; |
780 | 784 | ||
781 | card = snd_interwave_card_new(dev); | 785 | err = snd_interwave_card_new(dev, &card); |
782 | if (! card) | 786 | if (err < 0) |
783 | return -ENOMEM; | 787 | return err; |
784 | 788 | ||
785 | snd_card_set_dev(card, devptr); | 789 | snd_card_set_dev(card, devptr); |
786 | if ((err = snd_interwave_probe(card, dev)) < 0) { | 790 | if ((err = snd_interwave_probe(card, dev)) < 0) { |
@@ -876,9 +880,9 @@ static int __devinit snd_interwave_pnp_detect(struct pnp_card_link *pcard, | |||
876 | if (dev >= SNDRV_CARDS) | 880 | if (dev >= SNDRV_CARDS) |
877 | return -ENODEV; | 881 | return -ENODEV; |
878 | 882 | ||
879 | card = snd_interwave_card_new(dev); | 883 | res = snd_interwave_card_new(dev, &card); |
880 | if (! card) | 884 | if (res < 0) |
881 | return -ENOMEM; | 885 | return res; |
882 | 886 | ||
883 | if ((res = snd_interwave_pnp(dev, card->private_data, pcard, pid)) < 0) { | 887 | if ((res = snd_interwave_pnp(dev, card->private_data, pcard, pid)) < 0) { |
884 | snd_card_free(card); | 888 | snd_card_free(card); |
diff --git a/sound/isa/msnd/Makefile b/sound/isa/msnd/Makefile new file mode 100644 index 000000000000..2171c0aa2f62 --- /dev/null +++ b/sound/isa/msnd/Makefile | |||
@@ -0,0 +1,9 @@ | |||
1 | |||
2 | snd-msnd-lib-objs := msnd.o msnd_midi.o msnd_pinnacle_mixer.o | ||
3 | snd-msnd-pinnacle-objs := msnd_pinnacle.o | ||
4 | snd-msnd-classic-objs := msnd_classic.o | ||
5 | |||
6 | # Toplevel Module Dependency | ||
7 | obj-$(CONFIG_SND_MSND_PINNACLE) += snd-msnd-pinnacle.o snd-msnd-lib.o | ||
8 | obj-$(CONFIG_SND_MSND_CLASSIC) += snd-msnd-classic.o snd-msnd-lib.o | ||
9 | |||
diff --git a/sound/isa/msnd/msnd.c b/sound/isa/msnd/msnd.c new file mode 100644 index 000000000000..906454413ed2 --- /dev/null +++ b/sound/isa/msnd/msnd.c | |||
@@ -0,0 +1,705 @@ | |||
1 | /********************************************************************* | ||
2 | * | ||
3 | * 2002/06/30 Karsten Wiese: | ||
4 | * removed kernel-version dependencies. | ||
5 | * ripped from linux kernel 2.4.18 (OSS Implementation) by me. | ||
6 | * In the OSS Version, this file is compiled to a separate MODULE, | ||
7 | * that is used by the pinnacle and the classic driver. | ||
8 | * since there is no classic driver for alsa yet (i dont have a classic | ||
9 | * & writing one blindfold is difficult) this file's object is statically | ||
10 | * linked into the pinnacle-driver-module for now. look for the string | ||
11 | * "uncomment this to make this a module again" | ||
12 | * to do guess what. | ||
13 | * | ||
14 | * the following is a copy of the 2.4.18 OSS FREE file-heading comment: | ||
15 | * | ||
16 | * msnd.c - Driver Base | ||
17 | * | ||
18 | * Turtle Beach MultiSound Sound Card Driver for Linux | ||
19 | * | ||
20 | * Copyright (C) 1998 Andrew Veliath | ||
21 | * | ||
22 | * This program is free software; you can redistribute it and/or modify | ||
23 | * it under the terms of the GNU General Public License as published by | ||
24 | * the Free Software Foundation; either version 2 of the License, or | ||
25 | * (at your option) any later version. | ||
26 | * | ||
27 | * This program is distributed in the hope that it will be useful, | ||
28 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
29 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
30 | * GNU General Public License for more details. | ||
31 | * | ||
32 | * You should have received a copy of the GNU General Public License | ||
33 | * along with this program; if not, write to the Free Software | ||
34 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
35 | * | ||
36 | ********************************************************************/ | ||
37 | |||
38 | #include <linux/kernel.h> | ||
39 | #include <linux/types.h> | ||
40 | #include <linux/interrupt.h> | ||
41 | #include <linux/io.h> | ||
42 | #include <linux/fs.h> | ||
43 | #include <linux/delay.h> | ||
44 | |||
45 | #include <sound/core.h> | ||
46 | #include <sound/initval.h> | ||
47 | #include <sound/pcm.h> | ||
48 | #include <sound/pcm_params.h> | ||
49 | |||
50 | #include "msnd.h" | ||
51 | |||
52 | #define LOGNAME "msnd" | ||
53 | |||
54 | |||
55 | void snd_msnd_init_queue(void *base, int start, int size) | ||
56 | { | ||
57 | writew(PCTODSP_BASED(start), base + JQS_wStart); | ||
58 | writew(PCTODSP_OFFSET(size) - 1, base + JQS_wSize); | ||
59 | writew(0, base + JQS_wHead); | ||
60 | writew(0, base + JQS_wTail); | ||
61 | } | ||
62 | EXPORT_SYMBOL(snd_msnd_init_queue); | ||
63 | |||
64 | static int snd_msnd_wait_TXDE(struct snd_msnd *dev) | ||
65 | { | ||
66 | unsigned int io = dev->io; | ||
67 | int timeout = 1000; | ||
68 | |||
69 | while (timeout-- > 0) | ||
70 | if (inb(io + HP_ISR) & HPISR_TXDE) | ||
71 | return 0; | ||
72 | |||
73 | return -EIO; | ||
74 | } | ||
75 | |||
76 | static int snd_msnd_wait_HC0(struct snd_msnd *dev) | ||
77 | { | ||
78 | unsigned int io = dev->io; | ||
79 | int timeout = 1000; | ||
80 | |||
81 | while (timeout-- > 0) | ||
82 | if (!(inb(io + HP_CVR) & HPCVR_HC)) | ||
83 | return 0; | ||
84 | |||
85 | return -EIO; | ||
86 | } | ||
87 | |||
88 | int snd_msnd_send_dsp_cmd(struct snd_msnd *dev, u8 cmd) | ||
89 | { | ||
90 | unsigned long flags; | ||
91 | |||
92 | spin_lock_irqsave(&dev->lock, flags); | ||
93 | if (snd_msnd_wait_HC0(dev) == 0) { | ||
94 | outb(cmd, dev->io + HP_CVR); | ||
95 | spin_unlock_irqrestore(&dev->lock, flags); | ||
96 | return 0; | ||
97 | } | ||
98 | spin_unlock_irqrestore(&dev->lock, flags); | ||
99 | |||
100 | snd_printd(KERN_ERR LOGNAME ": Send DSP command timeout\n"); | ||
101 | |||
102 | return -EIO; | ||
103 | } | ||
104 | EXPORT_SYMBOL(snd_msnd_send_dsp_cmd); | ||
105 | |||
106 | int snd_msnd_send_word(struct snd_msnd *dev, unsigned char high, | ||
107 | unsigned char mid, unsigned char low) | ||
108 | { | ||
109 | unsigned int io = dev->io; | ||
110 | |||
111 | if (snd_msnd_wait_TXDE(dev) == 0) { | ||
112 | outb(high, io + HP_TXH); | ||
113 | outb(mid, io + HP_TXM); | ||
114 | outb(low, io + HP_TXL); | ||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | snd_printd(KERN_ERR LOGNAME ": Send host word timeout\n"); | ||
119 | |||
120 | return -EIO; | ||
121 | } | ||
122 | EXPORT_SYMBOL(snd_msnd_send_word); | ||
123 | |||
124 | int snd_msnd_upload_host(struct snd_msnd *dev, const u8 *bin, int len) | ||
125 | { | ||
126 | int i; | ||
127 | |||
128 | if (len % 3 != 0) { | ||
129 | snd_printk(KERN_ERR LOGNAME | ||
130 | ": Upload host data not multiple of 3!\n"); | ||
131 | return -EINVAL; | ||
132 | } | ||
133 | |||
134 | for (i = 0; i < len; i += 3) | ||
135 | if (snd_msnd_send_word(dev, bin[i], bin[i + 1], bin[i + 2])) | ||
136 | return -EIO; | ||
137 | |||
138 | inb(dev->io + HP_RXL); | ||
139 | inb(dev->io + HP_CVR); | ||
140 | |||
141 | return 0; | ||
142 | } | ||
143 | EXPORT_SYMBOL(snd_msnd_upload_host); | ||
144 | |||
145 | int snd_msnd_enable_irq(struct snd_msnd *dev) | ||
146 | { | ||
147 | unsigned long flags; | ||
148 | |||
149 | if (dev->irq_ref++) | ||
150 | return 0; | ||
151 | |||
152 | snd_printdd(LOGNAME ": Enabling IRQ\n"); | ||
153 | |||
154 | spin_lock_irqsave(&dev->lock, flags); | ||
155 | if (snd_msnd_wait_TXDE(dev) == 0) { | ||
156 | outb(inb(dev->io + HP_ICR) | HPICR_TREQ, dev->io + HP_ICR); | ||
157 | if (dev->type == msndClassic) | ||
158 | outb(dev->irqid, dev->io + HP_IRQM); | ||
159 | |||
160 | outb(inb(dev->io + HP_ICR) & ~HPICR_TREQ, dev->io + HP_ICR); | ||
161 | outb(inb(dev->io + HP_ICR) | HPICR_RREQ, dev->io + HP_ICR); | ||
162 | enable_irq(dev->irq); | ||
163 | snd_msnd_init_queue(dev->DSPQ, dev->dspq_data_buff, | ||
164 | dev->dspq_buff_size); | ||
165 | spin_unlock_irqrestore(&dev->lock, flags); | ||
166 | return 0; | ||
167 | } | ||
168 | spin_unlock_irqrestore(&dev->lock, flags); | ||
169 | |||
170 | snd_printd(KERN_ERR LOGNAME ": Enable IRQ failed\n"); | ||
171 | |||
172 | return -EIO; | ||
173 | } | ||
174 | EXPORT_SYMBOL(snd_msnd_enable_irq); | ||
175 | |||
176 | int snd_msnd_disable_irq(struct snd_msnd *dev) | ||
177 | { | ||
178 | unsigned long flags; | ||
179 | |||
180 | if (--dev->irq_ref > 0) | ||
181 | return 0; | ||
182 | |||
183 | if (dev->irq_ref < 0) | ||
184 | snd_printd(KERN_WARNING LOGNAME ": IRQ ref count is %d\n", | ||
185 | dev->irq_ref); | ||
186 | |||
187 | snd_printdd(LOGNAME ": Disabling IRQ\n"); | ||
188 | |||
189 | spin_lock_irqsave(&dev->lock, flags); | ||
190 | if (snd_msnd_wait_TXDE(dev) == 0) { | ||
191 | outb(inb(dev->io + HP_ICR) & ~HPICR_RREQ, dev->io + HP_ICR); | ||
192 | if (dev->type == msndClassic) | ||
193 | outb(HPIRQ_NONE, dev->io + HP_IRQM); | ||
194 | disable_irq(dev->irq); | ||
195 | spin_unlock_irqrestore(&dev->lock, flags); | ||
196 | return 0; | ||
197 | } | ||
198 | spin_unlock_irqrestore(&dev->lock, flags); | ||
199 | |||
200 | snd_printd(KERN_ERR LOGNAME ": Disable IRQ failed\n"); | ||
201 | |||
202 | return -EIO; | ||
203 | } | ||
204 | EXPORT_SYMBOL(snd_msnd_disable_irq); | ||
205 | |||
206 | static inline long get_play_delay_jiffies(struct snd_msnd *chip, long size) | ||
207 | { | ||
208 | long tmp = (size * HZ * chip->play_sample_size) / 8; | ||
209 | return tmp / (chip->play_sample_rate * chip->play_channels); | ||
210 | } | ||
211 | |||
212 | static void snd_msnd_dsp_write_flush(struct snd_msnd *chip) | ||
213 | { | ||
214 | if (!(chip->mode & FMODE_WRITE) || !test_bit(F_WRITING, &chip->flags)) | ||
215 | return; | ||
216 | set_bit(F_WRITEFLUSH, &chip->flags); | ||
217 | /* interruptible_sleep_on_timeout( | ||
218 | &chip->writeflush, | ||
219 | get_play_delay_jiffies(&chip, chip->DAPF.len));*/ | ||
220 | clear_bit(F_WRITEFLUSH, &chip->flags); | ||
221 | if (!signal_pending(current)) | ||
222 | schedule_timeout_interruptible( | ||
223 | get_play_delay_jiffies(chip, chip->play_period_bytes)); | ||
224 | clear_bit(F_WRITING, &chip->flags); | ||
225 | } | ||
226 | |||
227 | void snd_msnd_dsp_halt(struct snd_msnd *chip, struct file *file) | ||
228 | { | ||
229 | if ((file ? file->f_mode : chip->mode) & FMODE_READ) { | ||
230 | clear_bit(F_READING, &chip->flags); | ||
231 | snd_msnd_send_dsp_cmd(chip, HDEX_RECORD_STOP); | ||
232 | snd_msnd_disable_irq(chip); | ||
233 | if (file) { | ||
234 | snd_printd(KERN_INFO LOGNAME | ||
235 | ": Stopping read for %p\n", file); | ||
236 | chip->mode &= ~FMODE_READ; | ||
237 | } | ||
238 | clear_bit(F_AUDIO_READ_INUSE, &chip->flags); | ||
239 | } | ||
240 | if ((file ? file->f_mode : chip->mode) & FMODE_WRITE) { | ||
241 | if (test_bit(F_WRITING, &chip->flags)) { | ||
242 | snd_msnd_dsp_write_flush(chip); | ||
243 | snd_msnd_send_dsp_cmd(chip, HDEX_PLAY_STOP); | ||
244 | } | ||
245 | snd_msnd_disable_irq(chip); | ||
246 | if (file) { | ||
247 | snd_printd(KERN_INFO | ||
248 | LOGNAME ": Stopping write for %p\n", file); | ||
249 | chip->mode &= ~FMODE_WRITE; | ||
250 | } | ||
251 | clear_bit(F_AUDIO_WRITE_INUSE, &chip->flags); | ||
252 | } | ||
253 | } | ||
254 | EXPORT_SYMBOL(snd_msnd_dsp_halt); | ||
255 | |||
256 | |||
257 | int snd_msnd_DARQ(struct snd_msnd *chip, int bank) | ||
258 | { | ||
259 | int /*size, n,*/ timeout = 3; | ||
260 | u16 wTmp; | ||
261 | /* void *DAQD; */ | ||
262 | |||
263 | /* Increment the tail and check for queue wrap */ | ||
264 | wTmp = readw(chip->DARQ + JQS_wTail) + PCTODSP_OFFSET(DAQDS__size); | ||
265 | if (wTmp > readw(chip->DARQ + JQS_wSize)) | ||
266 | wTmp = 0; | ||
267 | while (wTmp == readw(chip->DARQ + JQS_wHead) && timeout--) | ||
268 | udelay(1); | ||
269 | |||
270 | if (chip->capturePeriods == 2) { | ||
271 | void *pDAQ = chip->mappedbase + DARQ_DATA_BUFF + | ||
272 | bank * DAQDS__size + DAQDS_wStart; | ||
273 | unsigned short offset = 0x3000 + chip->capturePeriodBytes; | ||
274 | |||
275 | if (readw(pDAQ) != PCTODSP_BASED(0x3000)) | ||
276 | offset = 0x3000; | ||
277 | writew(PCTODSP_BASED(offset), pDAQ); | ||
278 | } | ||
279 | |||
280 | writew(wTmp, chip->DARQ + JQS_wTail); | ||
281 | |||
282 | #if 0 | ||
283 | /* Get our digital audio queue struct */ | ||
284 | DAQD = bank * DAQDS__size + chip->mappedbase + DARQ_DATA_BUFF; | ||
285 | |||
286 | /* Get length of data */ | ||
287 | size = readw(DAQD + DAQDS_wSize); | ||
288 | |||
289 | /* Read data from the head (unprotected bank 1 access okay | ||
290 | since this is only called inside an interrupt) */ | ||
291 | outb(HPBLKSEL_1, chip->io + HP_BLKS); | ||
292 | n = msnd_fifo_write(&chip->DARF, | ||
293 | (char *)(chip->base + bank * DAR_BUFF_SIZE), | ||
294 | size, 0); | ||
295 | if (n <= 0) { | ||
296 | outb(HPBLKSEL_0, chip->io + HP_BLKS); | ||
297 | return n; | ||
298 | } | ||
299 | outb(HPBLKSEL_0, chip->io + HP_BLKS); | ||
300 | #endif | ||
301 | |||
302 | return 1; | ||
303 | } | ||
304 | EXPORT_SYMBOL(snd_msnd_DARQ); | ||
305 | |||
306 | int snd_msnd_DAPQ(struct snd_msnd *chip, int start) | ||
307 | { | ||
308 | u16 DAPQ_tail; | ||
309 | int protect = start, nbanks = 0; | ||
310 | void *DAQD; | ||
311 | static int play_banks_submitted; | ||
312 | /* unsigned long flags; | ||
313 | spin_lock_irqsave(&chip->lock, flags); not necessary */ | ||
314 | |||
315 | DAPQ_tail = readw(chip->DAPQ + JQS_wTail); | ||
316 | while (DAPQ_tail != readw(chip->DAPQ + JQS_wHead) || start) { | ||
317 | int bank_num = DAPQ_tail / PCTODSP_OFFSET(DAQDS__size); | ||
318 | |||
319 | if (start) { | ||
320 | start = 0; | ||
321 | play_banks_submitted = 0; | ||
322 | } | ||
323 | |||
324 | /* Get our digital audio queue struct */ | ||
325 | DAQD = bank_num * DAQDS__size + chip->mappedbase + | ||
326 | DAPQ_DATA_BUFF; | ||
327 | |||
328 | /* Write size of this bank */ | ||
329 | writew(chip->play_period_bytes, DAQD + DAQDS_wSize); | ||
330 | if (play_banks_submitted < 3) | ||
331 | ++play_banks_submitted; | ||
332 | else if (chip->playPeriods == 2) { | ||
333 | unsigned short offset = chip->play_period_bytes; | ||
334 | |||
335 | if (readw(DAQD + DAQDS_wStart) != PCTODSP_BASED(0x0)) | ||
336 | offset = 0; | ||
337 | |||
338 | writew(PCTODSP_BASED(offset), DAQD + DAQDS_wStart); | ||
339 | } | ||
340 | ++nbanks; | ||
341 | |||
342 | /* Then advance the tail */ | ||
343 | /* | ||
344 | if (protect) | ||
345 | snd_printd(KERN_INFO "B %X %lX\n", | ||
346 | bank_num, xtime.tv_usec); | ||
347 | */ | ||
348 | |||
349 | DAPQ_tail = (++bank_num % 3) * PCTODSP_OFFSET(DAQDS__size); | ||
350 | writew(DAPQ_tail, chip->DAPQ + JQS_wTail); | ||
351 | /* Tell the DSP to play the bank */ | ||
352 | snd_msnd_send_dsp_cmd(chip, HDEX_PLAY_START); | ||
353 | if (protect) | ||
354 | if (2 == bank_num) | ||
355 | break; | ||
356 | } | ||
357 | /* | ||
358 | if (protect) | ||
359 | snd_printd(KERN_INFO "%lX\n", xtime.tv_usec); | ||
360 | */ | ||
361 | /* spin_unlock_irqrestore(&chip->lock, flags); not necessary */ | ||
362 | return nbanks; | ||
363 | } | ||
364 | EXPORT_SYMBOL(snd_msnd_DAPQ); | ||
365 | |||
366 | static void snd_msnd_play_reset_queue(struct snd_msnd *chip, | ||
367 | unsigned int pcm_periods, | ||
368 | unsigned int pcm_count) | ||
369 | { | ||
370 | int n; | ||
371 | void *pDAQ = chip->mappedbase + DAPQ_DATA_BUFF; | ||
372 | |||
373 | chip->last_playbank = -1; | ||
374 | chip->playLimit = pcm_count * (pcm_periods - 1); | ||
375 | chip->playPeriods = pcm_periods; | ||
376 | writew(PCTODSP_OFFSET(0 * DAQDS__size), chip->DAPQ + JQS_wHead); | ||
377 | writew(PCTODSP_OFFSET(0 * DAQDS__size), chip->DAPQ + JQS_wTail); | ||
378 | |||
379 | chip->play_period_bytes = pcm_count; | ||
380 | |||
381 | for (n = 0; n < pcm_periods; ++n, pDAQ += DAQDS__size) { | ||
382 | writew(PCTODSP_BASED((u32)(pcm_count * n)), | ||
383 | pDAQ + DAQDS_wStart); | ||
384 | writew(0, pDAQ + DAQDS_wSize); | ||
385 | writew(1, pDAQ + DAQDS_wFormat); | ||
386 | writew(chip->play_sample_size, pDAQ + DAQDS_wSampleSize); | ||
387 | writew(chip->play_channels, pDAQ + DAQDS_wChannels); | ||
388 | writew(chip->play_sample_rate, pDAQ + DAQDS_wSampleRate); | ||
389 | writew(HIMT_PLAY_DONE * 0x100 + n, pDAQ + DAQDS_wIntMsg); | ||
390 | writew(n, pDAQ + DAQDS_wFlags); | ||
391 | } | ||
392 | } | ||
393 | |||
394 | static void snd_msnd_capture_reset_queue(struct snd_msnd *chip, | ||
395 | unsigned int pcm_periods, | ||
396 | unsigned int pcm_count) | ||
397 | { | ||
398 | int n; | ||
399 | void *pDAQ; | ||
400 | /* unsigned long flags; */ | ||
401 | |||
402 | /* snd_msnd_init_queue(chip->DARQ, DARQ_DATA_BUFF, DARQ_BUFF_SIZE); */ | ||
403 | |||
404 | chip->last_recbank = 2; | ||
405 | chip->captureLimit = pcm_count * (pcm_periods - 1); | ||
406 | chip->capturePeriods = pcm_periods; | ||
407 | writew(PCTODSP_OFFSET(0 * DAQDS__size), chip->DARQ + JQS_wHead); | ||
408 | writew(PCTODSP_OFFSET(chip->last_recbank * DAQDS__size), | ||
409 | chip->DARQ + JQS_wTail); | ||
410 | |||
411 | #if 0 /* Critical section: bank 1 access. this is how the OSS driver does it:*/ | ||
412 | spin_lock_irqsave(&chip->lock, flags); | ||
413 | outb(HPBLKSEL_1, chip->io + HP_BLKS); | ||
414 | memset_io(chip->mappedbase, 0, DAR_BUFF_SIZE * 3); | ||
415 | outb(HPBLKSEL_0, chip->io + HP_BLKS); | ||
416 | spin_unlock_irqrestore(&chip->lock, flags); | ||
417 | #endif | ||
418 | |||
419 | chip->capturePeriodBytes = pcm_count; | ||
420 | snd_printdd("snd_msnd_capture_reset_queue() %i\n", pcm_count); | ||
421 | |||
422 | pDAQ = chip->mappedbase + DARQ_DATA_BUFF; | ||
423 | |||
424 | for (n = 0; n < pcm_periods; ++n, pDAQ += DAQDS__size) { | ||
425 | u32 tmp = pcm_count * n; | ||
426 | |||
427 | writew(PCTODSP_BASED(tmp + 0x3000), pDAQ + DAQDS_wStart); | ||
428 | writew(pcm_count, pDAQ + DAQDS_wSize); | ||
429 | writew(1, pDAQ + DAQDS_wFormat); | ||
430 | writew(chip->capture_sample_size, pDAQ + DAQDS_wSampleSize); | ||
431 | writew(chip->capture_channels, pDAQ + DAQDS_wChannels); | ||
432 | writew(chip->capture_sample_rate, pDAQ + DAQDS_wSampleRate); | ||
433 | writew(HIMT_RECORD_DONE * 0x100 + n, pDAQ + DAQDS_wIntMsg); | ||
434 | writew(n, pDAQ + DAQDS_wFlags); | ||
435 | } | ||
436 | } | ||
437 | |||
438 | static struct snd_pcm_hardware snd_msnd_playback = { | ||
439 | .info = SNDRV_PCM_INFO_MMAP | | ||
440 | SNDRV_PCM_INFO_INTERLEAVED | | ||
441 | SNDRV_PCM_INFO_MMAP_VALID, | ||
442 | .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, | ||
443 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
444 | .rate_min = 8000, | ||
445 | .rate_max = 48000, | ||
446 | .channels_min = 1, | ||
447 | .channels_max = 2, | ||
448 | .buffer_bytes_max = 0x3000, | ||
449 | .period_bytes_min = 0x40, | ||
450 | .period_bytes_max = 0x1800, | ||
451 | .periods_min = 2, | ||
452 | .periods_max = 3, | ||
453 | .fifo_size = 0, | ||
454 | }; | ||
455 | |||
456 | static struct snd_pcm_hardware snd_msnd_capture = { | ||
457 | .info = SNDRV_PCM_INFO_MMAP | | ||
458 | SNDRV_PCM_INFO_INTERLEAVED | | ||
459 | SNDRV_PCM_INFO_MMAP_VALID, | ||
460 | .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, | ||
461 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
462 | .rate_min = 8000, | ||
463 | .rate_max = 48000, | ||
464 | .channels_min = 1, | ||
465 | .channels_max = 2, | ||
466 | .buffer_bytes_max = 0x3000, | ||
467 | .period_bytes_min = 0x40, | ||
468 | .period_bytes_max = 0x1800, | ||
469 | .periods_min = 2, | ||
470 | .periods_max = 3, | ||
471 | .fifo_size = 0, | ||
472 | }; | ||
473 | |||
474 | |||
475 | static int snd_msnd_playback_open(struct snd_pcm_substream *substream) | ||
476 | { | ||
477 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
478 | struct snd_msnd *chip = snd_pcm_substream_chip(substream); | ||
479 | |||
480 | set_bit(F_AUDIO_WRITE_INUSE, &chip->flags); | ||
481 | clear_bit(F_WRITING, &chip->flags); | ||
482 | snd_msnd_enable_irq(chip); | ||
483 | |||
484 | runtime->dma_area = chip->mappedbase; | ||
485 | runtime->dma_bytes = 0x3000; | ||
486 | |||
487 | chip->playback_substream = substream; | ||
488 | runtime->hw = snd_msnd_playback; | ||
489 | return 0; | ||
490 | } | ||
491 | |||
492 | static int snd_msnd_playback_close(struct snd_pcm_substream *substream) | ||
493 | { | ||
494 | struct snd_msnd *chip = snd_pcm_substream_chip(substream); | ||
495 | |||
496 | snd_msnd_disable_irq(chip); | ||
497 | clear_bit(F_AUDIO_WRITE_INUSE, &chip->flags); | ||
498 | return 0; | ||
499 | } | ||
500 | |||
501 | |||
502 | static int snd_msnd_playback_hw_params(struct snd_pcm_substream *substream, | ||
503 | struct snd_pcm_hw_params *params) | ||
504 | { | ||
505 | int i; | ||
506 | struct snd_msnd *chip = snd_pcm_substream_chip(substream); | ||
507 | void *pDAQ = chip->mappedbase + DAPQ_DATA_BUFF; | ||
508 | |||
509 | chip->play_sample_size = snd_pcm_format_width(params_format(params)); | ||
510 | chip->play_channels = params_channels(params); | ||
511 | chip->play_sample_rate = params_rate(params); | ||
512 | |||
513 | for (i = 0; i < 3; ++i, pDAQ += DAQDS__size) { | ||
514 | writew(chip->play_sample_size, pDAQ + DAQDS_wSampleSize); | ||
515 | writew(chip->play_channels, pDAQ + DAQDS_wChannels); | ||
516 | writew(chip->play_sample_rate, pDAQ + DAQDS_wSampleRate); | ||
517 | } | ||
518 | /* dont do this here: | ||
519 | * snd_msnd_calibrate_adc(chip->play_sample_rate); | ||
520 | */ | ||
521 | |||
522 | return 0; | ||
523 | } | ||
524 | |||
525 | static int snd_msnd_playback_prepare(struct snd_pcm_substream *substream) | ||
526 | { | ||
527 | struct snd_msnd *chip = snd_pcm_substream_chip(substream); | ||
528 | unsigned int pcm_size = snd_pcm_lib_buffer_bytes(substream); | ||
529 | unsigned int pcm_count = snd_pcm_lib_period_bytes(substream); | ||
530 | unsigned int pcm_periods = pcm_size / pcm_count; | ||
531 | |||
532 | snd_msnd_play_reset_queue(chip, pcm_periods, pcm_count); | ||
533 | chip->playDMAPos = 0; | ||
534 | return 0; | ||
535 | } | ||
536 | |||
537 | static int snd_msnd_playback_trigger(struct snd_pcm_substream *substream, | ||
538 | int cmd) | ||
539 | { | ||
540 | struct snd_msnd *chip = snd_pcm_substream_chip(substream); | ||
541 | int result = 0; | ||
542 | |||
543 | if (cmd == SNDRV_PCM_TRIGGER_START) { | ||
544 | snd_printdd("snd_msnd_playback_trigger(START)\n"); | ||
545 | chip->banksPlayed = 0; | ||
546 | set_bit(F_WRITING, &chip->flags); | ||
547 | snd_msnd_DAPQ(chip, 1); | ||
548 | } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { | ||
549 | snd_printdd("snd_msnd_playback_trigger(STop)\n"); | ||
550 | /* interrupt diagnostic, comment this out later */ | ||
551 | clear_bit(F_WRITING, &chip->flags); | ||
552 | snd_msnd_send_dsp_cmd(chip, HDEX_PLAY_STOP); | ||
553 | } else { | ||
554 | snd_printd(KERN_ERR "snd_msnd_playback_trigger(?????)\n"); | ||
555 | result = -EINVAL; | ||
556 | } | ||
557 | |||
558 | snd_printdd("snd_msnd_playback_trigger() ENDE\n"); | ||
559 | return result; | ||
560 | } | ||
561 | |||
562 | static snd_pcm_uframes_t | ||
563 | snd_msnd_playback_pointer(struct snd_pcm_substream *substream) | ||
564 | { | ||
565 | struct snd_msnd *chip = snd_pcm_substream_chip(substream); | ||
566 | |||
567 | return bytes_to_frames(substream->runtime, chip->playDMAPos); | ||
568 | } | ||
569 | |||
570 | |||
571 | static struct snd_pcm_ops snd_msnd_playback_ops = { | ||
572 | .open = snd_msnd_playback_open, | ||
573 | .close = snd_msnd_playback_close, | ||
574 | .ioctl = snd_pcm_lib_ioctl, | ||
575 | .hw_params = snd_msnd_playback_hw_params, | ||
576 | .prepare = snd_msnd_playback_prepare, | ||
577 | .trigger = snd_msnd_playback_trigger, | ||
578 | .pointer = snd_msnd_playback_pointer, | ||
579 | }; | ||
580 | |||
581 | static int snd_msnd_capture_open(struct snd_pcm_substream *substream) | ||
582 | { | ||
583 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
584 | struct snd_msnd *chip = snd_pcm_substream_chip(substream); | ||
585 | |||
586 | set_bit(F_AUDIO_READ_INUSE, &chip->flags); | ||
587 | snd_msnd_enable_irq(chip); | ||
588 | runtime->dma_area = chip->mappedbase + 0x3000; | ||
589 | runtime->dma_bytes = 0x3000; | ||
590 | memset(runtime->dma_area, 0, runtime->dma_bytes); | ||
591 | chip->capture_substream = substream; | ||
592 | runtime->hw = snd_msnd_capture; | ||
593 | return 0; | ||
594 | } | ||
595 | |||
596 | static int snd_msnd_capture_close(struct snd_pcm_substream *substream) | ||
597 | { | ||
598 | struct snd_msnd *chip = snd_pcm_substream_chip(substream); | ||
599 | |||
600 | snd_msnd_disable_irq(chip); | ||
601 | clear_bit(F_AUDIO_READ_INUSE, &chip->flags); | ||
602 | return 0; | ||
603 | } | ||
604 | |||
605 | static int snd_msnd_capture_prepare(struct snd_pcm_substream *substream) | ||
606 | { | ||
607 | struct snd_msnd *chip = snd_pcm_substream_chip(substream); | ||
608 | unsigned int pcm_size = snd_pcm_lib_buffer_bytes(substream); | ||
609 | unsigned int pcm_count = snd_pcm_lib_period_bytes(substream); | ||
610 | unsigned int pcm_periods = pcm_size / pcm_count; | ||
611 | |||
612 | snd_msnd_capture_reset_queue(chip, pcm_periods, pcm_count); | ||
613 | chip->captureDMAPos = 0; | ||
614 | return 0; | ||
615 | } | ||
616 | |||
617 | static int snd_msnd_capture_trigger(struct snd_pcm_substream *substream, | ||
618 | int cmd) | ||
619 | { | ||
620 | struct snd_msnd *chip = snd_pcm_substream_chip(substream); | ||
621 | |||
622 | if (cmd == SNDRV_PCM_TRIGGER_START) { | ||
623 | chip->last_recbank = -1; | ||
624 | set_bit(F_READING, &chip->flags); | ||
625 | if (snd_msnd_send_dsp_cmd(chip, HDEX_RECORD_START) == 0) | ||
626 | return 0; | ||
627 | |||
628 | clear_bit(F_READING, &chip->flags); | ||
629 | } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { | ||
630 | clear_bit(F_READING, &chip->flags); | ||
631 | snd_msnd_send_dsp_cmd(chip, HDEX_RECORD_STOP); | ||
632 | return 0; | ||
633 | } | ||
634 | return -EINVAL; | ||
635 | } | ||
636 | |||
637 | |||
638 | static snd_pcm_uframes_t | ||
639 | snd_msnd_capture_pointer(struct snd_pcm_substream *substream) | ||
640 | { | ||
641 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
642 | struct snd_msnd *chip = snd_pcm_substream_chip(substream); | ||
643 | |||
644 | return bytes_to_frames(runtime, chip->captureDMAPos); | ||
645 | } | ||
646 | |||
647 | |||
648 | static int snd_msnd_capture_hw_params(struct snd_pcm_substream *substream, | ||
649 | struct snd_pcm_hw_params *params) | ||
650 | { | ||
651 | int i; | ||
652 | struct snd_msnd *chip = snd_pcm_substream_chip(substream); | ||
653 | void *pDAQ = chip->mappedbase + DARQ_DATA_BUFF; | ||
654 | |||
655 | chip->capture_sample_size = snd_pcm_format_width(params_format(params)); | ||
656 | chip->capture_channels = params_channels(params); | ||
657 | chip->capture_sample_rate = params_rate(params); | ||
658 | |||
659 | for (i = 0; i < 3; ++i, pDAQ += DAQDS__size) { | ||
660 | writew(chip->capture_sample_size, pDAQ + DAQDS_wSampleSize); | ||
661 | writew(chip->capture_channels, pDAQ + DAQDS_wChannels); | ||
662 | writew(chip->capture_sample_rate, pDAQ + DAQDS_wSampleRate); | ||
663 | } | ||
664 | return 0; | ||
665 | } | ||
666 | |||
667 | |||
668 | static struct snd_pcm_ops snd_msnd_capture_ops = { | ||
669 | .open = snd_msnd_capture_open, | ||
670 | .close = snd_msnd_capture_close, | ||
671 | .ioctl = snd_pcm_lib_ioctl, | ||
672 | .hw_params = snd_msnd_capture_hw_params, | ||
673 | .prepare = snd_msnd_capture_prepare, | ||
674 | .trigger = snd_msnd_capture_trigger, | ||
675 | .pointer = snd_msnd_capture_pointer, | ||
676 | }; | ||
677 | |||
678 | |||
679 | int snd_msnd_pcm(struct snd_card *card, int device, | ||
680 | struct snd_pcm **rpcm) | ||
681 | { | ||
682 | struct snd_msnd *chip = card->private_data; | ||
683 | struct snd_pcm *pcm; | ||
684 | int err; | ||
685 | |||
686 | err = snd_pcm_new(card, "MSNDPINNACLE", device, 1, 1, &pcm); | ||
687 | if (err < 0) | ||
688 | return err; | ||
689 | |||
690 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_msnd_playback_ops); | ||
691 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_msnd_capture_ops); | ||
692 | |||
693 | pcm->private_data = chip; | ||
694 | strcpy(pcm->name, "Hurricane"); | ||
695 | |||
696 | |||
697 | if (rpcm) | ||
698 | *rpcm = pcm; | ||
699 | return 0; | ||
700 | } | ||
701 | EXPORT_SYMBOL(snd_msnd_pcm); | ||
702 | |||
703 | MODULE_DESCRIPTION("Common routines for Turtle Beach Multisound drivers"); | ||
704 | MODULE_LICENSE("GPL"); | ||
705 | |||
diff --git a/sound/isa/msnd/msnd.h b/sound/isa/msnd/msnd.h new file mode 100644 index 000000000000..3773e242b58e --- /dev/null +++ b/sound/isa/msnd/msnd.h | |||
@@ -0,0 +1,308 @@ | |||
1 | /********************************************************************* | ||
2 | * | ||
3 | * msnd.h | ||
4 | * | ||
5 | * Turtle Beach MultiSound Sound Card Driver for Linux | ||
6 | * | ||
7 | * Some parts of this header file were derived from the Turtle Beach | ||
8 | * MultiSound Driver Development Kit. | ||
9 | * | ||
10 | * Copyright (C) 1998 Andrew Veliath | ||
11 | * Copyright (C) 1993 Turtle Beach Systems, Inc. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | * | ||
27 | ********************************************************************/ | ||
28 | #ifndef __MSND_H | ||
29 | #define __MSND_H | ||
30 | |||
31 | #define DEFSAMPLERATE 44100 | ||
32 | #define DEFSAMPLESIZE SNDRV_PCM_FORMAT_S16 | ||
33 | #define DEFCHANNELS 1 | ||
34 | |||
35 | #define SRAM_BANK_SIZE 0x8000 | ||
36 | #define SRAM_CNTL_START 0x7F00 | ||
37 | #define SMA_STRUCT_START 0x7F40 | ||
38 | |||
39 | #define DSP_BASE_ADDR 0x4000 | ||
40 | #define DSP_BANK_BASE 0x4000 | ||
41 | |||
42 | #define AGND 0x01 | ||
43 | #define SIGNAL 0x02 | ||
44 | |||
45 | #define EXT_DSP_BIT_DCAL 0x0001 | ||
46 | #define EXT_DSP_BIT_MIDI_CON 0x0002 | ||
47 | |||
48 | #define BUFFSIZE 0x8000 | ||
49 | #define HOSTQ_SIZE 0x40 | ||
50 | |||
51 | #define DAP_BUFF_SIZE 0x2400 | ||
52 | |||
53 | #define DAPQ_STRUCT_SIZE 0x10 | ||
54 | #define DARQ_STRUCT_SIZE 0x10 | ||
55 | #define DAPQ_BUFF_SIZE (3 * 0x10) | ||
56 | #define DARQ_BUFF_SIZE (3 * 0x10) | ||
57 | #define MODQ_BUFF_SIZE 0x400 | ||
58 | |||
59 | #define DAPQ_DATA_BUFF 0x6C00 | ||
60 | #define DARQ_DATA_BUFF 0x6C30 | ||
61 | #define MODQ_DATA_BUFF 0x6C60 | ||
62 | #define MIDQ_DATA_BUFF 0x7060 | ||
63 | |||
64 | #define DAPQ_OFFSET SRAM_CNTL_START | ||
65 | #define DARQ_OFFSET (SRAM_CNTL_START + 0x08) | ||
66 | #define MODQ_OFFSET (SRAM_CNTL_START + 0x10) | ||
67 | #define MIDQ_OFFSET (SRAM_CNTL_START + 0x18) | ||
68 | #define DSPQ_OFFSET (SRAM_CNTL_START + 0x20) | ||
69 | |||
70 | #define HP_ICR 0x00 | ||
71 | #define HP_CVR 0x01 | ||
72 | #define HP_ISR 0x02 | ||
73 | #define HP_IVR 0x03 | ||
74 | #define HP_NU 0x04 | ||
75 | #define HP_INFO 0x04 | ||
76 | #define HP_TXH 0x05 | ||
77 | #define HP_RXH 0x05 | ||
78 | #define HP_TXM 0x06 | ||
79 | #define HP_RXM 0x06 | ||
80 | #define HP_TXL 0x07 | ||
81 | #define HP_RXL 0x07 | ||
82 | |||
83 | #define HP_ICR_DEF 0x00 | ||
84 | #define HP_CVR_DEF 0x12 | ||
85 | #define HP_ISR_DEF 0x06 | ||
86 | #define HP_IVR_DEF 0x0f | ||
87 | #define HP_NU_DEF 0x00 | ||
88 | |||
89 | #define HP_IRQM 0x09 | ||
90 | |||
91 | #define HPR_BLRC 0x08 | ||
92 | #define HPR_SPR1 0x09 | ||
93 | #define HPR_SPR2 0x0A | ||
94 | #define HPR_TCL0 0x0B | ||
95 | #define HPR_TCL1 0x0C | ||
96 | #define HPR_TCL2 0x0D | ||
97 | #define HPR_TCL3 0x0E | ||
98 | #define HPR_TCL4 0x0F | ||
99 | |||
100 | #define HPICR_INIT 0x80 | ||
101 | #define HPICR_HM1 0x40 | ||
102 | #define HPICR_HM0 0x20 | ||
103 | #define HPICR_HF1 0x10 | ||
104 | #define HPICR_HF0 0x08 | ||
105 | #define HPICR_TREQ 0x02 | ||
106 | #define HPICR_RREQ 0x01 | ||
107 | |||
108 | #define HPCVR_HC 0x80 | ||
109 | |||
110 | #define HPISR_HREQ 0x80 | ||
111 | #define HPISR_DMA 0x40 | ||
112 | #define HPISR_HF3 0x10 | ||
113 | #define HPISR_HF2 0x08 | ||
114 | #define HPISR_TRDY 0x04 | ||
115 | #define HPISR_TXDE 0x02 | ||
116 | #define HPISR_RXDF 0x01 | ||
117 | |||
118 | #define HPIO_290 0 | ||
119 | #define HPIO_260 1 | ||
120 | #define HPIO_250 2 | ||
121 | #define HPIO_240 3 | ||
122 | #define HPIO_230 4 | ||
123 | #define HPIO_220 5 | ||
124 | #define HPIO_210 6 | ||
125 | #define HPIO_3E0 7 | ||
126 | |||
127 | #define HPMEM_NONE 0 | ||
128 | #define HPMEM_B000 1 | ||
129 | #define HPMEM_C800 2 | ||
130 | #define HPMEM_D000 3 | ||
131 | #define HPMEM_D400 4 | ||
132 | #define HPMEM_D800 5 | ||
133 | #define HPMEM_E000 6 | ||
134 | #define HPMEM_E800 7 | ||
135 | |||
136 | #define HPIRQ_NONE 0 | ||
137 | #define HPIRQ_5 1 | ||
138 | #define HPIRQ_7 2 | ||
139 | #define HPIRQ_9 3 | ||
140 | #define HPIRQ_10 4 | ||
141 | #define HPIRQ_11 5 | ||
142 | #define HPIRQ_12 6 | ||
143 | #define HPIRQ_15 7 | ||
144 | |||
145 | #define HIMT_PLAY_DONE 0x00 | ||
146 | #define HIMT_RECORD_DONE 0x01 | ||
147 | #define HIMT_MIDI_EOS 0x02 | ||
148 | #define HIMT_MIDI_OUT 0x03 | ||
149 | |||
150 | #define HIMT_MIDI_IN_UCHAR 0x0E | ||
151 | #define HIMT_DSP 0x0F | ||
152 | |||
153 | #define HDEX_BASE 0x92 | ||
154 | #define HDEX_PLAY_START (0 + HDEX_BASE) | ||
155 | #define HDEX_PLAY_STOP (1 + HDEX_BASE) | ||
156 | #define HDEX_PLAY_PAUSE (2 + HDEX_BASE) | ||
157 | #define HDEX_PLAY_RESUME (3 + HDEX_BASE) | ||
158 | #define HDEX_RECORD_START (4 + HDEX_BASE) | ||
159 | #define HDEX_RECORD_STOP (5 + HDEX_BASE) | ||
160 | #define HDEX_MIDI_IN_START (6 + HDEX_BASE) | ||
161 | #define HDEX_MIDI_IN_STOP (7 + HDEX_BASE) | ||
162 | #define HDEX_MIDI_OUT_START (8 + HDEX_BASE) | ||
163 | #define HDEX_MIDI_OUT_STOP (9 + HDEX_BASE) | ||
164 | #define HDEX_AUX_REQ (10 + HDEX_BASE) | ||
165 | |||
166 | #define HDEXAR_CLEAR_PEAKS 1 | ||
167 | #define HDEXAR_IN_SET_POTS 2 | ||
168 | #define HDEXAR_AUX_SET_POTS 3 | ||
169 | #define HDEXAR_CAL_A_TO_D 4 | ||
170 | #define HDEXAR_RD_EXT_DSP_BITS 5 | ||
171 | |||
172 | /* Pinnacle only HDEXAR defs */ | ||
173 | #define HDEXAR_SET_ANA_IN 0 | ||
174 | #define HDEXAR_SET_SYNTH_IN 4 | ||
175 | #define HDEXAR_READ_DAT_IN 5 | ||
176 | #define HDEXAR_MIC_SET_POTS 6 | ||
177 | #define HDEXAR_SET_DAT_IN 7 | ||
178 | |||
179 | #define HDEXAR_SET_SYNTH_48 8 | ||
180 | #define HDEXAR_SET_SYNTH_44 9 | ||
181 | |||
182 | #define HIWORD(l) ((u16)((((u32)(l)) >> 16) & 0xFFFF)) | ||
183 | #define LOWORD(l) ((u16)(u32)(l)) | ||
184 | #define HIBYTE(w) ((u8)(((u16)(w) >> 8) & 0xFF)) | ||
185 | #define LOBYTE(w) ((u8)(w)) | ||
186 | #define MAKELONG(low, hi) ((long)(((u16)(low))|(((u32)((u16)(hi)))<<16))) | ||
187 | #define MAKEWORD(low, hi) ((u16)(((u8)(low))|(((u16)((u8)(hi)))<<8))) | ||
188 | |||
189 | #define PCTODSP_OFFSET(w) (u16)((w)/2) | ||
190 | #define PCTODSP_BASED(w) (u16)(((w)/2) + DSP_BASE_ADDR) | ||
191 | #define DSPTOPC_BASED(w) (((w) - DSP_BASE_ADDR) * 2) | ||
192 | |||
193 | #ifdef SLOWIO | ||
194 | # undef outb | ||
195 | # undef inb | ||
196 | # define outb outb_p | ||
197 | # define inb inb_p | ||
198 | #endif | ||
199 | |||
200 | /* JobQueueStruct */ | ||
201 | #define JQS_wStart 0x00 | ||
202 | #define JQS_wSize 0x02 | ||
203 | #define JQS_wHead 0x04 | ||
204 | #define JQS_wTail 0x06 | ||
205 | #define JQS__size 0x08 | ||
206 | |||
207 | /* DAQueueDataStruct */ | ||
208 | #define DAQDS_wStart 0x00 | ||
209 | #define DAQDS_wSize 0x02 | ||
210 | #define DAQDS_wFormat 0x04 | ||
211 | #define DAQDS_wSampleSize 0x06 | ||
212 | #define DAQDS_wChannels 0x08 | ||
213 | #define DAQDS_wSampleRate 0x0A | ||
214 | #define DAQDS_wIntMsg 0x0C | ||
215 | #define DAQDS_wFlags 0x0E | ||
216 | #define DAQDS__size 0x10 | ||
217 | |||
218 | #include <sound/pcm.h> | ||
219 | |||
220 | struct snd_msnd { | ||
221 | void __iomem *mappedbase; | ||
222 | int play_period_bytes; | ||
223 | int playLimit; | ||
224 | int playPeriods; | ||
225 | int playDMAPos; | ||
226 | int banksPlayed; | ||
227 | int captureDMAPos; | ||
228 | int capturePeriodBytes; | ||
229 | int captureLimit; | ||
230 | int capturePeriods; | ||
231 | struct snd_card *card; | ||
232 | void *msndmidi_mpu; | ||
233 | struct snd_rawmidi *rmidi; | ||
234 | |||
235 | /* Hardware resources */ | ||
236 | long io; | ||
237 | int memid, irqid; | ||
238 | int irq, irq_ref; | ||
239 | unsigned long base; | ||
240 | |||
241 | /* Motorola 56k DSP SMA */ | ||
242 | void __iomem *SMA; | ||
243 | void __iomem *DAPQ; | ||
244 | void __iomem *DARQ; | ||
245 | void __iomem *MODQ; | ||
246 | void __iomem *MIDQ; | ||
247 | void __iomem *DSPQ; | ||
248 | int dspq_data_buff, dspq_buff_size; | ||
249 | |||
250 | /* State variables */ | ||
251 | enum { msndClassic, msndPinnacle } type; | ||
252 | mode_t mode; | ||
253 | unsigned long flags; | ||
254 | #define F_RESETTING 0 | ||
255 | #define F_HAVEDIGITAL 1 | ||
256 | #define F_AUDIO_WRITE_INUSE 2 | ||
257 | #define F_WRITING 3 | ||
258 | #define F_WRITEBLOCK 4 | ||
259 | #define F_WRITEFLUSH 5 | ||
260 | #define F_AUDIO_READ_INUSE 6 | ||
261 | #define F_READING 7 | ||
262 | #define F_READBLOCK 8 | ||
263 | #define F_EXT_MIDI_INUSE 9 | ||
264 | #define F_HDR_MIDI_INUSE 10 | ||
265 | #define F_DISABLE_WRITE_NDELAY 11 | ||
266 | spinlock_t lock; | ||
267 | spinlock_t mixer_lock; | ||
268 | int nresets; | ||
269 | unsigned recsrc; | ||
270 | #define LEVEL_ENTRIES 32 | ||
271 | int left_levels[LEVEL_ENTRIES]; | ||
272 | int right_levels[LEVEL_ENTRIES]; | ||
273 | int calibrate_signal; | ||
274 | int play_sample_size, play_sample_rate, play_channels; | ||
275 | int play_ndelay; | ||
276 | int capture_sample_size, capture_sample_rate, capture_channels; | ||
277 | int capture_ndelay; | ||
278 | u8 bCurrentMidiPatch; | ||
279 | |||
280 | int last_playbank, last_recbank; | ||
281 | struct snd_pcm_substream *playback_substream; | ||
282 | struct snd_pcm_substream *capture_substream; | ||
283 | |||
284 | }; | ||
285 | |||
286 | void snd_msnd_init_queue(void *base, int start, int size); | ||
287 | |||
288 | int snd_msnd_send_dsp_cmd(struct snd_msnd *chip, u8 cmd); | ||
289 | int snd_msnd_send_word(struct snd_msnd *chip, | ||
290 | unsigned char high, | ||
291 | unsigned char mid, | ||
292 | unsigned char low); | ||
293 | int snd_msnd_upload_host(struct snd_msnd *chip, | ||
294 | const u8 *bin, int len); | ||
295 | int snd_msnd_enable_irq(struct snd_msnd *chip); | ||
296 | int snd_msnd_disable_irq(struct snd_msnd *chip); | ||
297 | void snd_msnd_dsp_halt(struct snd_msnd *chip, struct file *file); | ||
298 | int snd_msnd_DAPQ(struct snd_msnd *chip, int start); | ||
299 | int snd_msnd_DARQ(struct snd_msnd *chip, int start); | ||
300 | int snd_msnd_pcm(struct snd_card *card, int device, struct snd_pcm **rpcm); | ||
301 | |||
302 | int snd_msndmidi_new(struct snd_card *card, int device); | ||
303 | void snd_msndmidi_input_read(void *mpu); | ||
304 | |||
305 | void snd_msndmix_setup(struct snd_msnd *chip); | ||
306 | int __devinit snd_msndmix_new(struct snd_card *card); | ||
307 | int snd_msndmix_force_recsrc(struct snd_msnd *chip, int recsrc); | ||
308 | #endif /* __MSND_H */ | ||
diff --git a/sound/isa/msnd/msnd_classic.c b/sound/isa/msnd/msnd_classic.c new file mode 100644 index 000000000000..3b23a096fa4e --- /dev/null +++ b/sound/isa/msnd/msnd_classic.c | |||
@@ -0,0 +1,3 @@ | |||
1 | /* The work is in msnd_pinnacle.c, just define MSND_CLASSIC before it. */ | ||
2 | #define MSND_CLASSIC | ||
3 | #include "msnd_pinnacle.c" | ||
diff --git a/sound/isa/msnd/msnd_classic.h b/sound/isa/msnd/msnd_classic.h new file mode 100644 index 000000000000..f18d5fa5baf4 --- /dev/null +++ b/sound/isa/msnd/msnd_classic.h | |||
@@ -0,0 +1,129 @@ | |||
1 | /********************************************************************* | ||
2 | * | ||
3 | * msnd_classic.h | ||
4 | * | ||
5 | * Turtle Beach MultiSound Sound Card Driver for Linux | ||
6 | * | ||
7 | * Some parts of this header file were derived from the Turtle Beach | ||
8 | * MultiSound Driver Development Kit. | ||
9 | * | ||
10 | * Copyright (C) 1998 Andrew Veliath | ||
11 | * Copyright (C) 1993 Turtle Beach Systems, Inc. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | * | ||
27 | ********************************************************************/ | ||
28 | #ifndef __MSND_CLASSIC_H | ||
29 | #define __MSND_CLASSIC_H | ||
30 | |||
31 | #define DSP_NUMIO 0x10 | ||
32 | |||
33 | #define HP_MEMM 0x08 | ||
34 | |||
35 | #define HP_BITM 0x0E | ||
36 | #define HP_WAIT 0x0D | ||
37 | #define HP_DSPR 0x0A | ||
38 | #define HP_PROR 0x0B | ||
39 | #define HP_BLKS 0x0C | ||
40 | |||
41 | #define HPPRORESET_OFF 0 | ||
42 | #define HPPRORESET_ON 1 | ||
43 | |||
44 | #define HPDSPRESET_OFF 0 | ||
45 | #define HPDSPRESET_ON 1 | ||
46 | |||
47 | #define HPBLKSEL_0 0 | ||
48 | #define HPBLKSEL_1 1 | ||
49 | |||
50 | #define HPWAITSTATE_0 0 | ||
51 | #define HPWAITSTATE_1 1 | ||
52 | |||
53 | #define HPBITMODE_16 0 | ||
54 | #define HPBITMODE_8 1 | ||
55 | |||
56 | #define HIDSP_INT_PLAY_UNDER 0x00 | ||
57 | #define HIDSP_INT_RECORD_OVER 0x01 | ||
58 | #define HIDSP_INPUT_CLIPPING 0x02 | ||
59 | #define HIDSP_MIDI_IN_OVER 0x10 | ||
60 | #define HIDSP_MIDI_OVERRUN_ERR 0x13 | ||
61 | |||
62 | #define TIME_PRO_RESET_DONE 0x028A | ||
63 | #define TIME_PRO_SYSEX 0x0040 | ||
64 | #define TIME_PRO_RESET 0x0032 | ||
65 | |||
66 | #define DAR_BUFF_SIZE 0x2000 | ||
67 | |||
68 | #define MIDQ_BUFF_SIZE 0x200 | ||
69 | #define DSPQ_BUFF_SIZE 0x40 | ||
70 | |||
71 | #define DSPQ_DATA_BUFF 0x7260 | ||
72 | |||
73 | #define MOP_SYNTH 0x10 | ||
74 | #define MOP_EXTOUT 0x32 | ||
75 | #define MOP_EXTTHRU 0x02 | ||
76 | #define MOP_OUTMASK 0x01 | ||
77 | |||
78 | #define MIP_EXTIN 0x01 | ||
79 | #define MIP_SYNTH 0x00 | ||
80 | #define MIP_INMASK 0x32 | ||
81 | |||
82 | /* Classic SMA Common Data */ | ||
83 | #define SMA_wCurrPlayBytes 0x0000 | ||
84 | #define SMA_wCurrRecordBytes 0x0002 | ||
85 | #define SMA_wCurrPlayVolLeft 0x0004 | ||
86 | #define SMA_wCurrPlayVolRight 0x0006 | ||
87 | #define SMA_wCurrInVolLeft 0x0008 | ||
88 | #define SMA_wCurrInVolRight 0x000a | ||
89 | #define SMA_wUser_3 0x000c | ||
90 | #define SMA_wUser_4 0x000e | ||
91 | #define SMA_dwUser_5 0x0010 | ||
92 | #define SMA_dwUser_6 0x0014 | ||
93 | #define SMA_wUser_7 0x0018 | ||
94 | #define SMA_wReserved_A 0x001a | ||
95 | #define SMA_wReserved_B 0x001c | ||
96 | #define SMA_wReserved_C 0x001e | ||
97 | #define SMA_wReserved_D 0x0020 | ||
98 | #define SMA_wReserved_E 0x0022 | ||
99 | #define SMA_wReserved_F 0x0024 | ||
100 | #define SMA_wReserved_G 0x0026 | ||
101 | #define SMA_wReserved_H 0x0028 | ||
102 | #define SMA_wCurrDSPStatusFlags 0x002a | ||
103 | #define SMA_wCurrHostStatusFlags 0x002c | ||
104 | #define SMA_wCurrInputTagBits 0x002e | ||
105 | #define SMA_wCurrLeftPeak 0x0030 | ||
106 | #define SMA_wCurrRightPeak 0x0032 | ||
107 | #define SMA_wExtDSPbits 0x0034 | ||
108 | #define SMA_bExtHostbits 0x0036 | ||
109 | #define SMA_bBoardLevel 0x0037 | ||
110 | #define SMA_bInPotPosRight 0x0038 | ||
111 | #define SMA_bInPotPosLeft 0x0039 | ||
112 | #define SMA_bAuxPotPosRight 0x003a | ||
113 | #define SMA_bAuxPotPosLeft 0x003b | ||
114 | #define SMA_wCurrMastVolLeft 0x003c | ||
115 | #define SMA_wCurrMastVolRight 0x003e | ||
116 | #define SMA_bUser_12 0x0040 | ||
117 | #define SMA_bUser_13 0x0041 | ||
118 | #define SMA_wUser_14 0x0042 | ||
119 | #define SMA_wUser_15 0x0044 | ||
120 | #define SMA_wCalFreqAtoD 0x0046 | ||
121 | #define SMA_wUser_16 0x0048 | ||
122 | #define SMA_wUser_17 0x004a | ||
123 | #define SMA__size 0x004c | ||
124 | |||
125 | #define INITCODEFILE "turtlebeach/msndinit.bin" | ||
126 | #define PERMCODEFILE "turtlebeach/msndperm.bin" | ||
127 | #define LONGNAME "MultiSound (Classic/Monterey/Tahiti)" | ||
128 | |||
129 | #endif /* __MSND_CLASSIC_H */ | ||
diff --git a/sound/isa/msnd/msnd_midi.c b/sound/isa/msnd/msnd_midi.c new file mode 100644 index 000000000000..cb9aa4c4edd0 --- /dev/null +++ b/sound/isa/msnd/msnd_midi.c | |||
@@ -0,0 +1,180 @@ | |||
1 | /* | ||
2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> | ||
3 | * Copyright (c) 2009 by Krzysztof Helt | ||
4 | * Routines for control of MPU-401 in UART mode | ||
5 | * | ||
6 | * MPU-401 supports UART mode which is not capable generate transmit | ||
7 | * interrupts thus output is done via polling. Also, if irq < 0, then | ||
8 | * input is done also via polling. Do not expect good performance. | ||
9 | * | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | #include <linux/io.h> | ||
28 | #include <linux/delay.h> | ||
29 | #include <linux/ioport.h> | ||
30 | #include <linux/errno.h> | ||
31 | #include <sound/core.h> | ||
32 | #include <sound/rawmidi.h> | ||
33 | |||
34 | #include "msnd.h" | ||
35 | |||
36 | #define MSNDMIDI_MODE_BIT_INPUT 0 | ||
37 | #define MSNDMIDI_MODE_BIT_OUTPUT 1 | ||
38 | #define MSNDMIDI_MODE_BIT_INPUT_TRIGGER 2 | ||
39 | #define MSNDMIDI_MODE_BIT_OUTPUT_TRIGGER 3 | ||
40 | |||
41 | struct snd_msndmidi { | ||
42 | struct snd_msnd *dev; | ||
43 | |||
44 | unsigned long mode; /* MSNDMIDI_MODE_XXXX */ | ||
45 | |||
46 | struct snd_rawmidi_substream *substream_input; | ||
47 | |||
48 | spinlock_t input_lock; | ||
49 | }; | ||
50 | |||
51 | /* | ||
52 | * input/output open/close - protected by open_mutex in rawmidi.c | ||
53 | */ | ||
54 | static int snd_msndmidi_input_open(struct snd_rawmidi_substream *substream) | ||
55 | { | ||
56 | struct snd_msndmidi *mpu; | ||
57 | |||
58 | snd_printdd("snd_msndmidi_input_open()\n"); | ||
59 | |||
60 | mpu = substream->rmidi->private_data; | ||
61 | |||
62 | mpu->substream_input = substream; | ||
63 | |||
64 | snd_msnd_enable_irq(mpu->dev); | ||
65 | |||
66 | snd_msnd_send_dsp_cmd(mpu->dev, HDEX_MIDI_IN_START); | ||
67 | set_bit(MSNDMIDI_MODE_BIT_INPUT, &mpu->mode); | ||
68 | return 0; | ||
69 | } | ||
70 | |||
71 | static int snd_msndmidi_input_close(struct snd_rawmidi_substream *substream) | ||
72 | { | ||
73 | struct snd_msndmidi *mpu; | ||
74 | |||
75 | mpu = substream->rmidi->private_data; | ||
76 | snd_msnd_send_dsp_cmd(mpu->dev, HDEX_MIDI_IN_STOP); | ||
77 | clear_bit(MSNDMIDI_MODE_BIT_INPUT, &mpu->mode); | ||
78 | mpu->substream_input = NULL; | ||
79 | snd_msnd_disable_irq(mpu->dev); | ||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | static void snd_msndmidi_input_drop(struct snd_msndmidi *mpu) | ||
84 | { | ||
85 | u16 tail; | ||
86 | |||
87 | tail = readw(mpu->dev->MIDQ + JQS_wTail); | ||
88 | writew(tail, mpu->dev->MIDQ + JQS_wHead); | ||
89 | } | ||
90 | |||
91 | /* | ||
92 | * trigger input | ||
93 | */ | ||
94 | static void snd_msndmidi_input_trigger(struct snd_rawmidi_substream *substream, | ||
95 | int up) | ||
96 | { | ||
97 | unsigned long flags; | ||
98 | struct snd_msndmidi *mpu; | ||
99 | |||
100 | snd_printdd("snd_msndmidi_input_trigger(, %i)\n", up); | ||
101 | |||
102 | mpu = substream->rmidi->private_data; | ||
103 | spin_lock_irqsave(&mpu->input_lock, flags); | ||
104 | if (up) { | ||
105 | if (!test_and_set_bit(MSNDMIDI_MODE_BIT_INPUT_TRIGGER, | ||
106 | &mpu->mode)) | ||
107 | snd_msndmidi_input_drop(mpu); | ||
108 | } else { | ||
109 | clear_bit(MSNDMIDI_MODE_BIT_INPUT_TRIGGER, &mpu->mode); | ||
110 | } | ||
111 | spin_unlock_irqrestore(&mpu->input_lock, flags); | ||
112 | if (up) | ||
113 | snd_msndmidi_input_read(mpu); | ||
114 | } | ||
115 | |||
116 | void snd_msndmidi_input_read(void *mpuv) | ||
117 | { | ||
118 | unsigned long flags; | ||
119 | struct snd_msndmidi *mpu = mpuv; | ||
120 | void *pwMIDQData = mpu->dev->mappedbase + MIDQ_DATA_BUFF; | ||
121 | |||
122 | spin_lock_irqsave(&mpu->input_lock, flags); | ||
123 | while (readw(mpu->dev->MIDQ + JQS_wTail) != | ||
124 | readw(mpu->dev->MIDQ + JQS_wHead)) { | ||
125 | u16 wTmp, val; | ||
126 | val = readw(pwMIDQData + 2 * readw(mpu->dev->MIDQ + JQS_wHead)); | ||
127 | |||
128 | if (test_bit(MSNDMIDI_MODE_BIT_INPUT_TRIGGER, | ||
129 | &mpu->mode)) | ||
130 | snd_rawmidi_receive(mpu->substream_input, | ||
131 | (unsigned char *)&val, 1); | ||
132 | |||
133 | wTmp = readw(mpu->dev->MIDQ + JQS_wHead) + 1; | ||
134 | if (wTmp > readw(mpu->dev->MIDQ + JQS_wSize)) | ||
135 | writew(0, mpu->dev->MIDQ + JQS_wHead); | ||
136 | else | ||
137 | writew(wTmp, mpu->dev->MIDQ + JQS_wHead); | ||
138 | } | ||
139 | spin_unlock_irqrestore(&mpu->input_lock, flags); | ||
140 | } | ||
141 | EXPORT_SYMBOL(snd_msndmidi_input_read); | ||
142 | |||
143 | static struct snd_rawmidi_ops snd_msndmidi_input = { | ||
144 | .open = snd_msndmidi_input_open, | ||
145 | .close = snd_msndmidi_input_close, | ||
146 | .trigger = snd_msndmidi_input_trigger, | ||
147 | }; | ||
148 | |||
149 | static void snd_msndmidi_free(struct snd_rawmidi *rmidi) | ||
150 | { | ||
151 | struct snd_msndmidi *mpu = rmidi->private_data; | ||
152 | kfree(mpu); | ||
153 | } | ||
154 | |||
155 | int snd_msndmidi_new(struct snd_card *card, int device) | ||
156 | { | ||
157 | struct snd_msnd *chip = card->private_data; | ||
158 | struct snd_msndmidi *mpu; | ||
159 | struct snd_rawmidi *rmidi; | ||
160 | int err; | ||
161 | |||
162 | err = snd_rawmidi_new(card, "MSND-MIDI", device, 1, 1, &rmidi); | ||
163 | if (err < 0) | ||
164 | return err; | ||
165 | mpu = kcalloc(1, sizeof(*mpu), GFP_KERNEL); | ||
166 | if (mpu == NULL) { | ||
167 | snd_device_free(card, rmidi); | ||
168 | return -ENOMEM; | ||
169 | } | ||
170 | mpu->dev = chip; | ||
171 | chip->msndmidi_mpu = mpu; | ||
172 | rmidi->private_data = mpu; | ||
173 | rmidi->private_free = snd_msndmidi_free; | ||
174 | spin_lock_init(&mpu->input_lock); | ||
175 | strcpy(rmidi->name, "MSND MIDI"); | ||
176 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, | ||
177 | &snd_msndmidi_input); | ||
178 | rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT; | ||
179 | return 0; | ||
180 | } | ||
diff --git a/sound/isa/msnd/msnd_pinnacle.c b/sound/isa/msnd/msnd_pinnacle.c new file mode 100644 index 000000000000..60b6abd71612 --- /dev/null +++ b/sound/isa/msnd/msnd_pinnacle.c | |||
@@ -0,0 +1,1238 @@ | |||
1 | /********************************************************************* | ||
2 | * | ||
3 | * Linux multisound pinnacle/fiji driver for ALSA. | ||
4 | * | ||
5 | * 2002/06/30 Karsten Wiese: | ||
6 | * for now this is only used to build a pinnacle / fiji driver. | ||
7 | * the OSS parent of this code is designed to also support | ||
8 | * the multisound classic via the file msnd_classic.c. | ||
9 | * to make it easier for some brave heart to implemt classic | ||
10 | * support in alsa, i left all the MSND_CLASSIC tokens in this file. | ||
11 | * but for now this untested & undone. | ||
12 | * | ||
13 | * | ||
14 | * ripped from linux kernel 2.4.18 by Karsten Wiese. | ||
15 | * | ||
16 | * the following is a copy of the 2.4.18 OSS FREE file-heading comment: | ||
17 | * | ||
18 | * Turtle Beach MultiSound Sound Card Driver for Linux | ||
19 | * msnd_pinnacle.c / msnd_classic.c | ||
20 | * | ||
21 | * -- If MSND_CLASSIC is defined: | ||
22 | * | ||
23 | * -> driver for Turtle Beach Classic/Monterey/Tahiti | ||
24 | * | ||
25 | * -- Else | ||
26 | * | ||
27 | * -> driver for Turtle Beach Pinnacle/Fiji | ||
28 | * | ||
29 | * 12-3-2000 Modified IO port validation Steve Sycamore | ||
30 | * | ||
31 | * Copyright (C) 1998 Andrew Veliath | ||
32 | * | ||
33 | * This program is free software; you can redistribute it and/or modify | ||
34 | * it under the terms of the GNU General Public License as published by | ||
35 | * the Free Software Foundation; either version 2 of the License, or | ||
36 | * (at your option) any later version. | ||
37 | * | ||
38 | * This program is distributed in the hope that it will be useful, | ||
39 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
40 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
41 | * GNU General Public License for more details. | ||
42 | * | ||
43 | * You should have received a copy of the GNU General Public License | ||
44 | * along with this program; if not, write to the Free Software | ||
45 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
46 | * | ||
47 | ********************************************************************/ | ||
48 | |||
49 | #include <linux/kernel.h> | ||
50 | #include <linux/module.h> | ||
51 | #include <linux/interrupt.h> | ||
52 | #include <linux/types.h> | ||
53 | #include <linux/delay.h> | ||
54 | #include <linux/ioport.h> | ||
55 | #include <linux/firmware.h> | ||
56 | #include <linux/isa.h> | ||
57 | #include <linux/isapnp.h> | ||
58 | #include <linux/irq.h> | ||
59 | #include <linux/io.h> | ||
60 | |||
61 | #include <sound/core.h> | ||
62 | #include <sound/initval.h> | ||
63 | #include <sound/asound.h> | ||
64 | #include <sound/pcm.h> | ||
65 | #include <sound/mpu401.h> | ||
66 | |||
67 | #ifdef MSND_CLASSIC | ||
68 | # ifndef __alpha__ | ||
69 | # define SLOWIO | ||
70 | # endif | ||
71 | #endif | ||
72 | #include "msnd.h" | ||
73 | #ifdef MSND_CLASSIC | ||
74 | # include "msnd_classic.h" | ||
75 | # define LOGNAME "msnd_classic" | ||
76 | #else | ||
77 | # include "msnd_pinnacle.h" | ||
78 | # define LOGNAME "snd_msnd_pinnacle" | ||
79 | #endif | ||
80 | |||
81 | static void __devinit set_default_audio_parameters(struct snd_msnd *chip) | ||
82 | { | ||
83 | chip->play_sample_size = DEFSAMPLESIZE; | ||
84 | chip->play_sample_rate = DEFSAMPLERATE; | ||
85 | chip->play_channels = DEFCHANNELS; | ||
86 | chip->capture_sample_size = DEFSAMPLESIZE; | ||
87 | chip->capture_sample_rate = DEFSAMPLERATE; | ||
88 | chip->capture_channels = DEFCHANNELS; | ||
89 | } | ||
90 | |||
91 | static void snd_msnd_eval_dsp_msg(struct snd_msnd *chip, u16 wMessage) | ||
92 | { | ||
93 | switch (HIBYTE(wMessage)) { | ||
94 | case HIMT_PLAY_DONE: { | ||
95 | if (chip->banksPlayed < 3) | ||
96 | snd_printdd("%08X: HIMT_PLAY_DONE: %i\n", | ||
97 | (unsigned)jiffies, LOBYTE(wMessage)); | ||
98 | |||
99 | if (chip->last_playbank == LOBYTE(wMessage)) { | ||
100 | snd_printdd("chip.last_playbank == LOBYTE(wMessage)\n"); | ||
101 | break; | ||
102 | } | ||
103 | chip->banksPlayed++; | ||
104 | |||
105 | if (test_bit(F_WRITING, &chip->flags)) | ||
106 | snd_msnd_DAPQ(chip, 0); | ||
107 | |||
108 | chip->last_playbank = LOBYTE(wMessage); | ||
109 | chip->playDMAPos += chip->play_period_bytes; | ||
110 | if (chip->playDMAPos > chip->playLimit) | ||
111 | chip->playDMAPos = 0; | ||
112 | snd_pcm_period_elapsed(chip->playback_substream); | ||
113 | |||
114 | break; | ||
115 | } | ||
116 | case HIMT_RECORD_DONE: | ||
117 | if (chip->last_recbank == LOBYTE(wMessage)) | ||
118 | break; | ||
119 | chip->last_recbank = LOBYTE(wMessage); | ||
120 | chip->captureDMAPos += chip->capturePeriodBytes; | ||
121 | if (chip->captureDMAPos > (chip->captureLimit)) | ||
122 | chip->captureDMAPos = 0; | ||
123 | |||
124 | if (test_bit(F_READING, &chip->flags)) | ||
125 | snd_msnd_DARQ(chip, chip->last_recbank); | ||
126 | |||
127 | snd_pcm_period_elapsed(chip->capture_substream); | ||
128 | break; | ||
129 | |||
130 | case HIMT_DSP: | ||
131 | switch (LOBYTE(wMessage)) { | ||
132 | #ifndef MSND_CLASSIC | ||
133 | case HIDSP_PLAY_UNDER: | ||
134 | #endif | ||
135 | case HIDSP_INT_PLAY_UNDER: | ||
136 | snd_printd(KERN_WARNING LOGNAME ": Play underflow %i\n", | ||
137 | chip->banksPlayed); | ||
138 | if (chip->banksPlayed > 2) | ||
139 | clear_bit(F_WRITING, &chip->flags); | ||
140 | break; | ||
141 | |||
142 | case HIDSP_INT_RECORD_OVER: | ||
143 | snd_printd(KERN_WARNING LOGNAME ": Record overflow\n"); | ||
144 | clear_bit(F_READING, &chip->flags); | ||
145 | break; | ||
146 | |||
147 | default: | ||
148 | snd_printd(KERN_WARNING LOGNAME | ||
149 | ": DSP message %d 0x%02x\n", | ||
150 | LOBYTE(wMessage), LOBYTE(wMessage)); | ||
151 | break; | ||
152 | } | ||
153 | break; | ||
154 | |||
155 | case HIMT_MIDI_IN_UCHAR: | ||
156 | if (chip->msndmidi_mpu) | ||
157 | snd_msndmidi_input_read(chip->msndmidi_mpu); | ||
158 | break; | ||
159 | |||
160 | default: | ||
161 | snd_printd(KERN_WARNING LOGNAME ": HIMT message %d 0x%02x\n", | ||
162 | HIBYTE(wMessage), HIBYTE(wMessage)); | ||
163 | break; | ||
164 | } | ||
165 | } | ||
166 | |||
167 | static irqreturn_t snd_msnd_interrupt(int irq, void *dev_id) | ||
168 | { | ||
169 | struct snd_msnd *chip = dev_id; | ||
170 | void *pwDSPQData = chip->mappedbase + DSPQ_DATA_BUFF; | ||
171 | |||
172 | /* Send ack to DSP */ | ||
173 | /* inb(chip->io + HP_RXL); */ | ||
174 | |||
175 | /* Evaluate queued DSP messages */ | ||
176 | while (readw(chip->DSPQ + JQS_wTail) != readw(chip->DSPQ + JQS_wHead)) { | ||
177 | u16 wTmp; | ||
178 | |||
179 | snd_msnd_eval_dsp_msg(chip, | ||
180 | readw(pwDSPQData + 2 * readw(chip->DSPQ + JQS_wHead))); | ||
181 | |||
182 | wTmp = readw(chip->DSPQ + JQS_wHead) + 1; | ||
183 | if (wTmp > readw(chip->DSPQ + JQS_wSize)) | ||
184 | writew(0, chip->DSPQ + JQS_wHead); | ||
185 | else | ||
186 | writew(wTmp, chip->DSPQ + JQS_wHead); | ||
187 | } | ||
188 | /* Send ack to DSP */ | ||
189 | inb(chip->io + HP_RXL); | ||
190 | return IRQ_HANDLED; | ||
191 | } | ||
192 | |||
193 | |||
194 | static int snd_msnd_reset_dsp(long io, unsigned char *info) | ||
195 | { | ||
196 | int timeout = 100; | ||
197 | |||
198 | outb(HPDSPRESET_ON, io + HP_DSPR); | ||
199 | msleep(1); | ||
200 | #ifndef MSND_CLASSIC | ||
201 | if (info) | ||
202 | *info = inb(io + HP_INFO); | ||
203 | #endif | ||
204 | outb(HPDSPRESET_OFF, io + HP_DSPR); | ||
205 | msleep(1); | ||
206 | while (timeout-- > 0) { | ||
207 | if (inb(io + HP_CVR) == HP_CVR_DEF) | ||
208 | return 0; | ||
209 | msleep(1); | ||
210 | } | ||
211 | snd_printk(KERN_ERR LOGNAME ": Cannot reset DSP\n"); | ||
212 | |||
213 | return -EIO; | ||
214 | } | ||
215 | |||
216 | static int __devinit snd_msnd_probe(struct snd_card *card) | ||
217 | { | ||
218 | struct snd_msnd *chip = card->private_data; | ||
219 | unsigned char info; | ||
220 | #ifndef MSND_CLASSIC | ||
221 | char *xv, *rev = NULL; | ||
222 | char *pin = "TB Pinnacle", *fiji = "TB Fiji"; | ||
223 | char *pinfiji = "TB Pinnacle/Fiji"; | ||
224 | #endif | ||
225 | |||
226 | if (!request_region(chip->io, DSP_NUMIO, "probing")) { | ||
227 | snd_printk(KERN_ERR LOGNAME ": I/O port conflict\n"); | ||
228 | return -ENODEV; | ||
229 | } | ||
230 | |||
231 | if (snd_msnd_reset_dsp(chip->io, &info) < 0) { | ||
232 | release_region(chip->io, DSP_NUMIO); | ||
233 | return -ENODEV; | ||
234 | } | ||
235 | |||
236 | #ifdef MSND_CLASSIC | ||
237 | strcpy(card->shortname, "Classic/Tahiti/Monterey"); | ||
238 | strcpy(card->longname, "Turtle Beach Multisound"); | ||
239 | printk(KERN_INFO LOGNAME ": %s, " | ||
240 | "I/O 0x%lx-0x%lx, IRQ %d, memory mapped to 0x%lX-0x%lX\n", | ||
241 | card->shortname, | ||
242 | chip->io, chip->io + DSP_NUMIO - 1, | ||
243 | chip->irq, | ||
244 | chip->base, chip->base + 0x7fff); | ||
245 | #else | ||
246 | switch (info >> 4) { | ||
247 | case 0xf: | ||
248 | xv = "<= 1.15"; | ||
249 | break; | ||
250 | case 0x1: | ||
251 | xv = "1.18/1.2"; | ||
252 | break; | ||
253 | case 0x2: | ||
254 | xv = "1.3"; | ||
255 | break; | ||
256 | case 0x3: | ||
257 | xv = "1.4"; | ||
258 | break; | ||
259 | default: | ||
260 | xv = "unknown"; | ||
261 | break; | ||
262 | } | ||
263 | |||
264 | switch (info & 0x7) { | ||
265 | case 0x0: | ||
266 | rev = "I"; | ||
267 | strcpy(card->shortname, pin); | ||
268 | break; | ||
269 | case 0x1: | ||
270 | rev = "F"; | ||
271 | strcpy(card->shortname, pin); | ||
272 | break; | ||
273 | case 0x2: | ||
274 | rev = "G"; | ||
275 | strcpy(card->shortname, pin); | ||
276 | break; | ||
277 | case 0x3: | ||
278 | rev = "H"; | ||
279 | strcpy(card->shortname, pin); | ||
280 | break; | ||
281 | case 0x4: | ||
282 | rev = "E"; | ||
283 | strcpy(card->shortname, fiji); | ||
284 | break; | ||
285 | case 0x5: | ||
286 | rev = "C"; | ||
287 | strcpy(card->shortname, fiji); | ||
288 | break; | ||
289 | case 0x6: | ||
290 | rev = "D"; | ||
291 | strcpy(card->shortname, fiji); | ||
292 | break; | ||
293 | case 0x7: | ||
294 | rev = "A-B (Fiji) or A-E (Pinnacle)"; | ||
295 | strcpy(card->shortname, pinfiji); | ||
296 | break; | ||
297 | } | ||
298 | strcpy(card->longname, "Turtle Beach Multisound Pinnacle"); | ||
299 | printk(KERN_INFO LOGNAME ": %s revision %s, Xilinx version %s, " | ||
300 | "I/O 0x%lx-0x%lx, IRQ %d, memory mapped to 0x%lX-0x%lX\n", | ||
301 | card->shortname, | ||
302 | rev, xv, | ||
303 | chip->io, chip->io + DSP_NUMIO - 1, | ||
304 | chip->irq, | ||
305 | chip->base, chip->base + 0x7fff); | ||
306 | #endif | ||
307 | |||
308 | release_region(chip->io, DSP_NUMIO); | ||
309 | return 0; | ||
310 | } | ||
311 | |||
312 | static int snd_msnd_init_sma(struct snd_msnd *chip) | ||
313 | { | ||
314 | static int initted; | ||
315 | u16 mastVolLeft, mastVolRight; | ||
316 | unsigned long flags; | ||
317 | |||
318 | #ifdef MSND_CLASSIC | ||
319 | outb(chip->memid, chip->io + HP_MEMM); | ||
320 | #endif | ||
321 | outb(HPBLKSEL_0, chip->io + HP_BLKS); | ||
322 | /* Motorola 56k shared memory base */ | ||
323 | chip->SMA = chip->mappedbase + SMA_STRUCT_START; | ||
324 | |||
325 | if (initted) { | ||
326 | mastVolLeft = readw(chip->SMA + SMA_wCurrMastVolLeft); | ||
327 | mastVolRight = readw(chip->SMA + SMA_wCurrMastVolRight); | ||
328 | } else | ||
329 | mastVolLeft = mastVolRight = 0; | ||
330 | memset_io(chip->mappedbase, 0, 0x8000); | ||
331 | |||
332 | /* Critical section: bank 1 access */ | ||
333 | spin_lock_irqsave(&chip->lock, flags); | ||
334 | outb(HPBLKSEL_1, chip->io + HP_BLKS); | ||
335 | memset_io(chip->mappedbase, 0, 0x8000); | ||
336 | outb(HPBLKSEL_0, chip->io + HP_BLKS); | ||
337 | spin_unlock_irqrestore(&chip->lock, flags); | ||
338 | |||
339 | /* Digital audio play queue */ | ||
340 | chip->DAPQ = chip->mappedbase + DAPQ_OFFSET; | ||
341 | snd_msnd_init_queue(chip->DAPQ, DAPQ_DATA_BUFF, DAPQ_BUFF_SIZE); | ||
342 | |||
343 | /* Digital audio record queue */ | ||
344 | chip->DARQ = chip->mappedbase + DARQ_OFFSET; | ||
345 | snd_msnd_init_queue(chip->DARQ, DARQ_DATA_BUFF, DARQ_BUFF_SIZE); | ||
346 | |||
347 | /* MIDI out queue */ | ||
348 | chip->MODQ = chip->mappedbase + MODQ_OFFSET; | ||
349 | snd_msnd_init_queue(chip->MODQ, MODQ_DATA_BUFF, MODQ_BUFF_SIZE); | ||
350 | |||
351 | /* MIDI in queue */ | ||
352 | chip->MIDQ = chip->mappedbase + MIDQ_OFFSET; | ||
353 | snd_msnd_init_queue(chip->MIDQ, MIDQ_DATA_BUFF, MIDQ_BUFF_SIZE); | ||
354 | |||
355 | /* DSP -> host message queue */ | ||
356 | chip->DSPQ = chip->mappedbase + DSPQ_OFFSET; | ||
357 | snd_msnd_init_queue(chip->DSPQ, DSPQ_DATA_BUFF, DSPQ_BUFF_SIZE); | ||
358 | |||
359 | /* Setup some DSP values */ | ||
360 | #ifndef MSND_CLASSIC | ||
361 | writew(1, chip->SMA + SMA_wCurrPlayFormat); | ||
362 | writew(chip->play_sample_size, chip->SMA + SMA_wCurrPlaySampleSize); | ||
363 | writew(chip->play_channels, chip->SMA + SMA_wCurrPlayChannels); | ||
364 | writew(chip->play_sample_rate, chip->SMA + SMA_wCurrPlaySampleRate); | ||
365 | #endif | ||
366 | writew(chip->play_sample_rate, chip->SMA + SMA_wCalFreqAtoD); | ||
367 | writew(mastVolLeft, chip->SMA + SMA_wCurrMastVolLeft); | ||
368 | writew(mastVolRight, chip->SMA + SMA_wCurrMastVolRight); | ||
369 | #ifndef MSND_CLASSIC | ||
370 | writel(0x00010000, chip->SMA + SMA_dwCurrPlayPitch); | ||
371 | writel(0x00000001, chip->SMA + SMA_dwCurrPlayRate); | ||
372 | #endif | ||
373 | writew(0x303, chip->SMA + SMA_wCurrInputTagBits); | ||
374 | |||
375 | initted = 1; | ||
376 | |||
377 | return 0; | ||
378 | } | ||
379 | |||
380 | |||
381 | static int upload_dsp_code(struct snd_card *card) | ||
382 | { | ||
383 | struct snd_msnd *chip = card->private_data; | ||
384 | const struct firmware *init_fw = NULL, *perm_fw = NULL; | ||
385 | int err; | ||
386 | |||
387 | outb(HPBLKSEL_0, chip->io + HP_BLKS); | ||
388 | |||
389 | err = request_firmware(&init_fw, INITCODEFILE, card->dev); | ||
390 | if (err < 0) { | ||
391 | printk(KERN_ERR LOGNAME ": Error loading " INITCODEFILE); | ||
392 | goto cleanup1; | ||
393 | } | ||
394 | err = request_firmware(&perm_fw, PERMCODEFILE, card->dev); | ||
395 | if (err < 0) { | ||
396 | printk(KERN_ERR LOGNAME ": Error loading " PERMCODEFILE); | ||
397 | goto cleanup; | ||
398 | } | ||
399 | |||
400 | memcpy_toio(chip->mappedbase, perm_fw->data, perm_fw->size); | ||
401 | if (snd_msnd_upload_host(chip, init_fw->data, init_fw->size) < 0) { | ||
402 | printk(KERN_WARNING LOGNAME ": Error uploading to DSP\n"); | ||
403 | err = -ENODEV; | ||
404 | goto cleanup; | ||
405 | } | ||
406 | printk(KERN_INFO LOGNAME ": DSP firmware uploaded\n"); | ||
407 | err = 0; | ||
408 | |||
409 | cleanup: | ||
410 | release_firmware(perm_fw); | ||
411 | cleanup1: | ||
412 | release_firmware(init_fw); | ||
413 | return err; | ||
414 | } | ||
415 | |||
416 | #ifdef MSND_CLASSIC | ||
417 | static void reset_proteus(struct snd_msnd *chip) | ||
418 | { | ||
419 | outb(HPPRORESET_ON, chip->io + HP_PROR); | ||
420 | msleep(TIME_PRO_RESET); | ||
421 | outb(HPPRORESET_OFF, chip->io + HP_PROR); | ||
422 | msleep(TIME_PRO_RESET_DONE); | ||
423 | } | ||
424 | #endif | ||
425 | |||
426 | static int snd_msnd_initialize(struct snd_card *card) | ||
427 | { | ||
428 | struct snd_msnd *chip = card->private_data; | ||
429 | int err, timeout; | ||
430 | |||
431 | #ifdef MSND_CLASSIC | ||
432 | outb(HPWAITSTATE_0, chip->io + HP_WAIT); | ||
433 | outb(HPBITMODE_16, chip->io + HP_BITM); | ||
434 | |||
435 | reset_proteus(chip); | ||
436 | #endif | ||
437 | err = snd_msnd_init_sma(chip); | ||
438 | if (err < 0) { | ||
439 | printk(KERN_WARNING LOGNAME ": Cannot initialize SMA\n"); | ||
440 | return err; | ||
441 | } | ||
442 | |||
443 | err = snd_msnd_reset_dsp(chip->io, NULL); | ||
444 | if (err < 0) | ||
445 | return err; | ||
446 | |||
447 | err = upload_dsp_code(card); | ||
448 | if (err < 0) { | ||
449 | printk(KERN_WARNING LOGNAME ": Cannot upload DSP code\n"); | ||
450 | return err; | ||
451 | } | ||
452 | |||
453 | timeout = 200; | ||
454 | |||
455 | while (readw(chip->mappedbase)) { | ||
456 | msleep(1); | ||
457 | if (!timeout--) { | ||
458 | snd_printd(KERN_ERR LOGNAME ": DSP reset timeout\n"); | ||
459 | return -EIO; | ||
460 | } | ||
461 | } | ||
462 | |||
463 | snd_msndmix_setup(chip); | ||
464 | return 0; | ||
465 | } | ||
466 | |||
467 | static int snd_msnd_dsp_full_reset(struct snd_card *card) | ||
468 | { | ||
469 | struct snd_msnd *chip = card->private_data; | ||
470 | int rv; | ||
471 | |||
472 | if (test_bit(F_RESETTING, &chip->flags) || ++chip->nresets > 10) | ||
473 | return 0; | ||
474 | |||
475 | set_bit(F_RESETTING, &chip->flags); | ||
476 | snd_msnd_dsp_halt(chip, NULL); /* Unconditionally halt */ | ||
477 | |||
478 | rv = snd_msnd_initialize(card); | ||
479 | if (rv) | ||
480 | printk(KERN_WARNING LOGNAME ": DSP reset failed\n"); | ||
481 | snd_msndmix_force_recsrc(chip, 0); | ||
482 | clear_bit(F_RESETTING, &chip->flags); | ||
483 | return rv; | ||
484 | } | ||
485 | |||
486 | static int snd_msnd_dev_free(struct snd_device *device) | ||
487 | { | ||
488 | snd_printdd("snd_msnd_chip_free()\n"); | ||
489 | return 0; | ||
490 | } | ||
491 | |||
492 | static int snd_msnd_send_dsp_cmd_chk(struct snd_msnd *chip, u8 cmd) | ||
493 | { | ||
494 | if (snd_msnd_send_dsp_cmd(chip, cmd) == 0) | ||
495 | return 0; | ||
496 | snd_msnd_dsp_full_reset(chip->card); | ||
497 | return snd_msnd_send_dsp_cmd(chip, cmd); | ||
498 | } | ||
499 | |||
500 | static int __devinit snd_msnd_calibrate_adc(struct snd_msnd *chip, u16 srate) | ||
501 | { | ||
502 | snd_printdd("snd_msnd_calibrate_adc(%i)\n", srate); | ||
503 | writew(srate, chip->SMA + SMA_wCalFreqAtoD); | ||
504 | if (chip->calibrate_signal == 0) | ||
505 | writew(readw(chip->SMA + SMA_wCurrHostStatusFlags) | ||
506 | | 0x0001, chip->SMA + SMA_wCurrHostStatusFlags); | ||
507 | else | ||
508 | writew(readw(chip->SMA + SMA_wCurrHostStatusFlags) | ||
509 | & ~0x0001, chip->SMA + SMA_wCurrHostStatusFlags); | ||
510 | if (snd_msnd_send_word(chip, 0, 0, HDEXAR_CAL_A_TO_D) == 0 && | ||
511 | snd_msnd_send_dsp_cmd_chk(chip, HDEX_AUX_REQ) == 0) { | ||
512 | schedule_timeout_interruptible(msecs_to_jiffies(333)); | ||
513 | return 0; | ||
514 | } | ||
515 | printk(KERN_WARNING LOGNAME ": ADC calibration failed\n"); | ||
516 | return -EIO; | ||
517 | } | ||
518 | |||
519 | /* | ||
520 | * ALSA callback function, called when attempting to open the MIDI device. | ||
521 | */ | ||
522 | static int snd_msnd_mpu401_open(struct snd_mpu401 *mpu) | ||
523 | { | ||
524 | snd_msnd_enable_irq(mpu->private_data); | ||
525 | snd_msnd_send_dsp_cmd(mpu->private_data, HDEX_MIDI_IN_START); | ||
526 | return 0; | ||
527 | } | ||
528 | |||
529 | static void snd_msnd_mpu401_close(struct snd_mpu401 *mpu) | ||
530 | { | ||
531 | snd_msnd_send_dsp_cmd(mpu->private_data, HDEX_MIDI_IN_STOP); | ||
532 | snd_msnd_disable_irq(mpu->private_data); | ||
533 | } | ||
534 | |||
535 | static long mpu_io[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; | ||
536 | static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; | ||
537 | |||
538 | static int __devinit snd_msnd_attach(struct snd_card *card) | ||
539 | { | ||
540 | struct snd_msnd *chip = card->private_data; | ||
541 | int err; | ||
542 | static struct snd_device_ops ops = { | ||
543 | .dev_free = snd_msnd_dev_free, | ||
544 | }; | ||
545 | |||
546 | err = request_irq(chip->irq, snd_msnd_interrupt, 0, card->shortname, | ||
547 | chip); | ||
548 | if (err < 0) { | ||
549 | printk(KERN_ERR LOGNAME ": Couldn't grab IRQ %d\n", chip->irq); | ||
550 | return err; | ||
551 | } | ||
552 | request_region(chip->io, DSP_NUMIO, card->shortname); | ||
553 | |||
554 | if (!request_mem_region(chip->base, BUFFSIZE, card->shortname)) { | ||
555 | printk(KERN_ERR LOGNAME | ||
556 | ": unable to grab memory region 0x%lx-0x%lx\n", | ||
557 | chip->base, chip->base + BUFFSIZE - 1); | ||
558 | release_region(chip->io, DSP_NUMIO); | ||
559 | free_irq(chip->irq, chip); | ||
560 | return -EBUSY; | ||
561 | } | ||
562 | chip->mappedbase = ioremap_nocache(chip->base, 0x8000); | ||
563 | if (!chip->mappedbase) { | ||
564 | printk(KERN_ERR LOGNAME | ||
565 | ": unable to map memory region 0x%lx-0x%lx\n", | ||
566 | chip->base, chip->base + BUFFSIZE - 1); | ||
567 | err = -EIO; | ||
568 | goto err_release_region; | ||
569 | } | ||
570 | |||
571 | err = snd_msnd_dsp_full_reset(card); | ||
572 | if (err < 0) | ||
573 | goto err_release_region; | ||
574 | |||
575 | /* Register device */ | ||
576 | err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); | ||
577 | if (err < 0) | ||
578 | goto err_release_region; | ||
579 | |||
580 | err = snd_msnd_pcm(card, 0, NULL); | ||
581 | if (err < 0) { | ||
582 | printk(KERN_ERR LOGNAME ": error creating new PCM device\n"); | ||
583 | goto err_release_region; | ||
584 | } | ||
585 | |||
586 | err = snd_msndmix_new(card); | ||
587 | if (err < 0) { | ||
588 | printk(KERN_ERR LOGNAME ": error creating new Mixer device\n"); | ||
589 | goto err_release_region; | ||
590 | } | ||
591 | |||
592 | |||
593 | if (mpu_io[0] != SNDRV_AUTO_PORT) { | ||
594 | struct snd_mpu401 *mpu; | ||
595 | |||
596 | err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, | ||
597 | mpu_io[0], | ||
598 | MPU401_MODE_INPUT | | ||
599 | MPU401_MODE_OUTPUT, | ||
600 | mpu_irq[0], IRQF_DISABLED, | ||
601 | &chip->rmidi); | ||
602 | if (err < 0) { | ||
603 | printk(KERN_ERR LOGNAME | ||
604 | ": error creating new Midi device\n"); | ||
605 | goto err_release_region; | ||
606 | } | ||
607 | mpu = chip->rmidi->private_data; | ||
608 | |||
609 | mpu->open_input = snd_msnd_mpu401_open; | ||
610 | mpu->close_input = snd_msnd_mpu401_close; | ||
611 | mpu->private_data = chip; | ||
612 | } | ||
613 | |||
614 | disable_irq(chip->irq); | ||
615 | snd_msnd_calibrate_adc(chip, chip->play_sample_rate); | ||
616 | snd_msndmix_force_recsrc(chip, 0); | ||
617 | |||
618 | err = snd_card_register(card); | ||
619 | if (err < 0) | ||
620 | goto err_release_region; | ||
621 | |||
622 | return 0; | ||
623 | |||
624 | err_release_region: | ||
625 | if (chip->mappedbase) | ||
626 | iounmap(chip->mappedbase); | ||
627 | release_mem_region(chip->base, BUFFSIZE); | ||
628 | release_region(chip->io, DSP_NUMIO); | ||
629 | free_irq(chip->irq, chip); | ||
630 | return err; | ||
631 | } | ||
632 | |||
633 | |||
634 | static void __devexit snd_msnd_unload(struct snd_card *card) | ||
635 | { | ||
636 | struct snd_msnd *chip = card->private_data; | ||
637 | |||
638 | iounmap(chip->mappedbase); | ||
639 | release_mem_region(chip->base, BUFFSIZE); | ||
640 | release_region(chip->io, DSP_NUMIO); | ||
641 | free_irq(chip->irq, chip); | ||
642 | snd_card_free(card); | ||
643 | } | ||
644 | |||
645 | #ifndef MSND_CLASSIC | ||
646 | |||
647 | /* Pinnacle/Fiji Logical Device Configuration */ | ||
648 | |||
649 | static int __devinit snd_msnd_write_cfg(int cfg, int reg, int value) | ||
650 | { | ||
651 | outb(reg, cfg); | ||
652 | outb(value, cfg + 1); | ||
653 | if (value != inb(cfg + 1)) { | ||
654 | printk(KERN_ERR LOGNAME ": snd_msnd_write_cfg: I/O error\n"); | ||
655 | return -EIO; | ||
656 | } | ||
657 | return 0; | ||
658 | } | ||
659 | |||
660 | static int __devinit snd_msnd_write_cfg_io0(int cfg, int num, u16 io) | ||
661 | { | ||
662 | if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) | ||
663 | return -EIO; | ||
664 | if (snd_msnd_write_cfg(cfg, IREG_IO0_BASEHI, HIBYTE(io))) | ||
665 | return -EIO; | ||
666 | if (snd_msnd_write_cfg(cfg, IREG_IO0_BASELO, LOBYTE(io))) | ||
667 | return -EIO; | ||
668 | return 0; | ||
669 | } | ||
670 | |||
671 | static int __devinit snd_msnd_write_cfg_io1(int cfg, int num, u16 io) | ||
672 | { | ||
673 | if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) | ||
674 | return -EIO; | ||
675 | if (snd_msnd_write_cfg(cfg, IREG_IO1_BASEHI, HIBYTE(io))) | ||
676 | return -EIO; | ||
677 | if (snd_msnd_write_cfg(cfg, IREG_IO1_BASELO, LOBYTE(io))) | ||
678 | return -EIO; | ||
679 | return 0; | ||
680 | } | ||
681 | |||
682 | static int __devinit snd_msnd_write_cfg_irq(int cfg, int num, u16 irq) | ||
683 | { | ||
684 | if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) | ||
685 | return -EIO; | ||
686 | if (snd_msnd_write_cfg(cfg, IREG_IRQ_NUMBER, LOBYTE(irq))) | ||
687 | return -EIO; | ||
688 | if (snd_msnd_write_cfg(cfg, IREG_IRQ_TYPE, IRQTYPE_EDGE)) | ||
689 | return -EIO; | ||
690 | return 0; | ||
691 | } | ||
692 | |||
693 | static int __devinit snd_msnd_write_cfg_mem(int cfg, int num, int mem) | ||
694 | { | ||
695 | u16 wmem; | ||
696 | |||
697 | mem >>= 8; | ||
698 | wmem = (u16)(mem & 0xfff); | ||
699 | if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) | ||
700 | return -EIO; | ||
701 | if (snd_msnd_write_cfg(cfg, IREG_MEMBASEHI, HIBYTE(wmem))) | ||
702 | return -EIO; | ||
703 | if (snd_msnd_write_cfg(cfg, IREG_MEMBASELO, LOBYTE(wmem))) | ||
704 | return -EIO; | ||
705 | if (wmem && snd_msnd_write_cfg(cfg, IREG_MEMCONTROL, | ||
706 | MEMTYPE_HIADDR | MEMTYPE_16BIT)) | ||
707 | return -EIO; | ||
708 | return 0; | ||
709 | } | ||
710 | |||
711 | static int __devinit snd_msnd_activate_logical(int cfg, int num) | ||
712 | { | ||
713 | if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) | ||
714 | return -EIO; | ||
715 | if (snd_msnd_write_cfg(cfg, IREG_ACTIVATE, LD_ACTIVATE)) | ||
716 | return -EIO; | ||
717 | return 0; | ||
718 | } | ||
719 | |||
720 | static int __devinit snd_msnd_write_cfg_logical(int cfg, int num, u16 io0, | ||
721 | u16 io1, u16 irq, int mem) | ||
722 | { | ||
723 | if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) | ||
724 | return -EIO; | ||
725 | if (snd_msnd_write_cfg_io0(cfg, num, io0)) | ||
726 | return -EIO; | ||
727 | if (snd_msnd_write_cfg_io1(cfg, num, io1)) | ||
728 | return -EIO; | ||
729 | if (snd_msnd_write_cfg_irq(cfg, num, irq)) | ||
730 | return -EIO; | ||
731 | if (snd_msnd_write_cfg_mem(cfg, num, mem)) | ||
732 | return -EIO; | ||
733 | if (snd_msnd_activate_logical(cfg, num)) | ||
734 | return -EIO; | ||
735 | return 0; | ||
736 | } | ||
737 | |||
738 | static int __devinit snd_msnd_pinnacle_cfg_reset(int cfg) | ||
739 | { | ||
740 | int i; | ||
741 | |||
742 | /* Reset devices if told to */ | ||
743 | printk(KERN_INFO LOGNAME ": Resetting all devices\n"); | ||
744 | for (i = 0; i < 4; ++i) | ||
745 | if (snd_msnd_write_cfg_logical(cfg, i, 0, 0, 0, 0)) | ||
746 | return -EIO; | ||
747 | |||
748 | return 0; | ||
749 | } | ||
750 | #endif | ||
751 | |||
752 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ | ||
753 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ | ||
754 | |||
755 | module_param_array(index, int, NULL, S_IRUGO); | ||
756 | MODULE_PARM_DESC(index, "Index value for msnd_pinnacle soundcard."); | ||
757 | module_param_array(id, charp, NULL, S_IRUGO); | ||
758 | MODULE_PARM_DESC(id, "ID string for msnd_pinnacle soundcard."); | ||
759 | |||
760 | static long io[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; | ||
761 | static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; | ||
762 | static long mem[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; | ||
763 | |||
764 | static long cfg[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; | ||
765 | |||
766 | #ifndef MSND_CLASSIC | ||
767 | /* Extra Peripheral Configuration (Default: Disable) */ | ||
768 | static long ide_io0[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; | ||
769 | static long ide_io1[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; | ||
770 | static int ide_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; | ||
771 | |||
772 | static long joystick_io[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; | ||
773 | /* If we have the digital daugherboard... */ | ||
774 | static int digital[SNDRV_CARDS]; | ||
775 | |||
776 | /* Extra Peripheral Configuration */ | ||
777 | static int reset[SNDRV_CARDS]; | ||
778 | #endif | ||
779 | |||
780 | static int write_ndelay[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 1 }; | ||
781 | |||
782 | static int calibrate_signal; | ||
783 | |||
784 | #ifdef CONFIG_PNP | ||
785 | static int isapnp[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; | ||
786 | module_param_array(isapnp, bool, NULL, 0444); | ||
787 | MODULE_PARM_DESC(isapnp, "ISA PnP detection for specified soundcard."); | ||
788 | #define has_isapnp(x) isapnp[x] | ||
789 | #else | ||
790 | #define has_isapnp(x) 0 | ||
791 | #endif | ||
792 | |||
793 | MODULE_AUTHOR("Karsten Wiese <annabellesgarden@yahoo.de>"); | ||
794 | MODULE_DESCRIPTION("Turtle Beach " LONGNAME " Linux Driver"); | ||
795 | MODULE_LICENSE("GPL"); | ||
796 | MODULE_FIRMWARE(INITCODEFILE); | ||
797 | MODULE_FIRMWARE(PERMCODEFILE); | ||
798 | |||
799 | module_param_array(io, long, NULL, S_IRUGO); | ||
800 | MODULE_PARM_DESC(io, "IO port #"); | ||
801 | module_param_array(irq, int, NULL, S_IRUGO); | ||
802 | module_param_array(mem, long, NULL, S_IRUGO); | ||
803 | module_param_array(write_ndelay, int, NULL, S_IRUGO); | ||
804 | module_param(calibrate_signal, int, S_IRUGO); | ||
805 | #ifndef MSND_CLASSIC | ||
806 | module_param_array(digital, int, NULL, S_IRUGO); | ||
807 | module_param_array(cfg, long, NULL, S_IRUGO); | ||
808 | module_param_array(reset, int, 0, S_IRUGO); | ||
809 | module_param_array(mpu_io, long, NULL, S_IRUGO); | ||
810 | module_param_array(mpu_irq, int, NULL, S_IRUGO); | ||
811 | module_param_array(ide_io0, long, NULL, S_IRUGO); | ||
812 | module_param_array(ide_io1, long, NULL, S_IRUGO); | ||
813 | module_param_array(ide_irq, int, NULL, S_IRUGO); | ||
814 | module_param_array(joystick_io, long, NULL, S_IRUGO); | ||
815 | #endif | ||
816 | |||
817 | |||
818 | static int __devinit snd_msnd_isa_match(struct device *pdev, unsigned int i) | ||
819 | { | ||
820 | if (io[i] == SNDRV_AUTO_PORT) | ||
821 | return 0; | ||
822 | |||
823 | if (irq[i] == SNDRV_AUTO_PORT || mem[i] == SNDRV_AUTO_PORT) { | ||
824 | printk(KERN_WARNING LOGNAME ": io, irq and mem must be set\n"); | ||
825 | return 0; | ||
826 | } | ||
827 | |||
828 | #ifdef MSND_CLASSIC | ||
829 | if (!(io[i] == 0x290 || | ||
830 | io[i] == 0x260 || | ||
831 | io[i] == 0x250 || | ||
832 | io[i] == 0x240 || | ||
833 | io[i] == 0x230 || | ||
834 | io[i] == 0x220 || | ||
835 | io[i] == 0x210 || | ||
836 | io[i] == 0x3e0)) { | ||
837 | printk(KERN_ERR LOGNAME ": \"io\" - DSP I/O base must be set " | ||
838 | " to 0x210, 0x220, 0x230, 0x240, 0x250, 0x260, 0x290, " | ||
839 | "or 0x3E0\n"); | ||
840 | return 0; | ||
841 | } | ||
842 | #else | ||
843 | if (io[i] < 0x100 || io[i] > 0x3e0 || (io[i] % 0x10) != 0) { | ||
844 | printk(KERN_ERR LOGNAME | ||
845 | ": \"io\" - DSP I/O base must within the range 0x100 " | ||
846 | "to 0x3E0 and must be evenly divisible by 0x10\n"); | ||
847 | return 0; | ||
848 | } | ||
849 | #endif /* MSND_CLASSIC */ | ||
850 | |||
851 | if (!(irq[i] == 5 || | ||
852 | irq[i] == 7 || | ||
853 | irq[i] == 9 || | ||
854 | irq[i] == 10 || | ||
855 | irq[i] == 11 || | ||
856 | irq[i] == 12)) { | ||
857 | printk(KERN_ERR LOGNAME | ||
858 | ": \"irq\" - must be set to 5, 7, 9, 10, 11 or 12\n"); | ||
859 | return 0; | ||
860 | } | ||
861 | |||
862 | if (!(mem[i] == 0xb0000 || | ||
863 | mem[i] == 0xc8000 || | ||
864 | mem[i] == 0xd0000 || | ||
865 | mem[i] == 0xd8000 || | ||
866 | mem[i] == 0xe0000 || | ||
867 | mem[i] == 0xe8000)) { | ||
868 | printk(KERN_ERR LOGNAME ": \"mem\" - must be set to " | ||
869 | "0xb0000, 0xc8000, 0xd0000, 0xd8000, 0xe0000 or " | ||
870 | "0xe8000\n"); | ||
871 | return 0; | ||
872 | } | ||
873 | |||
874 | #ifndef MSND_CLASSIC | ||
875 | if (cfg[i] == SNDRV_AUTO_PORT) { | ||
876 | printk(KERN_INFO LOGNAME ": Assuming PnP mode\n"); | ||
877 | } else if (cfg[i] != 0x250 && cfg[i] != 0x260 && cfg[i] != 0x270) { | ||
878 | printk(KERN_INFO LOGNAME | ||
879 | ": Config port must be 0x250, 0x260 or 0x270 " | ||
880 | "(or unspecified for PnP mode)\n"); | ||
881 | return 0; | ||
882 | } | ||
883 | #endif /* MSND_CLASSIC */ | ||
884 | |||
885 | return 1; | ||
886 | } | ||
887 | |||
888 | static int __devinit snd_msnd_isa_probe(struct device *pdev, unsigned int idx) | ||
889 | { | ||
890 | int err; | ||
891 | struct snd_card *card; | ||
892 | struct snd_msnd *chip; | ||
893 | |||
894 | if (has_isapnp(idx) || cfg[idx] == SNDRV_AUTO_PORT) { | ||
895 | printk(KERN_INFO LOGNAME ": Assuming PnP mode\n"); | ||
896 | return -ENODEV; | ||
897 | } | ||
898 | |||
899 | err = snd_card_create(index[idx], id[idx], THIS_MODULE, | ||
900 | sizeof(struct snd_msnd), &card); | ||
901 | if (err < 0) | ||
902 | return err; | ||
903 | |||
904 | snd_card_set_dev(card, pdev); | ||
905 | chip = card->private_data; | ||
906 | chip->card = card; | ||
907 | |||
908 | #ifdef MSND_CLASSIC | ||
909 | switch (irq[idx]) { | ||
910 | case 5: | ||
911 | chip->irqid = HPIRQ_5; break; | ||
912 | case 7: | ||
913 | chip->irqid = HPIRQ_7; break; | ||
914 | case 9: | ||
915 | chip->irqid = HPIRQ_9; break; | ||
916 | case 10: | ||
917 | chip->irqid = HPIRQ_10; break; | ||
918 | case 11: | ||
919 | chip->irqid = HPIRQ_11; break; | ||
920 | case 12: | ||
921 | chip->irqid = HPIRQ_12; break; | ||
922 | } | ||
923 | |||
924 | switch (mem[idx]) { | ||
925 | case 0xb0000: | ||
926 | chip->memid = HPMEM_B000; break; | ||
927 | case 0xc8000: | ||
928 | chip->memid = HPMEM_C800; break; | ||
929 | case 0xd0000: | ||
930 | chip->memid = HPMEM_D000; break; | ||
931 | case 0xd8000: | ||
932 | chip->memid = HPMEM_D800; break; | ||
933 | case 0xe0000: | ||
934 | chip->memid = HPMEM_E000; break; | ||
935 | case 0xe8000: | ||
936 | chip->memid = HPMEM_E800; break; | ||
937 | } | ||
938 | #else | ||
939 | printk(KERN_INFO LOGNAME ": Non-PnP mode: configuring at port 0x%lx\n", | ||
940 | cfg[idx]); | ||
941 | |||
942 | if (!request_region(cfg[idx], 2, "Pinnacle/Fiji Config")) { | ||
943 | printk(KERN_ERR LOGNAME ": Config port 0x%lx conflict\n", | ||
944 | cfg[idx]); | ||
945 | snd_card_free(card); | ||
946 | return -EIO; | ||
947 | } | ||
948 | if (reset[idx]) | ||
949 | if (snd_msnd_pinnacle_cfg_reset(cfg[idx])) { | ||
950 | err = -EIO; | ||
951 | goto cfg_error; | ||
952 | } | ||
953 | |||
954 | /* DSP */ | ||
955 | err = snd_msnd_write_cfg_logical(cfg[idx], 0, | ||
956 | io[idx], 0, | ||
957 | irq[idx], mem[idx]); | ||
958 | |||
959 | if (err) | ||
960 | goto cfg_error; | ||
961 | |||
962 | /* The following are Pinnacle specific */ | ||
963 | |||
964 | /* MPU */ | ||
965 | if (mpu_io[idx] != SNDRV_AUTO_PORT | ||
966 | && mpu_irq[idx] != SNDRV_AUTO_IRQ) { | ||
967 | printk(KERN_INFO LOGNAME | ||
968 | ": Configuring MPU to I/O 0x%lx IRQ %d\n", | ||
969 | mpu_io[idx], mpu_irq[idx]); | ||
970 | err = snd_msnd_write_cfg_logical(cfg[idx], 1, | ||
971 | mpu_io[idx], 0, | ||
972 | mpu_irq[idx], 0); | ||
973 | |||
974 | if (err) | ||
975 | goto cfg_error; | ||
976 | } | ||
977 | |||
978 | /* IDE */ | ||
979 | if (ide_io0[idx] != SNDRV_AUTO_PORT | ||
980 | && ide_io1[idx] != SNDRV_AUTO_PORT | ||
981 | && ide_irq[idx] != SNDRV_AUTO_IRQ) { | ||
982 | printk(KERN_INFO LOGNAME | ||
983 | ": Configuring IDE to I/O 0x%lx, 0x%lx IRQ %d\n", | ||
984 | ide_io0[idx], ide_io1[idx], ide_irq[idx]); | ||
985 | err = snd_msnd_write_cfg_logical(cfg[idx], 2, | ||
986 | ide_io0[idx], ide_io1[idx], | ||
987 | ide_irq[idx], 0); | ||
988 | |||
989 | if (err) | ||
990 | goto cfg_error; | ||
991 | } | ||
992 | |||
993 | /* Joystick */ | ||
994 | if (joystick_io[idx] != SNDRV_AUTO_PORT) { | ||
995 | printk(KERN_INFO LOGNAME | ||
996 | ": Configuring joystick to I/O 0x%lx\n", | ||
997 | joystick_io[idx]); | ||
998 | err = snd_msnd_write_cfg_logical(cfg[idx], 3, | ||
999 | joystick_io[idx], 0, | ||
1000 | 0, 0); | ||
1001 | |||
1002 | if (err) | ||
1003 | goto cfg_error; | ||
1004 | } | ||
1005 | release_region(cfg[idx], 2); | ||
1006 | |||
1007 | #endif /* MSND_CLASSIC */ | ||
1008 | |||
1009 | set_default_audio_parameters(chip); | ||
1010 | #ifdef MSND_CLASSIC | ||
1011 | chip->type = msndClassic; | ||
1012 | #else | ||
1013 | chip->type = msndPinnacle; | ||
1014 | #endif | ||
1015 | chip->io = io[idx]; | ||
1016 | chip->irq = irq[idx]; | ||
1017 | chip->base = mem[idx]; | ||
1018 | |||
1019 | chip->calibrate_signal = calibrate_signal ? 1 : 0; | ||
1020 | chip->recsrc = 0; | ||
1021 | chip->dspq_data_buff = DSPQ_DATA_BUFF; | ||
1022 | chip->dspq_buff_size = DSPQ_BUFF_SIZE; | ||
1023 | if (write_ndelay[idx]) | ||
1024 | clear_bit(F_DISABLE_WRITE_NDELAY, &chip->flags); | ||
1025 | else | ||
1026 | set_bit(F_DISABLE_WRITE_NDELAY, &chip->flags); | ||
1027 | #ifndef MSND_CLASSIC | ||
1028 | if (digital[idx]) | ||
1029 | set_bit(F_HAVEDIGITAL, &chip->flags); | ||
1030 | #endif | ||
1031 | spin_lock_init(&chip->lock); | ||
1032 | err = snd_msnd_probe(card); | ||
1033 | if (err < 0) { | ||
1034 | printk(KERN_ERR LOGNAME ": Probe failed\n"); | ||
1035 | snd_card_free(card); | ||
1036 | return err; | ||
1037 | } | ||
1038 | |||
1039 | err = snd_msnd_attach(card); | ||
1040 | if (err < 0) { | ||
1041 | printk(KERN_ERR LOGNAME ": Attach failed\n"); | ||
1042 | snd_card_free(card); | ||
1043 | return err; | ||
1044 | } | ||
1045 | dev_set_drvdata(pdev, card); | ||
1046 | |||
1047 | return 0; | ||
1048 | |||
1049 | #ifndef MSND_CLASSIC | ||
1050 | cfg_error: | ||
1051 | release_region(cfg[idx], 2); | ||
1052 | snd_card_free(card); | ||
1053 | return err; | ||
1054 | #endif | ||
1055 | } | ||
1056 | |||
1057 | static int __devexit snd_msnd_isa_remove(struct device *pdev, unsigned int dev) | ||
1058 | { | ||
1059 | snd_msnd_unload(dev_get_drvdata(pdev)); | ||
1060 | dev_set_drvdata(pdev, NULL); | ||
1061 | return 0; | ||
1062 | } | ||
1063 | |||
1064 | #define DEV_NAME "msnd-pinnacle" | ||
1065 | |||
1066 | static struct isa_driver snd_msnd_driver = { | ||
1067 | .match = snd_msnd_isa_match, | ||
1068 | .probe = snd_msnd_isa_probe, | ||
1069 | .remove = __devexit_p(snd_msnd_isa_remove), | ||
1070 | /* FIXME: suspend, resume */ | ||
1071 | .driver = { | ||
1072 | .name = DEV_NAME | ||
1073 | }, | ||
1074 | }; | ||
1075 | |||
1076 | #ifdef CONFIG_PNP | ||
1077 | static int __devinit snd_msnd_pnp_detect(struct pnp_card_link *pcard, | ||
1078 | const struct pnp_card_device_id *pid) | ||
1079 | { | ||
1080 | static int idx; | ||
1081 | struct pnp_dev *pnp_dev; | ||
1082 | struct pnp_dev *mpu_dev; | ||
1083 | struct snd_card *card; | ||
1084 | struct snd_msnd *chip; | ||
1085 | int ret; | ||
1086 | |||
1087 | for ( ; idx < SNDRV_CARDS; idx++) { | ||
1088 | if (has_isapnp(idx)) | ||
1089 | break; | ||
1090 | } | ||
1091 | if (idx >= SNDRV_CARDS) | ||
1092 | return -ENODEV; | ||
1093 | |||
1094 | /* | ||
1095 | * Check that we still have room for another sound card ... | ||
1096 | */ | ||
1097 | pnp_dev = pnp_request_card_device(pcard, pid->devs[0].id, NULL); | ||
1098 | if (!pnp_dev) | ||
1099 | return -ENODEV; | ||
1100 | |||
1101 | mpu_dev = pnp_request_card_device(pcard, pid->devs[1].id, NULL); | ||
1102 | if (!mpu_dev) | ||
1103 | return -ENODEV; | ||
1104 | |||
1105 | if (!pnp_is_active(pnp_dev) && pnp_activate_dev(pnp_dev) < 0) { | ||
1106 | printk(KERN_INFO "msnd_pinnacle: device is inactive\n"); | ||
1107 | return -EBUSY; | ||
1108 | } | ||
1109 | |||
1110 | if (!pnp_is_active(mpu_dev) && pnp_activate_dev(mpu_dev) < 0) { | ||
1111 | printk(KERN_INFO "msnd_pinnacle: MPU device is inactive\n"); | ||
1112 | return -EBUSY; | ||
1113 | } | ||
1114 | |||
1115 | /* | ||
1116 | * Create a new ALSA sound card entry, in anticipation | ||
1117 | * of detecting our hardware ... | ||
1118 | */ | ||
1119 | ret = snd_card_create(index[idx], id[idx], THIS_MODULE, | ||
1120 | sizeof(struct snd_msnd), &card); | ||
1121 | if (ret < 0) | ||
1122 | return ret; | ||
1123 | |||
1124 | chip = card->private_data; | ||
1125 | chip->card = card; | ||
1126 | snd_card_set_dev(card, &pcard->card->dev); | ||
1127 | |||
1128 | /* | ||
1129 | * Read the correct parameters off the ISA PnP bus ... | ||
1130 | */ | ||
1131 | io[idx] = pnp_port_start(pnp_dev, 0); | ||
1132 | irq[idx] = pnp_irq(pnp_dev, 0); | ||
1133 | mem[idx] = pnp_mem_start(pnp_dev, 0); | ||
1134 | mpu_io[idx] = pnp_port_start(mpu_dev, 0); | ||
1135 | mpu_irq[idx] = pnp_irq(mpu_dev, 0); | ||
1136 | |||
1137 | set_default_audio_parameters(chip); | ||
1138 | #ifdef MSND_CLASSIC | ||
1139 | chip->type = msndClassic; | ||
1140 | #else | ||
1141 | chip->type = msndPinnacle; | ||
1142 | #endif | ||
1143 | chip->io = io[idx]; | ||
1144 | chip->irq = irq[idx]; | ||
1145 | chip->base = mem[idx]; | ||
1146 | |||
1147 | chip->calibrate_signal = calibrate_signal ? 1 : 0; | ||
1148 | chip->recsrc = 0; | ||
1149 | chip->dspq_data_buff = DSPQ_DATA_BUFF; | ||
1150 | chip->dspq_buff_size = DSPQ_BUFF_SIZE; | ||
1151 | if (write_ndelay[idx]) | ||
1152 | clear_bit(F_DISABLE_WRITE_NDELAY, &chip->flags); | ||
1153 | else | ||
1154 | set_bit(F_DISABLE_WRITE_NDELAY, &chip->flags); | ||
1155 | #ifndef MSND_CLASSIC | ||
1156 | if (digital[idx]) | ||
1157 | set_bit(F_HAVEDIGITAL, &chip->flags); | ||
1158 | #endif | ||
1159 | spin_lock_init(&chip->lock); | ||
1160 | ret = snd_msnd_probe(card); | ||
1161 | if (ret < 0) { | ||
1162 | printk(KERN_ERR LOGNAME ": Probe failed\n"); | ||
1163 | goto _release_card; | ||
1164 | } | ||
1165 | |||
1166 | ret = snd_msnd_attach(card); | ||
1167 | if (ret < 0) { | ||
1168 | printk(KERN_ERR LOGNAME ": Attach failed\n"); | ||
1169 | goto _release_card; | ||
1170 | } | ||
1171 | |||
1172 | pnp_set_card_drvdata(pcard, card); | ||
1173 | ++idx; | ||
1174 | return 0; | ||
1175 | |||
1176 | _release_card: | ||
1177 | snd_card_free(card); | ||
1178 | return ret; | ||
1179 | } | ||
1180 | |||
1181 | static void __devexit snd_msnd_pnp_remove(struct pnp_card_link *pcard) | ||
1182 | { | ||
1183 | snd_msnd_unload(pnp_get_card_drvdata(pcard)); | ||
1184 | pnp_set_card_drvdata(pcard, NULL); | ||
1185 | } | ||
1186 | |||
1187 | static int isa_registered; | ||
1188 | static int pnp_registered; | ||
1189 | |||
1190 | static struct pnp_card_device_id msnd_pnpids[] = { | ||
1191 | /* Pinnacle PnP */ | ||
1192 | { .id = "BVJ0440", .devs = { { "TBS0000" }, { "TBS0001" } } }, | ||
1193 | { .id = "" } /* end */ | ||
1194 | }; | ||
1195 | |||
1196 | MODULE_DEVICE_TABLE(pnp_card, msnd_pnpids); | ||
1197 | |||
1198 | static struct pnp_card_driver msnd_pnpc_driver = { | ||
1199 | .flags = PNP_DRIVER_RES_DO_NOT_CHANGE, | ||
1200 | .name = "msnd_pinnacle", | ||
1201 | .id_table = msnd_pnpids, | ||
1202 | .probe = snd_msnd_pnp_detect, | ||
1203 | .remove = __devexit_p(snd_msnd_pnp_remove), | ||
1204 | }; | ||
1205 | #endif /* CONFIG_PNP */ | ||
1206 | |||
1207 | static int __init snd_msnd_init(void) | ||
1208 | { | ||
1209 | int err; | ||
1210 | |||
1211 | err = isa_register_driver(&snd_msnd_driver, SNDRV_CARDS); | ||
1212 | #ifdef CONFIG_PNP | ||
1213 | if (!err) | ||
1214 | isa_registered = 1; | ||
1215 | |||
1216 | err = pnp_register_card_driver(&msnd_pnpc_driver); | ||
1217 | if (!err) | ||
1218 | pnp_registered = 1; | ||
1219 | |||
1220 | if (isa_registered) | ||
1221 | err = 0; | ||
1222 | #endif | ||
1223 | return err; | ||
1224 | } | ||
1225 | |||
1226 | static void __exit snd_msnd_exit(void) | ||
1227 | { | ||
1228 | #ifdef CONFIG_PNP | ||
1229 | if (pnp_registered) | ||
1230 | pnp_unregister_card_driver(&msnd_pnpc_driver); | ||
1231 | if (isa_registered) | ||
1232 | #endif | ||
1233 | isa_unregister_driver(&snd_msnd_driver); | ||
1234 | } | ||
1235 | |||
1236 | module_init(snd_msnd_init); | ||
1237 | module_exit(snd_msnd_exit); | ||
1238 | |||
diff --git a/sound/isa/msnd/msnd_pinnacle.h b/sound/isa/msnd/msnd_pinnacle.h new file mode 100644 index 000000000000..48318d1ee340 --- /dev/null +++ b/sound/isa/msnd/msnd_pinnacle.h | |||
@@ -0,0 +1,181 @@ | |||
1 | /********************************************************************* | ||
2 | * | ||
3 | * msnd_pinnacle.h | ||
4 | * | ||
5 | * Turtle Beach MultiSound Sound Card Driver for Linux | ||
6 | * | ||
7 | * Some parts of this header file were derived from the Turtle Beach | ||
8 | * MultiSound Driver Development Kit. | ||
9 | * | ||
10 | * Copyright (C) 1998 Andrew Veliath | ||
11 | * Copyright (C) 1993 Turtle Beach Systems, Inc. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | * | ||
27 | ********************************************************************/ | ||
28 | #ifndef __MSND_PINNACLE_H | ||
29 | #define __MSND_PINNACLE_H | ||
30 | |||
31 | #define DSP_NUMIO 0x08 | ||
32 | |||
33 | #define IREG_LOGDEVICE 0x07 | ||
34 | #define IREG_ACTIVATE 0x30 | ||
35 | #define LD_ACTIVATE 0x01 | ||
36 | #define LD_DISACTIVATE 0x00 | ||
37 | #define IREG_EECONTROL 0x3F | ||
38 | #define IREG_MEMBASEHI 0x40 | ||
39 | #define IREG_MEMBASELO 0x41 | ||
40 | #define IREG_MEMCONTROL 0x42 | ||
41 | #define IREG_MEMRANGEHI 0x43 | ||
42 | #define IREG_MEMRANGELO 0x44 | ||
43 | #define MEMTYPE_8BIT 0x00 | ||
44 | #define MEMTYPE_16BIT 0x02 | ||
45 | #define MEMTYPE_RANGE 0x00 | ||
46 | #define MEMTYPE_HIADDR 0x01 | ||
47 | #define IREG_IO0_BASEHI 0x60 | ||
48 | #define IREG_IO0_BASELO 0x61 | ||
49 | #define IREG_IO1_BASEHI 0x62 | ||
50 | #define IREG_IO1_BASELO 0x63 | ||
51 | #define IREG_IRQ_NUMBER 0x70 | ||
52 | #define IREG_IRQ_TYPE 0x71 | ||
53 | #define IRQTYPE_HIGH 0x02 | ||
54 | #define IRQTYPE_LOW 0x00 | ||
55 | #define IRQTYPE_LEVEL 0x01 | ||
56 | #define IRQTYPE_EDGE 0x00 | ||
57 | |||
58 | #define HP_DSPR 0x04 | ||
59 | #define HP_BLKS 0x04 | ||
60 | |||
61 | #define HPDSPRESET_OFF 2 | ||
62 | #define HPDSPRESET_ON 0 | ||
63 | |||
64 | #define HPBLKSEL_0 2 | ||
65 | #define HPBLKSEL_1 3 | ||
66 | |||
67 | #define HIMT_DAT_OFF 0x03 | ||
68 | |||
69 | #define HIDSP_PLAY_UNDER 0x00 | ||
70 | #define HIDSP_INT_PLAY_UNDER 0x01 | ||
71 | #define HIDSP_SSI_TX_UNDER 0x02 | ||
72 | #define HIDSP_RECQ_OVERFLOW 0x08 | ||
73 | #define HIDSP_INT_RECORD_OVER 0x09 | ||
74 | #define HIDSP_SSI_RX_OVERFLOW 0x0a | ||
75 | |||
76 | #define HIDSP_MIDI_IN_OVER 0x10 | ||
77 | |||
78 | #define HIDSP_MIDI_FRAME_ERR 0x11 | ||
79 | #define HIDSP_MIDI_PARITY_ERR 0x12 | ||
80 | #define HIDSP_MIDI_OVERRUN_ERR 0x13 | ||
81 | |||
82 | #define HIDSP_INPUT_CLIPPING 0x20 | ||
83 | #define HIDSP_MIX_CLIPPING 0x30 | ||
84 | #define HIDSP_DAT_IN_OFF 0x21 | ||
85 | |||
86 | #define TIME_PRO_RESET_DONE 0x028A | ||
87 | #define TIME_PRO_SYSEX 0x001E | ||
88 | #define TIME_PRO_RESET 0x0032 | ||
89 | |||
90 | #define DAR_BUFF_SIZE 0x1000 | ||
91 | |||
92 | #define MIDQ_BUFF_SIZE 0x800 | ||
93 | #define DSPQ_BUFF_SIZE 0x5A0 | ||
94 | |||
95 | #define DSPQ_DATA_BUFF 0x7860 | ||
96 | |||
97 | #define MOP_WAVEHDR 0 | ||
98 | #define MOP_EXTOUT 1 | ||
99 | #define MOP_HWINIT 0xfe | ||
100 | #define MOP_NONE 0xff | ||
101 | #define MOP_MAX 1 | ||
102 | |||
103 | #define MIP_EXTIN 0 | ||
104 | #define MIP_WAVEHDR 1 | ||
105 | #define MIP_HWINIT 0xfe | ||
106 | #define MIP_MAX 1 | ||
107 | |||
108 | /* Pinnacle/Fiji SMA Common Data */ | ||
109 | #define SMA_wCurrPlayBytes 0x0000 | ||
110 | #define SMA_wCurrRecordBytes 0x0002 | ||
111 | #define SMA_wCurrPlayVolLeft 0x0004 | ||
112 | #define SMA_wCurrPlayVolRight 0x0006 | ||
113 | #define SMA_wCurrInVolLeft 0x0008 | ||
114 | #define SMA_wCurrInVolRight 0x000a | ||
115 | #define SMA_wCurrMHdrVolLeft 0x000c | ||
116 | #define SMA_wCurrMHdrVolRight 0x000e | ||
117 | #define SMA_dwCurrPlayPitch 0x0010 | ||
118 | #define SMA_dwCurrPlayRate 0x0014 | ||
119 | #define SMA_wCurrMIDIIOPatch 0x0018 | ||
120 | #define SMA_wCurrPlayFormat 0x001a | ||
121 | #define SMA_wCurrPlaySampleSize 0x001c | ||
122 | #define SMA_wCurrPlayChannels 0x001e | ||
123 | #define SMA_wCurrPlaySampleRate 0x0020 | ||
124 | #define SMA_wCurrRecordFormat 0x0022 | ||
125 | #define SMA_wCurrRecordSampleSize 0x0024 | ||
126 | #define SMA_wCurrRecordChannels 0x0026 | ||
127 | #define SMA_wCurrRecordSampleRate 0x0028 | ||
128 | #define SMA_wCurrDSPStatusFlags 0x002a | ||
129 | #define SMA_wCurrHostStatusFlags 0x002c | ||
130 | #define SMA_wCurrInputTagBits 0x002e | ||
131 | #define SMA_wCurrLeftPeak 0x0030 | ||
132 | #define SMA_wCurrRightPeak 0x0032 | ||
133 | #define SMA_bMicPotPosLeft 0x0034 | ||
134 | #define SMA_bMicPotPosRight 0x0035 | ||
135 | #define SMA_bMicPotMaxLeft 0x0036 | ||
136 | #define SMA_bMicPotMaxRight 0x0037 | ||
137 | #define SMA_bInPotPosLeft 0x0038 | ||
138 | #define SMA_bInPotPosRight 0x0039 | ||
139 | #define SMA_bAuxPotPosLeft 0x003a | ||
140 | #define SMA_bAuxPotPosRight 0x003b | ||
141 | #define SMA_bInPotMaxLeft 0x003c | ||
142 | #define SMA_bInPotMaxRight 0x003d | ||
143 | #define SMA_bAuxPotMaxLeft 0x003e | ||
144 | #define SMA_bAuxPotMaxRight 0x003f | ||
145 | #define SMA_bInPotMaxMethod 0x0040 | ||
146 | #define SMA_bAuxPotMaxMethod 0x0041 | ||
147 | #define SMA_wCurrMastVolLeft 0x0042 | ||
148 | #define SMA_wCurrMastVolRight 0x0044 | ||
149 | #define SMA_wCalFreqAtoD 0x0046 | ||
150 | #define SMA_wCurrAuxVolLeft 0x0048 | ||
151 | #define SMA_wCurrAuxVolRight 0x004a | ||
152 | #define SMA_wCurrPlay1VolLeft 0x004c | ||
153 | #define SMA_wCurrPlay1VolRight 0x004e | ||
154 | #define SMA_wCurrPlay2VolLeft 0x0050 | ||
155 | #define SMA_wCurrPlay2VolRight 0x0052 | ||
156 | #define SMA_wCurrPlay3VolLeft 0x0054 | ||
157 | #define SMA_wCurrPlay3VolRight 0x0056 | ||
158 | #define SMA_wCurrPlay4VolLeft 0x0058 | ||
159 | #define SMA_wCurrPlay4VolRight 0x005a | ||
160 | #define SMA_wCurrPlay1PeakLeft 0x005c | ||
161 | #define SMA_wCurrPlay1PeakRight 0x005e | ||
162 | #define SMA_wCurrPlay2PeakLeft 0x0060 | ||
163 | #define SMA_wCurrPlay2PeakRight 0x0062 | ||
164 | #define SMA_wCurrPlay3PeakLeft 0x0064 | ||
165 | #define SMA_wCurrPlay3PeakRight 0x0066 | ||
166 | #define SMA_wCurrPlay4PeakLeft 0x0068 | ||
167 | #define SMA_wCurrPlay4PeakRight 0x006a | ||
168 | #define SMA_wCurrPlayPeakLeft 0x006c | ||
169 | #define SMA_wCurrPlayPeakRight 0x006e | ||
170 | #define SMA_wCurrDATSR 0x0070 | ||
171 | #define SMA_wCurrDATRXCHNL 0x0072 | ||
172 | #define SMA_wCurrDATTXCHNL 0x0074 | ||
173 | #define SMA_wCurrDATRXRate 0x0076 | ||
174 | #define SMA_dwDSPPlayCount 0x0078 | ||
175 | #define SMA__size 0x007c | ||
176 | |||
177 | #define INITCODEFILE "turtlebeach/pndspini.bin" | ||
178 | #define PERMCODEFILE "turtlebeach/pndsperm.bin" | ||
179 | #define LONGNAME "MultiSound (Pinnacle/Fiji)" | ||
180 | |||
181 | #endif /* __MSND_PINNACLE_H */ | ||
diff --git a/sound/isa/msnd/msnd_pinnacle_mixer.c b/sound/isa/msnd/msnd_pinnacle_mixer.c new file mode 100644 index 000000000000..494058a1a502 --- /dev/null +++ b/sound/isa/msnd/msnd_pinnacle_mixer.c | |||
@@ -0,0 +1,343 @@ | |||
1 | /*************************************************************************** | ||
2 | msnd_pinnacle_mixer.c - description | ||
3 | ------------------- | ||
4 | begin : Fre Jun 7 2002 | ||
5 | copyright : (C) 2002 by karsten wiese | ||
6 | email : annabellesgarden@yahoo.de | ||
7 | ***************************************************************************/ | ||
8 | |||
9 | /*************************************************************************** | ||
10 | * * | ||
11 | * This program is free software; you can redistribute it and/or modify * | ||
12 | * it under the terms of the GNU General Public License as published by * | ||
13 | * the Free Software Foundation; either version 2 of the License, or * | ||
14 | * (at your option) any later version. * | ||
15 | * * | ||
16 | ***************************************************************************/ | ||
17 | |||
18 | #include <linux/io.h> | ||
19 | |||
20 | #include <sound/core.h> | ||
21 | #include <sound/control.h> | ||
22 | #include "msnd.h" | ||
23 | #include "msnd_pinnacle.h" | ||
24 | |||
25 | |||
26 | #define MSND_MIXER_VOLUME 0 | ||
27 | #define MSND_MIXER_PCM 1 | ||
28 | #define MSND_MIXER_AUX 2 /* Input source 1 (aux1) */ | ||
29 | #define MSND_MIXER_IMIX 3 /* Recording monitor */ | ||
30 | #define MSND_MIXER_SYNTH 4 | ||
31 | #define MSND_MIXER_SPEAKER 5 | ||
32 | #define MSND_MIXER_LINE 6 | ||
33 | #define MSND_MIXER_MIC 7 | ||
34 | #define MSND_MIXER_RECLEV 11 /* Recording level */ | ||
35 | #define MSND_MIXER_IGAIN 12 /* Input gain */ | ||
36 | #define MSND_MIXER_OGAIN 13 /* Output gain */ | ||
37 | #define MSND_MIXER_DIGITAL 17 /* Digital (input) 1 */ | ||
38 | |||
39 | /* Device mask bits */ | ||
40 | |||
41 | #define MSND_MASK_VOLUME (1 << MSND_MIXER_VOLUME) | ||
42 | #define MSND_MASK_SYNTH (1 << MSND_MIXER_SYNTH) | ||
43 | #define MSND_MASK_PCM (1 << MSND_MIXER_PCM) | ||
44 | #define MSND_MASK_SPEAKER (1 << MSND_MIXER_SPEAKER) | ||
45 | #define MSND_MASK_LINE (1 << MSND_MIXER_LINE) | ||
46 | #define MSND_MASK_MIC (1 << MSND_MIXER_MIC) | ||
47 | #define MSND_MASK_IMIX (1 << MSND_MIXER_IMIX) | ||
48 | #define MSND_MASK_RECLEV (1 << MSND_MIXER_RECLEV) | ||
49 | #define MSND_MASK_IGAIN (1 << MSND_MIXER_IGAIN) | ||
50 | #define MSND_MASK_OGAIN (1 << MSND_MIXER_OGAIN) | ||
51 | #define MSND_MASK_AUX (1 << MSND_MIXER_AUX) | ||
52 | #define MSND_MASK_DIGITAL (1 << MSND_MIXER_DIGITAL) | ||
53 | |||
54 | static int snd_msndmix_info_mux(struct snd_kcontrol *kcontrol, | ||
55 | struct snd_ctl_elem_info *uinfo) | ||
56 | { | ||
57 | static char *texts[3] = { | ||
58 | "Analog", "MASS", "SPDIF", | ||
59 | }; | ||
60 | struct snd_msnd *chip = snd_kcontrol_chip(kcontrol); | ||
61 | unsigned items = test_bit(F_HAVEDIGITAL, &chip->flags) ? 3 : 2; | ||
62 | |||
63 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
64 | uinfo->count = 1; | ||
65 | uinfo->value.enumerated.items = items; | ||
66 | if (uinfo->value.enumerated.item >= items) | ||
67 | uinfo->value.enumerated.item = items - 1; | ||
68 | strcpy(uinfo->value.enumerated.name, | ||
69 | texts[uinfo->value.enumerated.item]); | ||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | static int snd_msndmix_get_mux(struct snd_kcontrol *kcontrol, | ||
74 | struct snd_ctl_elem_value *ucontrol) | ||
75 | { | ||
76 | struct snd_msnd *chip = snd_kcontrol_chip(kcontrol); | ||
77 | /* MSND_MASK_IMIX is the default */ | ||
78 | ucontrol->value.enumerated.item[0] = 0; | ||
79 | |||
80 | if (chip->recsrc & MSND_MASK_SYNTH) { | ||
81 | ucontrol->value.enumerated.item[0] = 1; | ||
82 | } else if ((chip->recsrc & MSND_MASK_DIGITAL) && | ||
83 | test_bit(F_HAVEDIGITAL, &chip->flags)) { | ||
84 | ucontrol->value.enumerated.item[0] = 2; | ||
85 | } | ||
86 | |||
87 | |||
88 | return 0; | ||
89 | } | ||
90 | |||
91 | static int snd_msndmix_set_mux(struct snd_msnd *chip, int val) | ||
92 | { | ||
93 | unsigned newrecsrc; | ||
94 | int change; | ||
95 | unsigned char msndbyte; | ||
96 | |||
97 | switch (val) { | ||
98 | case 0: | ||
99 | newrecsrc = MSND_MASK_IMIX; | ||
100 | msndbyte = HDEXAR_SET_ANA_IN; | ||
101 | break; | ||
102 | case 1: | ||
103 | newrecsrc = MSND_MASK_SYNTH; | ||
104 | msndbyte = HDEXAR_SET_SYNTH_IN; | ||
105 | break; | ||
106 | case 2: | ||
107 | newrecsrc = MSND_MASK_DIGITAL; | ||
108 | msndbyte = HDEXAR_SET_DAT_IN; | ||
109 | break; | ||
110 | default: | ||
111 | return -EINVAL; | ||
112 | } | ||
113 | change = newrecsrc != chip->recsrc; | ||
114 | if (change) { | ||
115 | change = 0; | ||
116 | if (!snd_msnd_send_word(chip, 0, 0, msndbyte)) | ||
117 | if (!snd_msnd_send_dsp_cmd(chip, HDEX_AUX_REQ)) { | ||
118 | chip->recsrc = newrecsrc; | ||
119 | change = 1; | ||
120 | } | ||
121 | } | ||
122 | return change; | ||
123 | } | ||
124 | |||
125 | static int snd_msndmix_put_mux(struct snd_kcontrol *kcontrol, | ||
126 | struct snd_ctl_elem_value *ucontrol) | ||
127 | { | ||
128 | struct snd_msnd *msnd = snd_kcontrol_chip(kcontrol); | ||
129 | return snd_msndmix_set_mux(msnd, ucontrol->value.enumerated.item[0]); | ||
130 | } | ||
131 | |||
132 | |||
133 | static int snd_msndmix_volume_info(struct snd_kcontrol *kcontrol, | ||
134 | struct snd_ctl_elem_info *uinfo) | ||
135 | { | ||
136 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
137 | uinfo->count = 2; | ||
138 | uinfo->value.integer.min = 0; | ||
139 | uinfo->value.integer.max = 100; | ||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | static int snd_msndmix_volume_get(struct snd_kcontrol *kcontrol, | ||
144 | struct snd_ctl_elem_value *ucontrol) | ||
145 | { | ||
146 | struct snd_msnd *msnd = snd_kcontrol_chip(kcontrol); | ||
147 | int addr = kcontrol->private_value; | ||
148 | unsigned long flags; | ||
149 | |||
150 | spin_lock_irqsave(&msnd->mixer_lock, flags); | ||
151 | ucontrol->value.integer.value[0] = msnd->left_levels[addr] * 100; | ||
152 | ucontrol->value.integer.value[0] /= 0xFFFF; | ||
153 | ucontrol->value.integer.value[1] = msnd->right_levels[addr] * 100; | ||
154 | ucontrol->value.integer.value[1] /= 0xFFFF; | ||
155 | spin_unlock_irqrestore(&msnd->mixer_lock, flags); | ||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | #define update_volm(a, b) \ | ||
160 | do { \ | ||
161 | writew((dev->left_levels[a] >> 1) * \ | ||
162 | readw(dev->SMA + SMA_wCurrMastVolLeft) / 0xffff, \ | ||
163 | dev->SMA + SMA_##b##Left); \ | ||
164 | writew((dev->right_levels[a] >> 1) * \ | ||
165 | readw(dev->SMA + SMA_wCurrMastVolRight) / 0xffff, \ | ||
166 | dev->SMA + SMA_##b##Right); \ | ||
167 | } while (0); | ||
168 | |||
169 | #define update_potm(d, s, ar) \ | ||
170 | do { \ | ||
171 | writeb((dev->left_levels[d] >> 8) * \ | ||
172 | readw(dev->SMA + SMA_wCurrMastVolLeft) / 0xffff, \ | ||
173 | dev->SMA + SMA_##s##Left); \ | ||
174 | writeb((dev->right_levels[d] >> 8) * \ | ||
175 | readw(dev->SMA + SMA_wCurrMastVolRight) / 0xffff, \ | ||
176 | dev->SMA + SMA_##s##Right); \ | ||
177 | if (snd_msnd_send_word(dev, 0, 0, ar) == 0) \ | ||
178 | snd_msnd_send_dsp_cmd(dev, HDEX_AUX_REQ); \ | ||
179 | } while (0); | ||
180 | |||
181 | #define update_pot(d, s, ar) \ | ||
182 | do { \ | ||
183 | writeb(dev->left_levels[d] >> 8, \ | ||
184 | dev->SMA + SMA_##s##Left); \ | ||
185 | writeb(dev->right_levels[d] >> 8, \ | ||
186 | dev->SMA + SMA_##s##Right); \ | ||
187 | if (snd_msnd_send_word(dev, 0, 0, ar) == 0) \ | ||
188 | snd_msnd_send_dsp_cmd(dev, HDEX_AUX_REQ); \ | ||
189 | } while (0); | ||
190 | |||
191 | |||
192 | static int snd_msndmix_set(struct snd_msnd *dev, int d, int left, int right) | ||
193 | { | ||
194 | int bLeft, bRight; | ||
195 | int wLeft, wRight; | ||
196 | int updatemaster = 0; | ||
197 | |||
198 | if (d >= LEVEL_ENTRIES) | ||
199 | return -EINVAL; | ||
200 | |||
201 | bLeft = left * 0xff / 100; | ||
202 | wLeft = left * 0xffff / 100; | ||
203 | |||
204 | bRight = right * 0xff / 100; | ||
205 | wRight = right * 0xffff / 100; | ||
206 | |||
207 | dev->left_levels[d] = wLeft; | ||
208 | dev->right_levels[d] = wRight; | ||
209 | |||
210 | switch (d) { | ||
211 | /* master volume unscaled controls */ | ||
212 | case MSND_MIXER_LINE: /* line pot control */ | ||
213 | /* scaled by IMIX in digital mix */ | ||
214 | writeb(bLeft, dev->SMA + SMA_bInPotPosLeft); | ||
215 | writeb(bRight, dev->SMA + SMA_bInPotPosRight); | ||
216 | if (snd_msnd_send_word(dev, 0, 0, HDEXAR_IN_SET_POTS) == 0) | ||
217 | snd_msnd_send_dsp_cmd(dev, HDEX_AUX_REQ); | ||
218 | break; | ||
219 | case MSND_MIXER_MIC: /* mic pot control */ | ||
220 | if (dev->type == msndClassic) | ||
221 | return -EINVAL; | ||
222 | /* scaled by IMIX in digital mix */ | ||
223 | writeb(bLeft, dev->SMA + SMA_bMicPotPosLeft); | ||
224 | writeb(bRight, dev->SMA + SMA_bMicPotPosRight); | ||
225 | if (snd_msnd_send_word(dev, 0, 0, HDEXAR_MIC_SET_POTS) == 0) | ||
226 | snd_msnd_send_dsp_cmd(dev, HDEX_AUX_REQ); | ||
227 | break; | ||
228 | case MSND_MIXER_VOLUME: /* master volume */ | ||
229 | writew(wLeft, dev->SMA + SMA_wCurrMastVolLeft); | ||
230 | writew(wRight, dev->SMA + SMA_wCurrMastVolRight); | ||
231 | /* fall through */ | ||
232 | |||
233 | case MSND_MIXER_AUX: /* aux pot control */ | ||
234 | /* scaled by master volume */ | ||
235 | /* fall through */ | ||
236 | |||
237 | /* digital controls */ | ||
238 | case MSND_MIXER_SYNTH: /* synth vol (dsp mix) */ | ||
239 | case MSND_MIXER_PCM: /* pcm vol (dsp mix) */ | ||
240 | case MSND_MIXER_IMIX: /* input monitor (dsp mix) */ | ||
241 | /* scaled by master volume */ | ||
242 | updatemaster = 1; | ||
243 | break; | ||
244 | |||
245 | default: | ||
246 | return -EINVAL; | ||
247 | } | ||
248 | |||
249 | if (updatemaster) { | ||
250 | /* update master volume scaled controls */ | ||
251 | update_volm(MSND_MIXER_PCM, wCurrPlayVol); | ||
252 | update_volm(MSND_MIXER_IMIX, wCurrInVol); | ||
253 | if (dev->type == msndPinnacle) | ||
254 | update_volm(MSND_MIXER_SYNTH, wCurrMHdrVol); | ||
255 | update_potm(MSND_MIXER_AUX, bAuxPotPos, HDEXAR_AUX_SET_POTS); | ||
256 | } | ||
257 | |||
258 | return 0; | ||
259 | } | ||
260 | |||
261 | static int snd_msndmix_volume_put(struct snd_kcontrol *kcontrol, | ||
262 | struct snd_ctl_elem_value *ucontrol) | ||
263 | { | ||
264 | struct snd_msnd *msnd = snd_kcontrol_chip(kcontrol); | ||
265 | int change, addr = kcontrol->private_value; | ||
266 | int left, right; | ||
267 | unsigned long flags; | ||
268 | |||
269 | left = ucontrol->value.integer.value[0] % 101; | ||
270 | right = ucontrol->value.integer.value[1] % 101; | ||
271 | spin_lock_irqsave(&msnd->mixer_lock, flags); | ||
272 | change = msnd->left_levels[addr] != left | ||
273 | || msnd->right_levels[addr] != right; | ||
274 | snd_msndmix_set(msnd, addr, left, right); | ||
275 | spin_unlock_irqrestore(&msnd->mixer_lock, flags); | ||
276 | return change; | ||
277 | } | ||
278 | |||
279 | |||
280 | #define DUMMY_VOLUME(xname, xindex, addr) \ | ||
281 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ | ||
282 | .info = snd_msndmix_volume_info, \ | ||
283 | .get = snd_msndmix_volume_get, .put = snd_msndmix_volume_put, \ | ||
284 | .private_value = addr } | ||
285 | |||
286 | |||
287 | static struct snd_kcontrol_new snd_msnd_controls[] = { | ||
288 | DUMMY_VOLUME("Master Volume", 0, MSND_MIXER_VOLUME), | ||
289 | DUMMY_VOLUME("PCM Volume", 0, MSND_MIXER_PCM), | ||
290 | DUMMY_VOLUME("Aux Volume", 0, MSND_MIXER_AUX), | ||
291 | DUMMY_VOLUME("Line Volume", 0, MSND_MIXER_LINE), | ||
292 | DUMMY_VOLUME("Mic Volume", 0, MSND_MIXER_MIC), | ||
293 | DUMMY_VOLUME("Monitor", 0, MSND_MIXER_IMIX), | ||
294 | { | ||
295 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
296 | .name = "Capture Source", | ||
297 | .info = snd_msndmix_info_mux, | ||
298 | .get = snd_msndmix_get_mux, | ||
299 | .put = snd_msndmix_put_mux, | ||
300 | } | ||
301 | }; | ||
302 | |||
303 | |||
304 | int __devinit snd_msndmix_new(struct snd_card *card) | ||
305 | { | ||
306 | struct snd_msnd *chip = card->private_data; | ||
307 | unsigned int idx; | ||
308 | int err; | ||
309 | |||
310 | if (snd_BUG_ON(!chip)) | ||
311 | return -EINVAL; | ||
312 | spin_lock_init(&chip->mixer_lock); | ||
313 | strcpy(card->mixername, "MSND Pinnacle Mixer"); | ||
314 | |||
315 | for (idx = 0; idx < ARRAY_SIZE(snd_msnd_controls); idx++) | ||
316 | err = snd_ctl_add(card, | ||
317 | snd_ctl_new1(snd_msnd_controls + idx, chip)); | ||
318 | if (err < 0) | ||
319 | return err; | ||
320 | |||
321 | return 0; | ||
322 | } | ||
323 | EXPORT_SYMBOL(snd_msndmix_new); | ||
324 | |||
325 | void snd_msndmix_setup(struct snd_msnd *dev) | ||
326 | { | ||
327 | update_pot(MSND_MIXER_LINE, bInPotPos, HDEXAR_IN_SET_POTS); | ||
328 | update_potm(MSND_MIXER_AUX, bAuxPotPos, HDEXAR_AUX_SET_POTS); | ||
329 | update_volm(MSND_MIXER_PCM, wCurrPlayVol); | ||
330 | update_volm(MSND_MIXER_IMIX, wCurrInVol); | ||
331 | if (dev->type == msndPinnacle) { | ||
332 | update_pot(MSND_MIXER_MIC, bMicPotPos, HDEXAR_MIC_SET_POTS); | ||
333 | update_volm(MSND_MIXER_SYNTH, wCurrMHdrVol); | ||
334 | } | ||
335 | } | ||
336 | EXPORT_SYMBOL(snd_msndmix_setup); | ||
337 | |||
338 | int snd_msndmix_force_recsrc(struct snd_msnd *dev, int recsrc) | ||
339 | { | ||
340 | dev->recsrc = -1; | ||
341 | return snd_msndmix_set_mux(dev, recsrc); | ||
342 | } | ||
343 | EXPORT_SYMBOL(snd_msndmix_force_recsrc); | ||
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c index b848d1001864..ef95279da7a3 100644 --- a/sound/isa/opl3sa2.c +++ b/sound/isa/opl3sa2.c | |||
@@ -179,12 +179,13 @@ static unsigned char __snd_opl3sa2_read(struct snd_opl3sa2 *chip, unsigned char | |||
179 | unsigned char result; | 179 | unsigned char result; |
180 | #if 0 | 180 | #if 0 |
181 | outb(0x1d, port); /* password */ | 181 | outb(0x1d, port); /* password */ |
182 | printk("read [0x%lx] = 0x%x\n", port, inb(port)); | 182 | printk(KERN_DEBUG "read [0x%lx] = 0x%x\n", port, inb(port)); |
183 | #endif | 183 | #endif |
184 | outb(reg, chip->port); /* register */ | 184 | outb(reg, chip->port); /* register */ |
185 | result = inb(chip->port + 1); | 185 | result = inb(chip->port + 1); |
186 | #if 0 | 186 | #if 0 |
187 | printk("read [0x%lx] = 0x%x [0x%x]\n", port, result, inb(port)); | 187 | printk(KERN_DEBUG "read [0x%lx] = 0x%x [0x%x]\n", |
188 | port, result, inb(port)); | ||
188 | #endif | 189 | #endif |
189 | return result; | 190 | return result; |
190 | } | 191 | } |
@@ -233,7 +234,10 @@ static int __devinit snd_opl3sa2_detect(struct snd_card *card) | |||
233 | snd_printk(KERN_ERR PFX "can't grab port 0x%lx\n", port); | 234 | snd_printk(KERN_ERR PFX "can't grab port 0x%lx\n", port); |
234 | return -EBUSY; | 235 | return -EBUSY; |
235 | } | 236 | } |
236 | // snd_printk("REG 0A = 0x%x\n", snd_opl3sa2_read(chip, 0x0a)); | 237 | /* |
238 | snd_printk(KERN_DEBUG "REG 0A = 0x%x\n", | ||
239 | snd_opl3sa2_read(chip, 0x0a)); | ||
240 | */ | ||
237 | chip->version = 0; | 241 | chip->version = 0; |
238 | tmp = snd_opl3sa2_read(chip, OPL3SA2_MISC); | 242 | tmp = snd_opl3sa2_read(chip, OPL3SA2_MISC); |
239 | if (tmp == 0xff) { | 243 | if (tmp == 0xff) { |
@@ -619,25 +623,28 @@ static void snd_opl3sa2_free(struct snd_card *card) | |||
619 | { | 623 | { |
620 | struct snd_opl3sa2 *chip = card->private_data; | 624 | struct snd_opl3sa2 *chip = card->private_data; |
621 | if (chip->irq >= 0) | 625 | if (chip->irq >= 0) |
622 | free_irq(chip->irq, (void *)chip); | 626 | free_irq(chip->irq, card); |
623 | release_and_free_resource(chip->res_port); | 627 | release_and_free_resource(chip->res_port); |
624 | } | 628 | } |
625 | 629 | ||
626 | static struct snd_card *snd_opl3sa2_card_new(int dev) | 630 | static int snd_opl3sa2_card_new(int dev, struct snd_card **cardp) |
627 | { | 631 | { |
628 | struct snd_card *card; | 632 | struct snd_card *card; |
629 | struct snd_opl3sa2 *chip; | 633 | struct snd_opl3sa2 *chip; |
634 | int err; | ||
630 | 635 | ||
631 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(struct snd_opl3sa2)); | 636 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, |
632 | if (card == NULL) | 637 | sizeof(struct snd_opl3sa2), &card); |
633 | return NULL; | 638 | if (err < 0) |
639 | return err; | ||
634 | strcpy(card->driver, "OPL3SA2"); | 640 | strcpy(card->driver, "OPL3SA2"); |
635 | strcpy(card->shortname, "Yamaha OPL3-SA2"); | 641 | strcpy(card->shortname, "Yamaha OPL3-SA"); |
636 | chip = card->private_data; | 642 | chip = card->private_data; |
637 | spin_lock_init(&chip->reg_lock); | 643 | spin_lock_init(&chip->reg_lock); |
638 | chip->irq = -1; | 644 | chip->irq = -1; |
639 | card->private_free = snd_opl3sa2_free; | 645 | card->private_free = snd_opl3sa2_free; |
640 | return card; | 646 | *cardp = card; |
647 | return 0; | ||
641 | } | 648 | } |
642 | 649 | ||
643 | static int __devinit snd_opl3sa2_probe(struct snd_card *card, int dev) | 650 | static int __devinit snd_opl3sa2_probe(struct snd_card *card, int dev) |
@@ -729,9 +736,9 @@ static int __devinit snd_opl3sa2_pnp_detect(struct pnp_dev *pdev, | |||
729 | if (dev >= SNDRV_CARDS) | 736 | if (dev >= SNDRV_CARDS) |
730 | return -ENODEV; | 737 | return -ENODEV; |
731 | 738 | ||
732 | card = snd_opl3sa2_card_new(dev); | 739 | err = snd_opl3sa2_card_new(dev, &card); |
733 | if (! card) | 740 | if (err < 0) |
734 | return -ENOMEM; | 741 | return err; |
735 | if ((err = snd_opl3sa2_pnp(dev, card->private_data, pdev)) < 0) { | 742 | if ((err = snd_opl3sa2_pnp(dev, card->private_data, pdev)) < 0) { |
736 | snd_card_free(card); | 743 | snd_card_free(card); |
737 | return err; | 744 | return err; |
@@ -795,9 +802,9 @@ static int __devinit snd_opl3sa2_pnp_cdetect(struct pnp_card_link *pcard, | |||
795 | if (dev >= SNDRV_CARDS) | 802 | if (dev >= SNDRV_CARDS) |
796 | return -ENODEV; | 803 | return -ENODEV; |
797 | 804 | ||
798 | card = snd_opl3sa2_card_new(dev); | 805 | err = snd_opl3sa2_card_new(dev, &card); |
799 | if (! card) | 806 | if (err < 0) |
800 | return -ENOMEM; | 807 | return err; |
801 | if ((err = snd_opl3sa2_pnp(dev, card->private_data, pdev)) < 0) { | 808 | if ((err = snd_opl3sa2_pnp(dev, card->private_data, pdev)) < 0) { |
802 | snd_card_free(card); | 809 | snd_card_free(card); |
803 | return err; | 810 | return err; |
@@ -876,9 +883,9 @@ static int __devinit snd_opl3sa2_isa_probe(struct device *pdev, | |||
876 | struct snd_card *card; | 883 | struct snd_card *card; |
877 | int err; | 884 | int err; |
878 | 885 | ||
879 | card = snd_opl3sa2_card_new(dev); | 886 | err = snd_opl3sa2_card_new(dev, &card); |
880 | if (! card) | 887 | if (err < 0) |
881 | return -ENOMEM; | 888 | return err; |
882 | snd_card_set_dev(card, pdev); | 889 | snd_card_set_dev(card, pdev); |
883 | if ((err = snd_opl3sa2_probe(card, dev)) < 0) { | 890 | if ((err = snd_opl3sa2_probe(card, dev)) < 0) { |
884 | snd_card_free(card); | 891 | snd_card_free(card); |
diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c index 440755cc0013..02e30d7c6a93 100644 --- a/sound/isa/opti9xx/miro.c +++ b/sound/isa/opti9xx/miro.c | |||
@@ -1228,9 +1228,10 @@ static int __devinit snd_miro_probe(struct device *devptr, unsigned int n) | |||
1228 | struct snd_pcm *pcm; | 1228 | struct snd_pcm *pcm; |
1229 | struct snd_rawmidi *rmidi; | 1229 | struct snd_rawmidi *rmidi; |
1230 | 1230 | ||
1231 | if (!(card = snd_card_new(index, id, THIS_MODULE, | 1231 | error = snd_card_create(index, id, THIS_MODULE, |
1232 | sizeof(struct snd_miro)))) | 1232 | sizeof(struct snd_miro), &card); |
1233 | return -ENOMEM; | 1233 | if (error < 0) |
1234 | return error; | ||
1234 | 1235 | ||
1235 | card->private_free = snd_card_miro_free; | 1236 | card->private_free = snd_card_miro_free; |
1236 | miro = card->private_data; | 1237 | miro = card->private_data; |
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index 19706b0d8497..5cd555325b9d 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c | |||
@@ -252,7 +252,7 @@ static int __devinit snd_opti9xx_init(struct snd_opti9xx *chip, | |||
252 | #endif /* OPTi93X */ | 252 | #endif /* OPTi93X */ |
253 | 253 | ||
254 | default: | 254 | default: |
255 | snd_printk("chip %d not supported\n", hardware); | 255 | snd_printk(KERN_ERR "chip %d not supported\n", hardware); |
256 | return -ENODEV; | 256 | return -ENODEV; |
257 | } | 257 | } |
258 | return 0; | 258 | return 0; |
@@ -294,7 +294,7 @@ static unsigned char snd_opti9xx_read(struct snd_opti9xx *chip, | |||
294 | #endif /* OPTi93X */ | 294 | #endif /* OPTi93X */ |
295 | 295 | ||
296 | default: | 296 | default: |
297 | snd_printk("chip %d not supported\n", chip->hardware); | 297 | snd_printk(KERN_ERR "chip %d not supported\n", chip->hardware); |
298 | } | 298 | } |
299 | 299 | ||
300 | spin_unlock_irqrestore(&chip->lock, flags); | 300 | spin_unlock_irqrestore(&chip->lock, flags); |
@@ -336,7 +336,7 @@ static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg, | |||
336 | #endif /* OPTi93X */ | 336 | #endif /* OPTi93X */ |
337 | 337 | ||
338 | default: | 338 | default: |
339 | snd_printk("chip %d not supported\n", chip->hardware); | 339 | snd_printk(KERN_ERR "chip %d not supported\n", chip->hardware); |
340 | } | 340 | } |
341 | 341 | ||
342 | spin_unlock_irqrestore(&chip->lock, flags); | 342 | spin_unlock_irqrestore(&chip->lock, flags); |
@@ -412,7 +412,7 @@ static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip) | |||
412 | #endif /* OPTi93X */ | 412 | #endif /* OPTi93X */ |
413 | 413 | ||
414 | default: | 414 | default: |
415 | snd_printk("chip %d not supported\n", chip->hardware); | 415 | snd_printk(KERN_ERR "chip %d not supported\n", chip->hardware); |
416 | return -EINVAL; | 416 | return -EINVAL; |
417 | } | 417 | } |
418 | 418 | ||
@@ -430,7 +430,8 @@ static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip) | |||
430 | wss_base_bits = 0x02; | 430 | wss_base_bits = 0x02; |
431 | break; | 431 | break; |
432 | default: | 432 | default: |
433 | snd_printk("WSS port 0x%lx not valid\n", chip->wss_base); | 433 | snd_printk(KERN_WARNING "WSS port 0x%lx not valid\n", |
434 | chip->wss_base); | ||
434 | goto __skip_base; | 435 | goto __skip_base; |
435 | } | 436 | } |
436 | snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), wss_base_bits << 4, 0x30); | 437 | snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), wss_base_bits << 4, 0x30); |
@@ -455,7 +456,7 @@ __skip_base: | |||
455 | irq_bits = 0x04; | 456 | irq_bits = 0x04; |
456 | break; | 457 | break; |
457 | default: | 458 | default: |
458 | snd_printk("WSS irq # %d not valid\n", chip->irq); | 459 | snd_printk(KERN_WARNING "WSS irq # %d not valid\n", chip->irq); |
459 | goto __skip_resources; | 460 | goto __skip_resources; |
460 | } | 461 | } |
461 | 462 | ||
@@ -470,13 +471,14 @@ __skip_base: | |||
470 | dma_bits = 0x03; | 471 | dma_bits = 0x03; |
471 | break; | 472 | break; |
472 | default: | 473 | default: |
473 | snd_printk("WSS dma1 # %d not valid\n", chip->dma1); | 474 | snd_printk(KERN_WARNING "WSS dma1 # %d not valid\n", |
475 | chip->dma1); | ||
474 | goto __skip_resources; | 476 | goto __skip_resources; |
475 | } | 477 | } |
476 | 478 | ||
477 | #if defined(CS4231) || defined(OPTi93X) | 479 | #if defined(CS4231) || defined(OPTi93X) |
478 | if (chip->dma1 == chip->dma2) { | 480 | if (chip->dma1 == chip->dma2) { |
479 | snd_printk("don't want to share dmas\n"); | 481 | snd_printk(KERN_ERR "don't want to share dmas\n"); |
480 | return -EBUSY; | 482 | return -EBUSY; |
481 | } | 483 | } |
482 | 484 | ||
@@ -485,7 +487,8 @@ __skip_base: | |||
485 | case 1: | 487 | case 1: |
486 | break; | 488 | break; |
487 | default: | 489 | default: |
488 | snd_printk("WSS dma2 # %d not valid\n", chip->dma2); | 490 | snd_printk(KERN_WARNING "WSS dma2 # %d not valid\n", |
491 | chip->dma2); | ||
489 | goto __skip_resources; | 492 | goto __skip_resources; |
490 | } | 493 | } |
491 | dma_bits |= 0x04; | 494 | dma_bits |= 0x04; |
@@ -516,7 +519,8 @@ __skip_resources: | |||
516 | mpu_port_bits = 0x00; | 519 | mpu_port_bits = 0x00; |
517 | break; | 520 | break; |
518 | default: | 521 | default: |
519 | snd_printk("MPU-401 port 0x%lx not valid\n", | 522 | snd_printk(KERN_WARNING |
523 | "MPU-401 port 0x%lx not valid\n", | ||
520 | chip->mpu_port); | 524 | chip->mpu_port); |
521 | goto __skip_mpu; | 525 | goto __skip_mpu; |
522 | } | 526 | } |
@@ -535,7 +539,7 @@ __skip_resources: | |||
535 | mpu_irq_bits = 0x01; | 539 | mpu_irq_bits = 0x01; |
536 | break; | 540 | break; |
537 | default: | 541 | default: |
538 | snd_printk("MPU-401 irq # %d not valid\n", | 542 | snd_printk(KERN_WARNING "MPU-401 irq # %d not valid\n", |
539 | chip->mpu_irq); | 543 | chip->mpu_irq); |
540 | goto __skip_mpu; | 544 | goto __skip_mpu; |
541 | } | 545 | } |
@@ -726,7 +730,7 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) | |||
726 | if (chip->wss_base == SNDRV_AUTO_PORT) { | 730 | if (chip->wss_base == SNDRV_AUTO_PORT) { |
727 | chip->wss_base = snd_legacy_find_free_ioport(possible_ports, 4); | 731 | chip->wss_base = snd_legacy_find_free_ioport(possible_ports, 4); |
728 | if (chip->wss_base < 0) { | 732 | if (chip->wss_base < 0) { |
729 | snd_printk("unable to find a free WSS port\n"); | 733 | snd_printk(KERN_ERR "unable to find a free WSS port\n"); |
730 | return -EBUSY; | 734 | return -EBUSY; |
731 | } | 735 | } |
732 | } | 736 | } |
@@ -815,14 +819,8 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) | |||
815 | chip->fm_port, chip->fm_port + 4 - 1); | 819 | chip->fm_port, chip->fm_port + 4 - 1); |
816 | } | 820 | } |
817 | if (opl3) { | 821 | if (opl3) { |
818 | #ifdef CS4231 | 822 | error = snd_opl3_hwdep_new(opl3, 0, 1, &synth); |
819 | const int t1dev = 1; | 823 | if (error < 0) |
820 | #else | ||
821 | const int t1dev = 0; | ||
822 | #endif | ||
823 | if ((error = snd_opl3_timer_new(opl3, t1dev, t1dev+1)) < 0) | ||
824 | return error; | ||
825 | if ((error = snd_opl3_hwdep_new(opl3, 0, 1, &synth)) < 0) | ||
826 | return error; | 824 | return error; |
827 | } | 825 | } |
828 | } | 826 | } |
@@ -830,15 +828,18 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) | |||
830 | return snd_card_register(card); | 828 | return snd_card_register(card); |
831 | } | 829 | } |
832 | 830 | ||
833 | static struct snd_card *snd_opti9xx_card_new(void) | 831 | static int snd_opti9xx_card_new(struct snd_card **cardp) |
834 | { | 832 | { |
835 | struct snd_card *card; | 833 | struct snd_card *card; |
834 | int err; | ||
836 | 835 | ||
837 | card = snd_card_new(index, id, THIS_MODULE, sizeof(struct snd_opti9xx)); | 836 | err = snd_card_create(index, id, THIS_MODULE, |
838 | if (! card) | 837 | sizeof(struct snd_opti9xx), &card); |
839 | return NULL; | 838 | if (err < 0) |
839 | return err; | ||
840 | card->private_free = snd_card_opti9xx_free; | 840 | card->private_free = snd_card_opti9xx_free; |
841 | return card; | 841 | *cardp = card; |
842 | return 0; | ||
842 | } | 843 | } |
843 | 844 | ||
844 | static int __devinit snd_opti9xx_isa_match(struct device *devptr, | 845 | static int __devinit snd_opti9xx_isa_match(struct device *devptr, |
@@ -897,15 +898,15 @@ static int __devinit snd_opti9xx_isa_probe(struct device *devptr, | |||
897 | #if defined(CS4231) || defined(OPTi93X) | 898 | #if defined(CS4231) || defined(OPTi93X) |
898 | if (dma2 == SNDRV_AUTO_DMA) { | 899 | if (dma2 == SNDRV_AUTO_DMA) { |
899 | if ((dma2 = snd_legacy_find_free_dma(possible_dma2s[dma1 % 4])) < 0) { | 900 | if ((dma2 = snd_legacy_find_free_dma(possible_dma2s[dma1 % 4])) < 0) { |
900 | snd_printk("unable to find a free DMA2\n"); | 901 | snd_printk(KERN_ERR "unable to find a free DMA2\n"); |
901 | return -EBUSY; | 902 | return -EBUSY; |
902 | } | 903 | } |
903 | } | 904 | } |
904 | #endif | 905 | #endif |
905 | 906 | ||
906 | card = snd_opti9xx_card_new(); | 907 | error = snd_opti9xx_card_new(&card); |
907 | if (! card) | 908 | if (error < 0) |
908 | return -ENOMEM; | 909 | return error; |
909 | 910 | ||
910 | if ((error = snd_card_opti9xx_detect(card, card->private_data)) < 0) { | 911 | if ((error = snd_card_opti9xx_detect(card, card->private_data)) < 0) { |
911 | snd_card_free(card); | 912 | snd_card_free(card); |
@@ -950,9 +951,9 @@ static int __devinit snd_opti9xx_pnp_probe(struct pnp_card_link *pcard, | |||
950 | return -EBUSY; | 951 | return -EBUSY; |
951 | if (! isapnp) | 952 | if (! isapnp) |
952 | return -ENODEV; | 953 | return -ENODEV; |
953 | card = snd_opti9xx_card_new(); | 954 | error = snd_opti9xx_card_new(&card); |
954 | if (! card) | 955 | if (error < 0) |
955 | return -ENOMEM; | 956 | return error; |
956 | chip = card->private_data; | 957 | chip = card->private_data; |
957 | 958 | ||
958 | hw = snd_card_opti9xx_pnp(chip, pcard, pid); | 959 | hw = snd_card_opti9xx_pnp(chip, pcard, pid); |
diff --git a/sound/isa/sb/es968.c b/sound/isa/sb/es968.c index c8c8e214c843..cafc3a7316a8 100644 --- a/sound/isa/sb/es968.c +++ b/sound/isa/sb/es968.c | |||
@@ -108,9 +108,10 @@ static int __devinit snd_card_es968_probe(int dev, | |||
108 | struct snd_card *card; | 108 | struct snd_card *card; |
109 | struct snd_card_es968 *acard; | 109 | struct snd_card_es968 *acard; |
110 | 110 | ||
111 | if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE, | 111 | error = snd_card_create(index[dev], id[dev], THIS_MODULE, |
112 | sizeof(struct snd_card_es968))) == NULL) | 112 | sizeof(struct snd_card_es968), &card); |
113 | return -ENOMEM; | 113 | if (error < 0) |
114 | return error; | ||
114 | acard = card->private_data; | 115 | acard = card->private_data; |
115 | if ((error = snd_card_es968_pnp(dev, acard, pcard, pid))) { | 116 | if ((error = snd_card_es968_pnp(dev, acard, pcard, pid))) { |
116 | snd_card_free(card); | 117 | snd_card_free(card); |
diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c index 2c201f78ce50..519c36346dec 100644 --- a/sound/isa/sb/sb16.c +++ b/sound/isa/sb/sb16.c | |||
@@ -324,14 +324,18 @@ static void snd_sb16_free(struct snd_card *card) | |||
324 | #define is_isapnp_selected(dev) 0 | 324 | #define is_isapnp_selected(dev) 0 |
325 | #endif | 325 | #endif |
326 | 326 | ||
327 | static struct snd_card *snd_sb16_card_new(int dev) | 327 | static int snd_sb16_card_new(int dev, struct snd_card **cardp) |
328 | { | 328 | { |
329 | struct snd_card *card = snd_card_new(index[dev], id[dev], THIS_MODULE, | 329 | struct snd_card *card; |
330 | sizeof(struct snd_card_sb16)); | 330 | int err; |
331 | if (card == NULL) | 331 | |
332 | return NULL; | 332 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, |
333 | sizeof(struct snd_card_sb16), &card); | ||
334 | if (err < 0) | ||
335 | return err; | ||
333 | card->private_free = snd_sb16_free; | 336 | card->private_free = snd_sb16_free; |
334 | return card; | 337 | *cardp = card; |
338 | return 0; | ||
335 | } | 339 | } |
336 | 340 | ||
337 | static int __devinit snd_sb16_probe(struct snd_card *card, int dev) | 341 | static int __devinit snd_sb16_probe(struct snd_card *card, int dev) |
@@ -489,9 +493,9 @@ static int __devinit snd_sb16_isa_probe1(int dev, struct device *pdev) | |||
489 | struct snd_card *card; | 493 | struct snd_card *card; |
490 | int err; | 494 | int err; |
491 | 495 | ||
492 | card = snd_sb16_card_new(dev); | 496 | err = snd_sb16_card_new(dev, &card); |
493 | if (! card) | 497 | if (err < 0) |
494 | return -ENOMEM; | 498 | return err; |
495 | 499 | ||
496 | acard = card->private_data; | 500 | acard = card->private_data; |
497 | /* non-PnP FM port address is hardwired with base port address */ | 501 | /* non-PnP FM port address is hardwired with base port address */ |
@@ -610,9 +614,9 @@ static int __devinit snd_sb16_pnp_detect(struct pnp_card_link *pcard, | |||
610 | for ( ; dev < SNDRV_CARDS; dev++) { | 614 | for ( ; dev < SNDRV_CARDS; dev++) { |
611 | if (!enable[dev] || !isapnp[dev]) | 615 | if (!enable[dev] || !isapnp[dev]) |
612 | continue; | 616 | continue; |
613 | card = snd_sb16_card_new(dev); | 617 | res = snd_sb16_card_new(dev, &card); |
614 | if (! card) | 618 | if (res < 0) |
615 | return -ENOMEM; | 619 | return res; |
616 | snd_card_set_dev(card, &pcard->card->dev); | 620 | snd_card_set_dev(card, &pcard->card->dev); |
617 | if ((res = snd_card_sb16_pnp(dev, card->private_data, pcard, pid)) < 0 || | 621 | if ((res = snd_card_sb16_pnp(dev, card->private_data, pcard, pid)) < 0 || |
618 | (res = snd_sb16_probe(card, dev)) < 0) { | 622 | (res = snd_sb16_probe(card, dev)) < 0) { |
diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c index ea06877be4b1..3cd57ee54660 100644 --- a/sound/isa/sb/sb8.c +++ b/sound/isa/sb/sb8.c | |||
@@ -103,10 +103,10 @@ static int __devinit snd_sb8_probe(struct device *pdev, unsigned int dev) | |||
103 | struct snd_opl3 *opl3; | 103 | struct snd_opl3 *opl3; |
104 | int err; | 104 | int err; |
105 | 105 | ||
106 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, | 106 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, |
107 | sizeof(struct snd_sb8)); | 107 | sizeof(struct snd_sb8), &card); |
108 | if (card == NULL) | 108 | if (err < 0) |
109 | return -ENOMEM; | 109 | return err; |
110 | acard = card->private_data; | 110 | acard = card->private_data; |
111 | card->private_free = snd_sb8_free; | 111 | card->private_free = snd_sb8_free; |
112 | 112 | ||
diff --git a/sound/isa/sb/sb_mixer.c b/sound/isa/sb/sb_mixer.c index 406a431af91e..475220bbcc96 100644 --- a/sound/isa/sb/sb_mixer.c +++ b/sound/isa/sb/sb_mixer.c | |||
@@ -182,7 +182,7 @@ static int snd_sbmixer_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
182 | 182 | ||
183 | static int snd_dt019x_input_sw_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 183 | static int snd_dt019x_input_sw_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) |
184 | { | 184 | { |
185 | static char *texts[5] = { | 185 | static const char *texts[5] = { |
186 | "CD", "Mic", "Line", "Synth", "Master" | 186 | "CD", "Mic", "Line", "Synth", "Master" |
187 | }; | 187 | }; |
188 | 188 | ||
@@ -269,12 +269,73 @@ static int snd_dt019x_input_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl | |||
269 | } | 269 | } |
270 | 270 | ||
271 | /* | 271 | /* |
272 | * ALS4000 mono recording control switch | ||
273 | */ | ||
274 | |||
275 | static int snd_als4k_mono_capture_route_info(struct snd_kcontrol *kcontrol, | ||
276 | struct snd_ctl_elem_info *uinfo) | ||
277 | { | ||
278 | static const char *texts[3] = { | ||
279 | "L chan only", "R chan only", "L ch/2 + R ch/2" | ||
280 | }; | ||
281 | |||
282 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
283 | uinfo->count = 1; | ||
284 | uinfo->value.enumerated.items = 3; | ||
285 | if (uinfo->value.enumerated.item > 2) | ||
286 | uinfo->value.enumerated.item = 2; | ||
287 | strcpy(uinfo->value.enumerated.name, | ||
288 | texts[uinfo->value.enumerated.item]); | ||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | static int snd_als4k_mono_capture_route_get(struct snd_kcontrol *kcontrol, | ||
293 | struct snd_ctl_elem_value *ucontrol) | ||
294 | { | ||
295 | struct snd_sb *sb = snd_kcontrol_chip(kcontrol); | ||
296 | unsigned long flags; | ||
297 | unsigned char oval; | ||
298 | |||
299 | spin_lock_irqsave(&sb->mixer_lock, flags); | ||
300 | oval = snd_sbmixer_read(sb, SB_ALS4000_MONO_IO_CTRL); | ||
301 | spin_unlock_irqrestore(&sb->mixer_lock, flags); | ||
302 | oval >>= 6; | ||
303 | if (oval > 2) | ||
304 | oval = 2; | ||
305 | |||
306 | ucontrol->value.enumerated.item[0] = oval; | ||
307 | return 0; | ||
308 | } | ||
309 | |||
310 | static int snd_als4k_mono_capture_route_put(struct snd_kcontrol *kcontrol, | ||
311 | struct snd_ctl_elem_value *ucontrol) | ||
312 | { | ||
313 | struct snd_sb *sb = snd_kcontrol_chip(kcontrol); | ||
314 | unsigned long flags; | ||
315 | int change; | ||
316 | unsigned char nval, oval; | ||
317 | |||
318 | if (ucontrol->value.enumerated.item[0] > 2) | ||
319 | return -EINVAL; | ||
320 | spin_lock_irqsave(&sb->mixer_lock, flags); | ||
321 | oval = snd_sbmixer_read(sb, SB_ALS4000_MONO_IO_CTRL); | ||
322 | |||
323 | nval = (oval & ~(3 << 6)) | ||
324 | | (ucontrol->value.enumerated.item[0] << 6); | ||
325 | change = nval != oval; | ||
326 | if (change) | ||
327 | snd_sbmixer_write(sb, SB_ALS4000_MONO_IO_CTRL, nval); | ||
328 | spin_unlock_irqrestore(&sb->mixer_lock, flags); | ||
329 | return change; | ||
330 | } | ||
331 | |||
332 | /* | ||
272 | * SBPRO input multiplexer | 333 | * SBPRO input multiplexer |
273 | */ | 334 | */ |
274 | 335 | ||
275 | static int snd_sb8mixer_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 336 | static int snd_sb8mixer_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) |
276 | { | 337 | { |
277 | static char *texts[3] = { | 338 | static const char *texts[3] = { |
278 | "Mic", "CD", "Line" | 339 | "Mic", "CD", "Line" |
279 | }; | 340 | }; |
280 | 341 | ||
@@ -442,6 +503,12 @@ int snd_sbmixer_add_ctl(struct snd_sb *chip, const char *name, int index, int ty | |||
442 | .get = snd_dt019x_input_sw_get, | 503 | .get = snd_dt019x_input_sw_get, |
443 | .put = snd_dt019x_input_sw_put, | 504 | .put = snd_dt019x_input_sw_put, |
444 | }, | 505 | }, |
506 | [SB_MIX_MONO_CAPTURE_ALS4K] = { | ||
507 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
508 | .info = snd_als4k_mono_capture_route_info, | ||
509 | .get = snd_als4k_mono_capture_route_get, | ||
510 | .put = snd_als4k_mono_capture_route_put, | ||
511 | }, | ||
445 | }; | 512 | }; |
446 | struct snd_kcontrol *ctl; | 513 | struct snd_kcontrol *ctl; |
447 | int err; | 514 | int err; |
@@ -636,6 +703,8 @@ static struct sbmix_elem snd_dt019x_ctl_capture_source = | |||
636 | }; | 703 | }; |
637 | 704 | ||
638 | static struct sbmix_elem *snd_dt019x_controls[] = { | 705 | static struct sbmix_elem *snd_dt019x_controls[] = { |
706 | /* ALS4000 below has some parts which we might be lacking, | ||
707 | * e.g. snd_als4000_ctl_mono_playback_switch - check it! */ | ||
639 | &snd_dt019x_ctl_master_play_vol, | 708 | &snd_dt019x_ctl_master_play_vol, |
640 | &snd_dt019x_ctl_pcm_play_vol, | 709 | &snd_dt019x_ctl_pcm_play_vol, |
641 | &snd_dt019x_ctl_synth_play_vol, | 710 | &snd_dt019x_ctl_synth_play_vol, |
@@ -666,18 +735,21 @@ static unsigned char snd_dt019x_init_values[][2] = { | |||
666 | /* | 735 | /* |
667 | * ALS4000 specific mixer elements | 736 | * ALS4000 specific mixer elements |
668 | */ | 737 | */ |
669 | /* FIXME: SB_ALS4000_MONO_IO_CTRL needs output select ctrl! */ | ||
670 | static struct sbmix_elem snd_als4000_ctl_master_mono_playback_switch = | 738 | static struct sbmix_elem snd_als4000_ctl_master_mono_playback_switch = |
671 | SB_SINGLE("Master Mono Playback Switch", SB_ALS4000_MONO_IO_CTRL, 5, 1); | 739 | SB_SINGLE("Master Mono Playback Switch", SB_ALS4000_MONO_IO_CTRL, 5, 1); |
672 | static struct sbmix_elem snd_als4000_ctl_master_mono_capture_route = | 740 | static struct sbmix_elem snd_als4k_ctl_master_mono_capture_route = { |
673 | SB_SINGLE("Master Mono Capture Route", SB_ALS4000_MONO_IO_CTRL, 6, 0x03); | 741 | .name = "Master Mono Capture Route", |
674 | /* FIXME: mono playback switch also available on DT019X? */ | 742 | .type = SB_MIX_MONO_CAPTURE_ALS4K |
743 | }; | ||
675 | static struct sbmix_elem snd_als4000_ctl_mono_playback_switch = | 744 | static struct sbmix_elem snd_als4000_ctl_mono_playback_switch = |
676 | SB_SINGLE("Mono Playback Switch", SB_DT019X_OUTPUT_SW2, 0, 1); | 745 | SB_SINGLE("Mono Playback Switch", SB_DT019X_OUTPUT_SW2, 0, 1); |
677 | static struct sbmix_elem snd_als4000_ctl_mic_20db_boost = | 746 | static struct sbmix_elem snd_als4000_ctl_mic_20db_boost = |
678 | SB_SINGLE("Mic Boost (+20dB)", SB_ALS4000_MIC_IN_GAIN, 0, 0x03); | 747 | SB_SINGLE("Mic Boost (+20dB)", SB_ALS4000_MIC_IN_GAIN, 0, 0x03); |
679 | static struct sbmix_elem snd_als4000_ctl_mixer_loopback = | 748 | static struct sbmix_elem snd_als4000_ctl_mixer_analog_loopback = |
680 | SB_SINGLE("Analog Loopback", SB_ALS4000_MIC_IN_GAIN, 7, 0x01); | 749 | SB_SINGLE("Analog Loopback Switch", SB_ALS4000_MIC_IN_GAIN, 7, 0x01); |
750 | static struct sbmix_elem snd_als4000_ctl_mixer_digital_loopback = | ||
751 | SB_SINGLE("Digital Loopback Switch", | ||
752 | SB_ALS4000_CR3_CONFIGURATION, 7, 0x01); | ||
681 | /* FIXME: functionality of 3D controls might be swapped, I didn't find | 753 | /* FIXME: functionality of 3D controls might be swapped, I didn't find |
682 | * a description of how to identify what is supposed to be what */ | 754 | * a description of how to identify what is supposed to be what */ |
683 | static struct sbmix_elem snd_als4000_3d_control_switch = | 755 | static struct sbmix_elem snd_als4000_3d_control_switch = |
@@ -694,6 +766,9 @@ static struct sbmix_elem snd_als4000_3d_control_delay = | |||
694 | SB_SINGLE("3D Control - Wide", SB_ALS4000_3D_TIME_DELAY, 0, 0x0f); | 766 | SB_SINGLE("3D Control - Wide", SB_ALS4000_3D_TIME_DELAY, 0, 0x0f); |
695 | static struct sbmix_elem snd_als4000_3d_control_poweroff_switch = | 767 | static struct sbmix_elem snd_als4000_3d_control_poweroff_switch = |
696 | SB_SINGLE("3D PowerOff Switch", SB_ALS4000_3D_TIME_DELAY, 4, 0x01); | 768 | SB_SINGLE("3D PowerOff Switch", SB_ALS4000_3D_TIME_DELAY, 4, 0x01); |
769 | static struct sbmix_elem snd_als4000_ctl_3db_freq_control_switch = | ||
770 | SB_SINGLE("Master Playback 8kHz / 20kHz LPF Switch", | ||
771 | SB_ALS4000_FMDAC, 5, 0x01); | ||
697 | #ifdef NOT_AVAILABLE | 772 | #ifdef NOT_AVAILABLE |
698 | static struct sbmix_elem snd_als4000_ctl_fmdac = | 773 | static struct sbmix_elem snd_als4000_ctl_fmdac = |
699 | SB_SINGLE("FMDAC Switch (Option ?)", SB_ALS4000_FMDAC, 0, 0x01); | 774 | SB_SINGLE("FMDAC Switch (Option ?)", SB_ALS4000_FMDAC, 0, 0x01); |
@@ -702,35 +777,37 @@ static struct sbmix_elem snd_als4000_ctl_qsound = | |||
702 | #endif | 777 | #endif |
703 | 778 | ||
704 | static struct sbmix_elem *snd_als4000_controls[] = { | 779 | static struct sbmix_elem *snd_als4000_controls[] = { |
705 | &snd_sb16_ctl_master_play_vol, | 780 | /* ALS4000a.PDF regs page */ |
706 | &snd_dt019x_ctl_pcm_play_switch, | 781 | &snd_sb16_ctl_master_play_vol, /* MX30/31 12 */ |
707 | &snd_sb16_ctl_pcm_play_vol, | 782 | &snd_dt019x_ctl_pcm_play_switch, /* MX4C 16 */ |
708 | &snd_sb16_ctl_synth_capture_route, | 783 | &snd_sb16_ctl_pcm_play_vol, /* MX32/33 12 */ |
709 | &snd_dt019x_ctl_synth_play_switch, | 784 | &snd_sb16_ctl_synth_capture_route, /* MX3D/3E 14 */ |
710 | &snd_sb16_ctl_synth_play_vol, | 785 | &snd_dt019x_ctl_synth_play_switch, /* MX4C 16 */ |
711 | &snd_sb16_ctl_cd_capture_route, | 786 | &snd_sb16_ctl_synth_play_vol, /* MX34/35 12/13 */ |
712 | &snd_sb16_ctl_cd_play_switch, | 787 | &snd_sb16_ctl_cd_capture_route, /* MX3D/3E 14 */ |
713 | &snd_sb16_ctl_cd_play_vol, | 788 | &snd_sb16_ctl_cd_play_switch, /* MX3C 14 */ |
714 | &snd_sb16_ctl_line_capture_route, | 789 | &snd_sb16_ctl_cd_play_vol, /* MX36/37 13 */ |
715 | &snd_sb16_ctl_line_play_switch, | 790 | &snd_sb16_ctl_line_capture_route, /* MX3D/3E 14 */ |
716 | &snd_sb16_ctl_line_play_vol, | 791 | &snd_sb16_ctl_line_play_switch, /* MX3C 14 */ |
717 | &snd_sb16_ctl_mic_capture_route, | 792 | &snd_sb16_ctl_line_play_vol, /* MX38/39 13 */ |
718 | &snd_als4000_ctl_mic_20db_boost, | 793 | &snd_sb16_ctl_mic_capture_route, /* MX3D/3E 14 */ |
719 | &snd_sb16_ctl_auto_mic_gain, | 794 | &snd_als4000_ctl_mic_20db_boost, /* MX4D 16 */ |
720 | &snd_sb16_ctl_mic_play_switch, | 795 | &snd_sb16_ctl_mic_play_switch, /* MX3C 14 */ |
721 | &snd_sb16_ctl_mic_play_vol, | 796 | &snd_sb16_ctl_mic_play_vol, /* MX3A 13 */ |
722 | &snd_sb16_ctl_pc_speaker_vol, | 797 | &snd_sb16_ctl_pc_speaker_vol, /* MX3B 14 */ |
723 | &snd_sb16_ctl_capture_vol, | 798 | &snd_sb16_ctl_capture_vol, /* MX3F/40 15 */ |
724 | &snd_sb16_ctl_play_vol, | 799 | &snd_sb16_ctl_play_vol, /* MX41/42 15 */ |
725 | &snd_als4000_ctl_master_mono_playback_switch, | 800 | &snd_als4000_ctl_master_mono_playback_switch, /* MX4C 16 */ |
726 | &snd_als4000_ctl_master_mono_capture_route, | 801 | &snd_als4k_ctl_master_mono_capture_route, /* MX4B 16 */ |
727 | &snd_als4000_ctl_mono_playback_switch, | 802 | &snd_als4000_ctl_mono_playback_switch, /* MX4C 16 */ |
728 | &snd_als4000_ctl_mixer_loopback, | 803 | &snd_als4000_ctl_mixer_analog_loopback, /* MX4D 16 */ |
729 | &snd_als4000_3d_control_switch, | 804 | &snd_als4000_ctl_mixer_digital_loopback, /* CR3 21 */ |
730 | &snd_als4000_3d_control_ratio, | 805 | &snd_als4000_3d_control_switch, /* MX50 17 */ |
731 | &snd_als4000_3d_control_freq, | 806 | &snd_als4000_3d_control_ratio, /* MX50 17 */ |
732 | &snd_als4000_3d_control_delay, | 807 | &snd_als4000_3d_control_freq, /* MX50 17 */ |
733 | &snd_als4000_3d_control_poweroff_switch, | 808 | &snd_als4000_3d_control_delay, /* MX51 18 */ |
809 | &snd_als4000_3d_control_poweroff_switch, /* MX51 18 */ | ||
810 | &snd_als4000_ctl_3db_freq_control_switch, /* MX4F 17 */ | ||
734 | #ifdef NOT_AVAILABLE | 811 | #ifdef NOT_AVAILABLE |
735 | &snd_als4000_ctl_fmdac, | 812 | &snd_als4000_ctl_fmdac, |
736 | &snd_als4000_ctl_qsound, | 813 | &snd_als4000_ctl_qsound, |
@@ -905,13 +982,14 @@ static unsigned char dt019x_saved_regs[] = { | |||
905 | }; | 982 | }; |
906 | 983 | ||
907 | static unsigned char als4000_saved_regs[] = { | 984 | static unsigned char als4000_saved_regs[] = { |
985 | /* please verify in dsheet whether regs to be added | ||
986 | are actually real H/W or just dummy */ | ||
908 | SB_DSP4_MASTER_DEV, SB_DSP4_MASTER_DEV + 1, | 987 | SB_DSP4_MASTER_DEV, SB_DSP4_MASTER_DEV + 1, |
909 | SB_DSP4_OUTPUT_SW, | 988 | SB_DSP4_OUTPUT_SW, |
910 | SB_DSP4_PCM_DEV, SB_DSP4_PCM_DEV + 1, | 989 | SB_DSP4_PCM_DEV, SB_DSP4_PCM_DEV + 1, |
911 | SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, | 990 | SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, |
912 | SB_DSP4_SYNTH_DEV, SB_DSP4_SYNTH_DEV + 1, | 991 | SB_DSP4_SYNTH_DEV, SB_DSP4_SYNTH_DEV + 1, |
913 | SB_DSP4_CD_DEV, SB_DSP4_CD_DEV + 1, | 992 | SB_DSP4_CD_DEV, SB_DSP4_CD_DEV + 1, |
914 | SB_DSP4_MIC_AGC, | ||
915 | SB_DSP4_MIC_DEV, | 993 | SB_DSP4_MIC_DEV, |
916 | SB_DSP4_SPEAKER_DEV, | 994 | SB_DSP4_SPEAKER_DEV, |
917 | SB_DSP4_IGAIN_DEV, SB_DSP4_IGAIN_DEV + 1, | 995 | SB_DSP4_IGAIN_DEV, SB_DSP4_IGAIN_DEV + 1, |
@@ -919,8 +997,10 @@ static unsigned char als4000_saved_regs[] = { | |||
919 | SB_DT019X_OUTPUT_SW2, | 997 | SB_DT019X_OUTPUT_SW2, |
920 | SB_ALS4000_MONO_IO_CTRL, | 998 | SB_ALS4000_MONO_IO_CTRL, |
921 | SB_ALS4000_MIC_IN_GAIN, | 999 | SB_ALS4000_MIC_IN_GAIN, |
1000 | SB_ALS4000_FMDAC, | ||
922 | SB_ALS4000_3D_SND_FX, | 1001 | SB_ALS4000_3D_SND_FX, |
923 | SB_ALS4000_3D_TIME_DELAY, | 1002 | SB_ALS4000_3D_TIME_DELAY, |
1003 | SB_ALS4000_CR3_CONFIGURATION, | ||
924 | }; | 1004 | }; |
925 | 1005 | ||
926 | static void save_mixer(struct snd_sb *chip, unsigned char *regs, int num_regs) | 1006 | static void save_mixer(struct snd_sb *chip, unsigned char *regs, int num_regs) |
diff --git a/sound/isa/sc6000.c b/sound/isa/sc6000.c index ca35924dc3b3..782010608ef4 100644 --- a/sound/isa/sc6000.c +++ b/sound/isa/sc6000.c | |||
@@ -489,9 +489,9 @@ static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev) | |||
489 | char __iomem *vmss_port; | 489 | char __iomem *vmss_port; |
490 | 490 | ||
491 | 491 | ||
492 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 492 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); |
493 | if (!card) | 493 | if (err < 0) |
494 | return -ENOMEM; | 494 | return err; |
495 | 495 | ||
496 | if (xirq == SNDRV_AUTO_IRQ) { | 496 | if (xirq == SNDRV_AUTO_IRQ) { |
497 | xirq = snd_legacy_find_free_irq(possible_irqs); | 497 | xirq = snd_legacy_find_free_irq(possible_irqs); |
@@ -576,10 +576,6 @@ static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev) | |||
576 | snd_printk(KERN_ERR PFX "no OPL device at 0x%x-0x%x ?\n", | 576 | snd_printk(KERN_ERR PFX "no OPL device at 0x%x-0x%x ?\n", |
577 | 0x388, 0x388 + 2); | 577 | 0x388, 0x388 + 2); |
578 | } else { | 578 | } else { |
579 | err = snd_opl3_timer_new(opl3, 0, 1); | ||
580 | if (err < 0) | ||
581 | goto err_unmap2; | ||
582 | |||
583 | err = snd_opl3_hwdep_new(opl3, 0, 1, NULL); | 579 | err = snd_opl3_hwdep_new(opl3, 0, 1, NULL); |
584 | if (err < 0) | 580 | if (err < 0) |
585 | goto err_unmap2; | 581 | goto err_unmap2; |
diff --git a/sound/isa/sgalaxy.c b/sound/isa/sgalaxy.c index 2c7503bf1271..6fe27b9d9440 100644 --- a/sound/isa/sgalaxy.c +++ b/sound/isa/sgalaxy.c | |||
@@ -243,9 +243,9 @@ static int __devinit snd_sgalaxy_probe(struct device *devptr, unsigned int dev) | |||
243 | struct snd_card *card; | 243 | struct snd_card *card; |
244 | struct snd_wss *chip; | 244 | struct snd_wss *chip; |
245 | 245 | ||
246 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 246 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); |
247 | if (card == NULL) | 247 | if (err < 0) |
248 | return -ENOMEM; | 248 | return err; |
249 | 249 | ||
250 | xirq = irq[dev]; | 250 | xirq = irq[dev]; |
251 | if (xirq == SNDRV_AUTO_IRQ) { | 251 | if (xirq == SNDRV_AUTO_IRQ) { |
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c index 48a16d865834..66187122377c 100644 --- a/sound/isa/sscape.c +++ b/sound/isa/sscape.c | |||
@@ -89,9 +89,6 @@ MODULE_DEVICE_TABLE(pnp_card, sscape_pnpids); | |||
89 | #endif | 89 | #endif |
90 | 90 | ||
91 | 91 | ||
92 | #define MPU401_IO(i) ((i) + 0) | ||
93 | #define MIDI_DATA_IO(i) ((i) + 0) | ||
94 | #define MIDI_CTRL_IO(i) ((i) + 1) | ||
95 | #define HOST_CTRL_IO(i) ((i) + 2) | 92 | #define HOST_CTRL_IO(i) ((i) + 2) |
96 | #define HOST_DATA_IO(i) ((i) + 3) | 93 | #define HOST_DATA_IO(i) ((i) + 3) |
97 | #define ODIE_ADDR_IO(i) ((i) + 4) | 94 | #define ODIE_ADDR_IO(i) ((i) + 4) |
@@ -129,9 +126,6 @@ enum GA_REG { | |||
129 | #define DMA_8BIT 0x80 | 126 | #define DMA_8BIT 0x80 |
130 | 127 | ||
131 | 128 | ||
132 | #define AD1845_FREQ_SEL_MSB 0x16 | ||
133 | #define AD1845_FREQ_SEL_LSB 0x17 | ||
134 | |||
135 | enum card_type { | 129 | enum card_type { |
136 | SSCAPE, | 130 | SSCAPE, |
137 | SSCAPE_PNP, | 131 | SSCAPE_PNP, |
@@ -141,8 +135,6 @@ enum card_type { | |||
141 | struct soundscape { | 135 | struct soundscape { |
142 | spinlock_t lock; | 136 | spinlock_t lock; |
143 | unsigned io_base; | 137 | unsigned io_base; |
144 | unsigned wss_base; | ||
145 | int codec_type; | ||
146 | int ic_type; | 138 | int ic_type; |
147 | enum card_type type; | 139 | enum card_type type; |
148 | struct resource *io_res; | 140 | struct resource *io_res; |
@@ -330,7 +322,7 @@ static int host_write_ctrl_unsafe(unsigned io_base, unsigned char data, | |||
330 | */ | 322 | */ |
331 | static inline int verify_mpu401(const struct snd_mpu401 * mpu) | 323 | static inline int verify_mpu401(const struct snd_mpu401 * mpu) |
332 | { | 324 | { |
333 | return ((inb(MIDI_CTRL_IO(mpu->port)) & 0xc0) == 0x80); | 325 | return ((inb(MPU401C(mpu)) & 0xc0) == 0x80); |
334 | } | 326 | } |
335 | 327 | ||
336 | /* | 328 | /* |
@@ -338,7 +330,7 @@ static inline int verify_mpu401(const struct snd_mpu401 * mpu) | |||
338 | */ | 330 | */ |
339 | static inline void initialise_mpu401(const struct snd_mpu401 * mpu) | 331 | static inline void initialise_mpu401(const struct snd_mpu401 * mpu) |
340 | { | 332 | { |
341 | outb(0, MIDI_DATA_IO(mpu->port)); | 333 | outb(0, MPU401D(mpu)); |
342 | } | 334 | } |
343 | 335 | ||
344 | /* | 336 | /* |
@@ -396,20 +388,20 @@ static int sscape_wait_dma_unsafe(unsigned io_base, enum GA_REG reg, unsigned ti | |||
396 | */ | 388 | */ |
397 | static int obp_startup_ack(struct soundscape *s, unsigned timeout) | 389 | static int obp_startup_ack(struct soundscape *s, unsigned timeout) |
398 | { | 390 | { |
399 | while (timeout != 0) { | 391 | unsigned long end_time = jiffies + msecs_to_jiffies(timeout); |
392 | |||
393 | do { | ||
400 | unsigned long flags; | 394 | unsigned long flags; |
401 | unsigned char x; | 395 | unsigned char x; |
402 | 396 | ||
403 | schedule_timeout_uninterruptible(1); | ||
404 | |||
405 | spin_lock_irqsave(&s->lock, flags); | 397 | spin_lock_irqsave(&s->lock, flags); |
406 | x = inb(HOST_DATA_IO(s->io_base)); | 398 | x = inb(HOST_DATA_IO(s->io_base)); |
407 | spin_unlock_irqrestore(&s->lock, flags); | 399 | spin_unlock_irqrestore(&s->lock, flags); |
408 | if ((x & 0xfe) == 0xfe) | 400 | if ((x & 0xfe) == 0xfe) |
409 | return 1; | 401 | return 1; |
410 | 402 | ||
411 | --timeout; | 403 | msleep(10); |
412 | } /* while */ | 404 | } while (time_before(jiffies, end_time)); |
413 | 405 | ||
414 | return 0; | 406 | return 0; |
415 | } | 407 | } |
@@ -423,20 +415,20 @@ static int obp_startup_ack(struct soundscape *s, unsigned timeout) | |||
423 | */ | 415 | */ |
424 | static int host_startup_ack(struct soundscape *s, unsigned timeout) | 416 | static int host_startup_ack(struct soundscape *s, unsigned timeout) |
425 | { | 417 | { |
426 | while (timeout != 0) { | 418 | unsigned long end_time = jiffies + msecs_to_jiffies(timeout); |
419 | |||
420 | do { | ||
427 | unsigned long flags; | 421 | unsigned long flags; |
428 | unsigned char x; | 422 | unsigned char x; |
429 | 423 | ||
430 | schedule_timeout_uninterruptible(1); | ||
431 | |||
432 | spin_lock_irqsave(&s->lock, flags); | 424 | spin_lock_irqsave(&s->lock, flags); |
433 | x = inb(HOST_DATA_IO(s->io_base)); | 425 | x = inb(HOST_DATA_IO(s->io_base)); |
434 | spin_unlock_irqrestore(&s->lock, flags); | 426 | spin_unlock_irqrestore(&s->lock, flags); |
435 | if (x == 0xfe) | 427 | if (x == 0xfe) |
436 | return 1; | 428 | return 1; |
437 | 429 | ||
438 | --timeout; | 430 | msleep(10); |
439 | } /* while */ | 431 | } while (time_before(jiffies, end_time)); |
440 | 432 | ||
441 | return 0; | 433 | return 0; |
442 | } | 434 | } |
@@ -532,10 +524,10 @@ static int upload_dma_data(struct soundscape *s, | |||
532 | * give it 5 seconds (max) ... | 524 | * give it 5 seconds (max) ... |
533 | */ | 525 | */ |
534 | ret = 0; | 526 | ret = 0; |
535 | if (!obp_startup_ack(s, 5)) { | 527 | if (!obp_startup_ack(s, 5000)) { |
536 | snd_printk(KERN_ERR "sscape: No response from on-board processor after upload\n"); | 528 | snd_printk(KERN_ERR "sscape: No response from on-board processor after upload\n"); |
537 | ret = -EAGAIN; | 529 | ret = -EAGAIN; |
538 | } else if (!host_startup_ack(s, 5)) { | 530 | } else if (!host_startup_ack(s, 5000)) { |
539 | snd_printk(KERN_ERR "sscape: SoundScape failed to initialise\n"); | 531 | snd_printk(KERN_ERR "sscape: SoundScape failed to initialise\n"); |
540 | ret = -EAGAIN; | 532 | ret = -EAGAIN; |
541 | } | 533 | } |
@@ -732,13 +724,7 @@ static int sscape_midi_get(struct snd_kcontrol *kctl, | |||
732 | unsigned long flags; | 724 | unsigned long flags; |
733 | 725 | ||
734 | spin_lock_irqsave(&s->lock, flags); | 726 | spin_lock_irqsave(&s->lock, flags); |
735 | set_host_mode_unsafe(s->io_base); | 727 | uctl->value.integer.value[0] = s->midi_vol; |
736 | |||
737 | if (host_write_ctrl_unsafe(s->io_base, CMD_GET_MIDI_VOL, 100)) { | ||
738 | uctl->value.integer.value[0] = host_read_ctrl_unsafe(s->io_base, 100); | ||
739 | } | ||
740 | |||
741 | set_midi_mode_unsafe(s->io_base); | ||
742 | spin_unlock_irqrestore(&s->lock, flags); | 728 | spin_unlock_irqrestore(&s->lock, flags); |
743 | return 0; | 729 | return 0; |
744 | } | 730 | } |
@@ -773,6 +759,7 @@ static int sscape_midi_put(struct snd_kcontrol *kctl, | |||
773 | change = (host_write_ctrl_unsafe(s->io_base, CMD_SET_MIDI_VOL, 100) | 759 | change = (host_write_ctrl_unsafe(s->io_base, CMD_SET_MIDI_VOL, 100) |
774 | && host_write_ctrl_unsafe(s->io_base, ((unsigned char) uctl->value.integer. value[0]) & 127, 100) | 760 | && host_write_ctrl_unsafe(s->io_base, ((unsigned char) uctl->value.integer. value[0]) & 127, 100) |
775 | && host_write_ctrl_unsafe(s->io_base, CMD_XXX_MIDI_VOL, 100)); | 761 | && host_write_ctrl_unsafe(s->io_base, CMD_XXX_MIDI_VOL, 100)); |
762 | s->midi_vol = (unsigned char) uctl->value.integer.value[0] & 127; | ||
776 | __skip_change: | 763 | __skip_change: |
777 | 764 | ||
778 | /* | 765 | /* |
@@ -815,12 +802,11 @@ static unsigned __devinit get_irq_config(int irq) | |||
815 | * Perform certain arcane port-checks to see whether there | 802 | * Perform certain arcane port-checks to see whether there |
816 | * is a SoundScape board lurking behind the given ports. | 803 | * is a SoundScape board lurking behind the given ports. |
817 | */ | 804 | */ |
818 | static int __devinit detect_sscape(struct soundscape *s) | 805 | static int __devinit detect_sscape(struct soundscape *s, long wss_io) |
819 | { | 806 | { |
820 | unsigned long flags; | 807 | unsigned long flags; |
821 | unsigned d; | 808 | unsigned d; |
822 | int retval = 0; | 809 | int retval = 0; |
823 | int codec = s->wss_base; | ||
824 | 810 | ||
825 | spin_lock_irqsave(&s->lock, flags); | 811 | spin_lock_irqsave(&s->lock, flags); |
826 | 812 | ||
@@ -836,13 +822,11 @@ static int __devinit detect_sscape(struct soundscape *s) | |||
836 | if ((d & 0x80) != 0) | 822 | if ((d & 0x80) != 0) |
837 | goto _done; | 823 | goto _done; |
838 | 824 | ||
839 | if (d == 0) { | 825 | if (d == 0) |
840 | s->codec_type = 1; | ||
841 | s->ic_type = IC_ODIE; | 826 | s->ic_type = IC_ODIE; |
842 | } else if ((d & 0x60) != 0) { | 827 | else if ((d & 0x60) != 0) |
843 | s->codec_type = 2; | ||
844 | s->ic_type = IC_OPUS; | 828 | s->ic_type = IC_OPUS; |
845 | } else | 829 | else |
846 | goto _done; | 830 | goto _done; |
847 | 831 | ||
848 | outb(0xfa, ODIE_ADDR_IO(s->io_base)); | 832 | outb(0xfa, ODIE_ADDR_IO(s->io_base)); |
@@ -862,10 +846,10 @@ static int __devinit detect_sscape(struct soundscape *s) | |||
862 | sscape_write_unsafe(s->io_base, GA_HMCTL_REG, d | 0xc0); | 846 | sscape_write_unsafe(s->io_base, GA_HMCTL_REG, d | 0xc0); |
863 | 847 | ||
864 | if (s->type == SSCAPE_VIVO) | 848 | if (s->type == SSCAPE_VIVO) |
865 | codec += 4; | 849 | wss_io += 4; |
866 | /* wait for WSS codec */ | 850 | /* wait for WSS codec */ |
867 | for (d = 0; d < 500; d++) { | 851 | for (d = 0; d < 500; d++) { |
868 | if ((inb(codec) & 0x80) == 0) | 852 | if ((inb(wss_io) & 0x80) == 0) |
869 | break; | 853 | break; |
870 | spin_unlock_irqrestore(&s->lock, flags); | 854 | spin_unlock_irqrestore(&s->lock, flags); |
871 | msleep(1); | 855 | msleep(1); |
@@ -955,82 +939,6 @@ static int __devinit create_mpu401(struct snd_card *card, int devnum, unsigned l | |||
955 | 939 | ||
956 | 940 | ||
957 | /* | 941 | /* |
958 | * Override for the CS4231 playback format function. | ||
959 | * The AD1845 has much simpler format and rate selection. | ||
960 | */ | ||
961 | static void ad1845_playback_format(struct snd_wss *chip, | ||
962 | struct snd_pcm_hw_params *params, | ||
963 | unsigned char format) | ||
964 | { | ||
965 | unsigned long flags; | ||
966 | unsigned rate = params_rate(params); | ||
967 | |||
968 | /* | ||
969 | * The AD1845 can't handle sample frequencies | ||
970 | * outside of 4 kHZ to 50 kHZ | ||
971 | */ | ||
972 | if (rate > 50000) | ||
973 | rate = 50000; | ||
974 | else if (rate < 4000) | ||
975 | rate = 4000; | ||
976 | |||
977 | spin_lock_irqsave(&chip->reg_lock, flags); | ||
978 | |||
979 | /* | ||
980 | * Program the AD1845 correctly for the playback stream. | ||
981 | * Note that we do NOT need to toggle the MCE bit because | ||
982 | * the PLAYBACK_ENABLE bit of the Interface Configuration | ||
983 | * register is set. | ||
984 | * | ||
985 | * NOTE: We seem to need to write to the MSB before the LSB | ||
986 | * to get the correct sample frequency. | ||
987 | */ | ||
988 | snd_wss_out(chip, CS4231_PLAYBK_FORMAT, (format & 0xf0)); | ||
989 | snd_wss_out(chip, AD1845_FREQ_SEL_MSB, (unsigned char) (rate >> 8)); | ||
990 | snd_wss_out(chip, AD1845_FREQ_SEL_LSB, (unsigned char) rate); | ||
991 | |||
992 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
993 | } | ||
994 | |||
995 | /* | ||
996 | * Override for the CS4231 capture format function. | ||
997 | * The AD1845 has much simpler format and rate selection. | ||
998 | */ | ||
999 | static void ad1845_capture_format(struct snd_wss *chip, | ||
1000 | struct snd_pcm_hw_params *params, | ||
1001 | unsigned char format) | ||
1002 | { | ||
1003 | unsigned long flags; | ||
1004 | unsigned rate = params_rate(params); | ||
1005 | |||
1006 | /* | ||
1007 | * The AD1845 can't handle sample frequencies | ||
1008 | * outside of 4 kHZ to 50 kHZ | ||
1009 | */ | ||
1010 | if (rate > 50000) | ||
1011 | rate = 50000; | ||
1012 | else if (rate < 4000) | ||
1013 | rate = 4000; | ||
1014 | |||
1015 | spin_lock_irqsave(&chip->reg_lock, flags); | ||
1016 | |||
1017 | /* | ||
1018 | * Program the AD1845 correctly for the playback stream. | ||
1019 | * Note that we do NOT need to toggle the MCE bit because | ||
1020 | * the CAPTURE_ENABLE bit of the Interface Configuration | ||
1021 | * register is set. | ||
1022 | * | ||
1023 | * NOTE: We seem to need to write to the MSB before the LSB | ||
1024 | * to get the correct sample frequency. | ||
1025 | */ | ||
1026 | snd_wss_out(chip, CS4231_REC_FORMAT, (format & 0xf0)); | ||
1027 | snd_wss_out(chip, AD1845_FREQ_SEL_MSB, (unsigned char) (rate >> 8)); | ||
1028 | snd_wss_out(chip, AD1845_FREQ_SEL_LSB, (unsigned char) rate); | ||
1029 | |||
1030 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
1031 | } | ||
1032 | |||
1033 | /* | ||
1034 | * Create an AD1845 PCM subdevice on the SoundScape. The AD1845 | 942 | * Create an AD1845 PCM subdevice on the SoundScape. The AD1845 |
1035 | * is very much like a CS4231, with a few extra bits. We will | 943 | * is very much like a CS4231, with a few extra bits. We will |
1036 | * try to support at least some of the extra bits by overriding | 944 | * try to support at least some of the extra bits by overriding |
@@ -1055,11 +963,6 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port, | |||
1055 | unsigned long flags; | 963 | unsigned long flags; |
1056 | struct snd_pcm *pcm; | 964 | struct snd_pcm *pcm; |
1057 | 965 | ||
1058 | #define AD1845_FREQ_SEL_ENABLE 0x08 | ||
1059 | |||
1060 | #define AD1845_PWR_DOWN_CTRL 0x1b | ||
1061 | #define AD1845_CRYS_CLOCK_SEL 0x1d | ||
1062 | |||
1063 | /* | 966 | /* |
1064 | * It turns out that the PLAYBACK_ENABLE bit is set | 967 | * It turns out that the PLAYBACK_ENABLE bit is set |
1065 | * by the lowlevel driver ... | 968 | * by the lowlevel driver ... |
@@ -1074,7 +977,6 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port, | |||
1074 | */ | 977 | */ |
1075 | 978 | ||
1076 | if (sscape->type != SSCAPE_VIVO) { | 979 | if (sscape->type != SSCAPE_VIVO) { |
1077 | int val; | ||
1078 | /* | 980 | /* |
1079 | * The input clock frequency on the SoundScape must | 981 | * The input clock frequency on the SoundScape must |
1080 | * be 14.31818 MHz, because we must set this register | 982 | * be 14.31818 MHz, because we must set this register |
@@ -1082,22 +984,10 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port, | |||
1082 | */ | 984 | */ |
1083 | snd_wss_mce_up(chip); | 985 | snd_wss_mce_up(chip); |
1084 | spin_lock_irqsave(&chip->reg_lock, flags); | 986 | spin_lock_irqsave(&chip->reg_lock, flags); |
1085 | snd_wss_out(chip, AD1845_CRYS_CLOCK_SEL, 0x20); | 987 | snd_wss_out(chip, AD1845_CLOCK, 0x20); |
1086 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 988 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
1087 | snd_wss_mce_down(chip); | 989 | snd_wss_mce_down(chip); |
1088 | 990 | ||
1089 | /* | ||
1090 | * More custom configuration: | ||
1091 | * a) select "mode 2" and provide a current drive of 8mA | ||
1092 | * b) enable frequency selection (for capture/playback) | ||
1093 | */ | ||
1094 | spin_lock_irqsave(&chip->reg_lock, flags); | ||
1095 | snd_wss_out(chip, CS4231_MISC_INFO, | ||
1096 | CS4231_MODE2 | 0x10); | ||
1097 | val = snd_wss_in(chip, AD1845_PWR_DOWN_CTRL); | ||
1098 | snd_wss_out(chip, AD1845_PWR_DOWN_CTRL, | ||
1099 | val | AD1845_FREQ_SEL_ENABLE); | ||
1100 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
1101 | } | 991 | } |
1102 | 992 | ||
1103 | err = snd_wss_pcm(chip, 0, &pcm); | 993 | err = snd_wss_pcm(chip, 0, &pcm); |
@@ -1113,11 +1003,13 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port, | |||
1113 | "for AD1845 chip\n"); | 1003 | "for AD1845 chip\n"); |
1114 | goto _error; | 1004 | goto _error; |
1115 | } | 1005 | } |
1116 | err = snd_wss_timer(chip, 0, NULL); | 1006 | if (chip->hardware != WSS_HW_AD1848) { |
1117 | if (err < 0) { | 1007 | err = snd_wss_timer(chip, 0, NULL); |
1118 | snd_printk(KERN_ERR "sscape: No timer device " | 1008 | if (err < 0) { |
1119 | "for AD1845 chip\n"); | 1009 | snd_printk(KERN_ERR "sscape: No timer device " |
1120 | goto _error; | 1010 | "for AD1845 chip\n"); |
1011 | goto _error; | ||
1012 | } | ||
1121 | } | 1013 | } |
1122 | 1014 | ||
1123 | if (sscape->type != SSCAPE_VIVO) { | 1015 | if (sscape->type != SSCAPE_VIVO) { |
@@ -1128,8 +1020,6 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port, | |||
1128 | "MIDI mixer control\n"); | 1020 | "MIDI mixer control\n"); |
1129 | goto _error; | 1021 | goto _error; |
1130 | } | 1022 | } |
1131 | chip->set_playback_format = ad1845_playback_format; | ||
1132 | chip->set_capture_format = ad1845_capture_format; | ||
1133 | } | 1023 | } |
1134 | 1024 | ||
1135 | strcpy(card->driver, "SoundScape"); | 1025 | strcpy(card->driver, "SoundScape"); |
@@ -1157,7 +1047,6 @@ static int __devinit create_sscape(int dev, struct snd_card *card) | |||
1157 | unsigned dma_cfg; | 1047 | unsigned dma_cfg; |
1158 | unsigned irq_cfg; | 1048 | unsigned irq_cfg; |
1159 | unsigned mpu_irq_cfg; | 1049 | unsigned mpu_irq_cfg; |
1160 | unsigned xport; | ||
1161 | struct resource *io_res; | 1050 | struct resource *io_res; |
1162 | struct resource *wss_res; | 1051 | struct resource *wss_res; |
1163 | unsigned long flags; | 1052 | unsigned long flags; |
@@ -1177,15 +1066,15 @@ static int __devinit create_sscape(int dev, struct snd_card *card) | |||
1177 | printk(KERN_ERR "sscape: Invalid IRQ %d\n", mpu_irq[dev]); | 1066 | printk(KERN_ERR "sscape: Invalid IRQ %d\n", mpu_irq[dev]); |
1178 | return -ENXIO; | 1067 | return -ENXIO; |
1179 | } | 1068 | } |
1180 | xport = port[dev]; | ||
1181 | 1069 | ||
1182 | /* | 1070 | /* |
1183 | * Grab IO ports that we will need to probe so that we | 1071 | * Grab IO ports that we will need to probe so that we |
1184 | * can detect and control this hardware ... | 1072 | * can detect and control this hardware ... |
1185 | */ | 1073 | */ |
1186 | io_res = request_region(xport, 8, "SoundScape"); | 1074 | io_res = request_region(port[dev], 8, "SoundScape"); |
1187 | if (!io_res) { | 1075 | if (!io_res) { |
1188 | snd_printk(KERN_ERR "sscape: can't grab port 0x%x\n", xport); | 1076 | snd_printk(KERN_ERR |
1077 | "sscape: can't grab port 0x%lx\n", port[dev]); | ||
1189 | return -EBUSY; | 1078 | return -EBUSY; |
1190 | } | 1079 | } |
1191 | wss_res = NULL; | 1080 | wss_res = NULL; |
@@ -1212,10 +1101,9 @@ static int __devinit create_sscape(int dev, struct snd_card *card) | |||
1212 | spin_lock_init(&sscape->fwlock); | 1101 | spin_lock_init(&sscape->fwlock); |
1213 | sscape->io_res = io_res; | 1102 | sscape->io_res = io_res; |
1214 | sscape->wss_res = wss_res; | 1103 | sscape->wss_res = wss_res; |
1215 | sscape->io_base = xport; | 1104 | sscape->io_base = port[dev]; |
1216 | sscape->wss_base = wss_port[dev]; | ||
1217 | 1105 | ||
1218 | if (!detect_sscape(sscape)) { | 1106 | if (!detect_sscape(sscape, wss_port[dev])) { |
1219 | printk(KERN_ERR "sscape: hardware not detected at 0x%x\n", sscape->io_base); | 1107 | printk(KERN_ERR "sscape: hardware not detected at 0x%x\n", sscape->io_base); |
1220 | err = -ENODEV; | 1108 | err = -ENODEV; |
1221 | goto _release_dma; | 1109 | goto _release_dma; |
@@ -1288,12 +1176,11 @@ static int __devinit create_sscape(int dev, struct snd_card *card) | |||
1288 | } | 1176 | } |
1289 | #define MIDI_DEVNUM 0 | 1177 | #define MIDI_DEVNUM 0 |
1290 | if (sscape->type != SSCAPE_VIVO) { | 1178 | if (sscape->type != SSCAPE_VIVO) { |
1291 | err = create_mpu401(card, MIDI_DEVNUM, | 1179 | err = create_mpu401(card, MIDI_DEVNUM, port[dev], mpu_irq[dev]); |
1292 | MPU401_IO(xport), mpu_irq[dev]); | ||
1293 | if (err < 0) { | 1180 | if (err < 0) { |
1294 | printk(KERN_ERR "sscape: Failed to create " | 1181 | printk(KERN_ERR "sscape: Failed to create " |
1295 | "MPU-401 device at 0x%x\n", | 1182 | "MPU-401 device at 0x%lx\n", |
1296 | MPU401_IO(xport)); | 1183 | port[dev]); |
1297 | goto _release_dma; | 1184 | goto _release_dma; |
1298 | } | 1185 | } |
1299 | 1186 | ||
@@ -1357,10 +1244,10 @@ static int __devinit snd_sscape_probe(struct device *pdev, unsigned int dev) | |||
1357 | struct soundscape *sscape; | 1244 | struct soundscape *sscape; |
1358 | int ret; | 1245 | int ret; |
1359 | 1246 | ||
1360 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, | 1247 | ret = snd_card_create(index[dev], id[dev], THIS_MODULE, |
1361 | sizeof(struct soundscape)); | 1248 | sizeof(struct soundscape), &card); |
1362 | if (!card) | 1249 | if (ret < 0) |
1363 | return -ENOMEM; | 1250 | return ret; |
1364 | 1251 | ||
1365 | sscape = get_card_soundscape(card); | 1252 | sscape = get_card_soundscape(card); |
1366 | sscape->type = SSCAPE; | 1253 | sscape->type = SSCAPE; |
@@ -1462,10 +1349,10 @@ static int __devinit sscape_pnp_detect(struct pnp_card_link *pcard, | |||
1462 | * Create a new ALSA sound card entry, in anticipation | 1349 | * Create a new ALSA sound card entry, in anticipation |
1463 | * of detecting our hardware ... | 1350 | * of detecting our hardware ... |
1464 | */ | 1351 | */ |
1465 | card = snd_card_new(index[idx], id[idx], THIS_MODULE, | 1352 | ret = snd_card_create(index[idx], id[idx], THIS_MODULE, |
1466 | sizeof(struct soundscape)); | 1353 | sizeof(struct soundscape), &card); |
1467 | if (!card) | 1354 | if (ret < 0) |
1468 | return -ENOMEM; | 1355 | return ret; |
1469 | 1356 | ||
1470 | sscape = get_card_soundscape(card); | 1357 | sscape = get_card_soundscape(card); |
1471 | 1358 | ||
diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c index 4c095bc7c729..a34ae7b1f7d0 100644 --- a/sound/isa/wavefront/wavefront.c +++ b/sound/isa/wavefront/wavefront.c | |||
@@ -338,15 +338,16 @@ snd_wavefront_free(struct snd_card *card) | |||
338 | } | 338 | } |
339 | } | 339 | } |
340 | 340 | ||
341 | static struct snd_card *snd_wavefront_card_new(int dev) | 341 | static int snd_wavefront_card_new(int dev, struct snd_card **cardp) |
342 | { | 342 | { |
343 | struct snd_card *card; | 343 | struct snd_card *card; |
344 | snd_wavefront_card_t *acard; | 344 | snd_wavefront_card_t *acard; |
345 | int err; | ||
345 | 346 | ||
346 | card = snd_card_new (index[dev], id[dev], THIS_MODULE, | 347 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, |
347 | sizeof(snd_wavefront_card_t)); | 348 | sizeof(snd_wavefront_card_t), &card); |
348 | if (card == NULL) | 349 | if (err < 0) |
349 | return NULL; | 350 | return err; |
350 | 351 | ||
351 | acard = card->private_data; | 352 | acard = card->private_data; |
352 | acard->wavefront.irq = -1; | 353 | acard->wavefront.irq = -1; |
@@ -357,7 +358,8 @@ static struct snd_card *snd_wavefront_card_new(int dev) | |||
357 | acard->wavefront.card = card; | 358 | acard->wavefront.card = card; |
358 | card->private_free = snd_wavefront_free; | 359 | card->private_free = snd_wavefront_free; |
359 | 360 | ||
360 | return card; | 361 | *cardp = card; |
362 | return 0; | ||
361 | } | 363 | } |
362 | 364 | ||
363 | static int __devinit | 365 | static int __devinit |
@@ -551,11 +553,11 @@ static int __devinit snd_wavefront_isa_match(struct device *pdev, | |||
551 | return 0; | 553 | return 0; |
552 | #endif | 554 | #endif |
553 | if (cs4232_pcm_port[dev] == SNDRV_AUTO_PORT) { | 555 | if (cs4232_pcm_port[dev] == SNDRV_AUTO_PORT) { |
554 | snd_printk("specify CS4232 port\n"); | 556 | snd_printk(KERN_ERR "specify CS4232 port\n"); |
555 | return 0; | 557 | return 0; |
556 | } | 558 | } |
557 | if (ics2115_port[dev] == SNDRV_AUTO_PORT) { | 559 | if (ics2115_port[dev] == SNDRV_AUTO_PORT) { |
558 | snd_printk("specify ICS2115 port\n"); | 560 | snd_printk(KERN_ERR "specify ICS2115 port\n"); |
559 | return 0; | 561 | return 0; |
560 | } | 562 | } |
561 | return 1; | 563 | return 1; |
@@ -567,9 +569,9 @@ static int __devinit snd_wavefront_isa_probe(struct device *pdev, | |||
567 | struct snd_card *card; | 569 | struct snd_card *card; |
568 | int err; | 570 | int err; |
569 | 571 | ||
570 | card = snd_wavefront_card_new(dev); | 572 | err = snd_wavefront_card_new(dev, &card); |
571 | if (! card) | 573 | if (err < 0) |
572 | return -ENOMEM; | 574 | return err; |
573 | snd_card_set_dev(card, pdev); | 575 | snd_card_set_dev(card, pdev); |
574 | if ((err = snd_wavefront_probe(card, dev)) < 0) { | 576 | if ((err = snd_wavefront_probe(card, dev)) < 0) { |
575 | snd_card_free(card); | 577 | snd_card_free(card); |
@@ -616,9 +618,9 @@ static int __devinit snd_wavefront_pnp_detect(struct pnp_card_link *pcard, | |||
616 | if (dev >= SNDRV_CARDS) | 618 | if (dev >= SNDRV_CARDS) |
617 | return -ENODEV; | 619 | return -ENODEV; |
618 | 620 | ||
619 | card = snd_wavefront_card_new(dev); | 621 | res = snd_wavefront_card_new(dev, &card); |
620 | if (! card) | 622 | if (res < 0) |
621 | return -ENOMEM; | 623 | return res; |
622 | 624 | ||
623 | if (snd_wavefront_pnp (dev, card->private_data, pcard, pid) < 0) { | 625 | if (snd_wavefront_pnp (dev, card->private_data, pcard, pid) < 0) { |
624 | if (cs4232_pcm_port[dev] == SNDRV_AUTO_PORT) { | 626 | if (cs4232_pcm_port[dev] == SNDRV_AUTO_PORT) { |
diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c index 4c410820a994..beb312cca75b 100644 --- a/sound/isa/wavefront/wavefront_synth.c +++ b/sound/isa/wavefront/wavefront_synth.c | |||
@@ -633,7 +633,7 @@ wavefront_get_sample_status (snd_wavefront_t *dev, int assume_rom) | |||
633 | wbuf[1] = i >> 7; | 633 | wbuf[1] = i >> 7; |
634 | 634 | ||
635 | if (snd_wavefront_cmd (dev, WFC_IDENTIFY_SAMPLE_TYPE, rbuf, wbuf)) { | 635 | if (snd_wavefront_cmd (dev, WFC_IDENTIFY_SAMPLE_TYPE, rbuf, wbuf)) { |
636 | snd_printk("cannot identify sample " | 636 | snd_printk(KERN_WARNING "cannot identify sample " |
637 | "type of slot %d\n", i); | 637 | "type of slot %d\n", i); |
638 | dev->sample_status[i] = WF_ST_EMPTY; | 638 | dev->sample_status[i] = WF_ST_EMPTY; |
639 | continue; | 639 | continue; |
diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c index 3d6c5f2838af..5d2ba1b749ab 100644 --- a/sound/isa/wss/wss_lib.c +++ b/sound/isa/wss/wss_lib.c | |||
@@ -181,25 +181,6 @@ static void snd_wss_wait(struct snd_wss *chip) | |||
181 | udelay(100); | 181 | udelay(100); |
182 | } | 182 | } |
183 | 183 | ||
184 | static void snd_wss_outm(struct snd_wss *chip, unsigned char reg, | ||
185 | unsigned char mask, unsigned char value) | ||
186 | { | ||
187 | unsigned char tmp = (chip->image[reg] & mask) | value; | ||
188 | |||
189 | snd_wss_wait(chip); | ||
190 | #ifdef CONFIG_SND_DEBUG | ||
191 | if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) | ||
192 | snd_printk("outm: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); | ||
193 | #endif | ||
194 | chip->image[reg] = tmp; | ||
195 | if (!chip->calibrate_mute) { | ||
196 | wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg); | ||
197 | wmb(); | ||
198 | wss_outb(chip, CS4231P(REG), tmp); | ||
199 | mb(); | ||
200 | } | ||
201 | } | ||
202 | |||
203 | static void snd_wss_dout(struct snd_wss *chip, unsigned char reg, | 184 | static void snd_wss_dout(struct snd_wss *chip, unsigned char reg, |
204 | unsigned char value) | 185 | unsigned char value) |
205 | { | 186 | { |
@@ -219,7 +200,8 @@ void snd_wss_out(struct snd_wss *chip, unsigned char reg, unsigned char value) | |||
219 | snd_wss_wait(chip); | 200 | snd_wss_wait(chip); |
220 | #ifdef CONFIG_SND_DEBUG | 201 | #ifdef CONFIG_SND_DEBUG |
221 | if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) | 202 | if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) |
222 | snd_printk("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); | 203 | snd_printk(KERN_DEBUG "out: auto calibration time out " |
204 | "- reg = 0x%x, value = 0x%x\n", reg, value); | ||
223 | #endif | 205 | #endif |
224 | wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg); | 206 | wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg); |
225 | wss_outb(chip, CS4231P(REG), value); | 207 | wss_outb(chip, CS4231P(REG), value); |
@@ -235,7 +217,8 @@ unsigned char snd_wss_in(struct snd_wss *chip, unsigned char reg) | |||
235 | snd_wss_wait(chip); | 217 | snd_wss_wait(chip); |
236 | #ifdef CONFIG_SND_DEBUG | 218 | #ifdef CONFIG_SND_DEBUG |
237 | if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) | 219 | if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) |
238 | snd_printk("in: auto calibration time out - reg = 0x%x\n", reg); | 220 | snd_printk(KERN_DEBUG "in: auto calibration time out " |
221 | "- reg = 0x%x\n", reg); | ||
239 | #endif | 222 | #endif |
240 | wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg); | 223 | wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg); |
241 | mb(); | 224 | mb(); |
@@ -252,7 +235,7 @@ void snd_cs4236_ext_out(struct snd_wss *chip, unsigned char reg, | |||
252 | wss_outb(chip, CS4231P(REG), val); | 235 | wss_outb(chip, CS4231P(REG), val); |
253 | chip->eimage[CS4236_REG(reg)] = val; | 236 | chip->eimage[CS4236_REG(reg)] = val; |
254 | #if 0 | 237 | #if 0 |
255 | printk("ext out : reg = 0x%x, val = 0x%x\n", reg, val); | 238 | printk(KERN_DEBUG "ext out : reg = 0x%x, val = 0x%x\n", reg, val); |
256 | #endif | 239 | #endif |
257 | } | 240 | } |
258 | EXPORT_SYMBOL(snd_cs4236_ext_out); | 241 | EXPORT_SYMBOL(snd_cs4236_ext_out); |
@@ -268,7 +251,8 @@ unsigned char snd_cs4236_ext_in(struct snd_wss *chip, unsigned char reg) | |||
268 | { | 251 | { |
269 | unsigned char res; | 252 | unsigned char res; |
270 | res = wss_inb(chip, CS4231P(REG)); | 253 | res = wss_inb(chip, CS4231P(REG)); |
271 | printk("ext in : reg = 0x%x, val = 0x%x\n", reg, res); | 254 | printk(KERN_DEBUG "ext in : reg = 0x%x, val = 0x%x\n", |
255 | reg, res); | ||
272 | return res; | 256 | return res; |
273 | } | 257 | } |
274 | #endif | 258 | #endif |
@@ -394,13 +378,16 @@ void snd_wss_mce_up(struct snd_wss *chip) | |||
394 | snd_wss_wait(chip); | 378 | snd_wss_wait(chip); |
395 | #ifdef CONFIG_SND_DEBUG | 379 | #ifdef CONFIG_SND_DEBUG |
396 | if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) | 380 | if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) |
397 | snd_printk("mce_up - auto calibration time out (0)\n"); | 381 | snd_printk(KERN_DEBUG |
382 | "mce_up - auto calibration time out (0)\n"); | ||
398 | #endif | 383 | #endif |
399 | spin_lock_irqsave(&chip->reg_lock, flags); | 384 | spin_lock_irqsave(&chip->reg_lock, flags); |
400 | chip->mce_bit |= CS4231_MCE; | 385 | chip->mce_bit |= CS4231_MCE; |
401 | timeout = wss_inb(chip, CS4231P(REGSEL)); | 386 | timeout = wss_inb(chip, CS4231P(REGSEL)); |
402 | if (timeout == 0x80) | 387 | if (timeout == 0x80) |
403 | snd_printk("mce_up [0x%lx]: serious init problem - codec still busy\n", chip->port); | 388 | snd_printk(KERN_DEBUG "mce_up [0x%lx]: " |
389 | "serious init problem - codec still busy\n", | ||
390 | chip->port); | ||
404 | if (!(timeout & CS4231_MCE)) | 391 | if (!(timeout & CS4231_MCE)) |
405 | wss_outb(chip, CS4231P(REGSEL), | 392 | wss_outb(chip, CS4231P(REGSEL), |
406 | chip->mce_bit | (timeout & 0x1f)); | 393 | chip->mce_bit | (timeout & 0x1f)); |
@@ -419,7 +406,9 @@ void snd_wss_mce_down(struct snd_wss *chip) | |||
419 | 406 | ||
420 | #ifdef CONFIG_SND_DEBUG | 407 | #ifdef CONFIG_SND_DEBUG |
421 | if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) | 408 | if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) |
422 | snd_printk("mce_down [0x%lx] - auto calibration time out (0)\n", (long)CS4231P(REGSEL)); | 409 | snd_printk(KERN_DEBUG "mce_down [0x%lx] - " |
410 | "auto calibration time out (0)\n", | ||
411 | (long)CS4231P(REGSEL)); | ||
423 | #endif | 412 | #endif |
424 | spin_lock_irqsave(&chip->reg_lock, flags); | 413 | spin_lock_irqsave(&chip->reg_lock, flags); |
425 | chip->mce_bit &= ~CS4231_MCE; | 414 | chip->mce_bit &= ~CS4231_MCE; |
@@ -427,7 +416,9 @@ void snd_wss_mce_down(struct snd_wss *chip) | |||
427 | wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f)); | 416 | wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f)); |
428 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 417 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
429 | if (timeout == 0x80) | 418 | if (timeout == 0x80) |
430 | snd_printk("mce_down [0x%lx]: serious init problem - codec still busy\n", chip->port); | 419 | snd_printk(KERN_DEBUG "mce_down [0x%lx]: " |
420 | "serious init problem - codec still busy\n", | ||
421 | chip->port); | ||
431 | if ((timeout & CS4231_MCE) == 0 || !(chip->hardware & hw_mask)) | 422 | if ((timeout & CS4231_MCE) == 0 || !(chip->hardware & hw_mask)) |
432 | return; | 423 | return; |
433 | 424 | ||
@@ -565,7 +556,7 @@ static unsigned char snd_wss_get_format(struct snd_wss *chip, | |||
565 | if (channels > 1) | 556 | if (channels > 1) |
566 | rformat |= CS4231_STEREO; | 557 | rformat |= CS4231_STEREO; |
567 | #if 0 | 558 | #if 0 |
568 | snd_printk("get_format: 0x%x (mode=0x%x)\n", format, mode); | 559 | snd_printk(KERN_DEBUG "get_format: 0x%x (mode=0x%x)\n", format, mode); |
569 | #endif | 560 | #endif |
570 | return rformat; | 561 | return rformat; |
571 | } | 562 | } |
@@ -587,7 +578,15 @@ static void snd_wss_calibrate_mute(struct snd_wss *chip, int mute) | |||
587 | chip->image[CS4231_RIGHT_INPUT]); | 578 | chip->image[CS4231_RIGHT_INPUT]); |
588 | snd_wss_dout(chip, CS4231_LOOPBACK, | 579 | snd_wss_dout(chip, CS4231_LOOPBACK, |
589 | chip->image[CS4231_LOOPBACK]); | 580 | chip->image[CS4231_LOOPBACK]); |
581 | } else { | ||
582 | snd_wss_dout(chip, CS4231_LEFT_INPUT, | ||
583 | 0); | ||
584 | snd_wss_dout(chip, CS4231_RIGHT_INPUT, | ||
585 | 0); | ||
586 | snd_wss_dout(chip, CS4231_LOOPBACK, | ||
587 | 0xfd); | ||
590 | } | 588 | } |
589 | |||
591 | snd_wss_dout(chip, CS4231_AUX1_LEFT_INPUT, | 590 | snd_wss_dout(chip, CS4231_AUX1_LEFT_INPUT, |
592 | mute | chip->image[CS4231_AUX1_LEFT_INPUT]); | 591 | mute | chip->image[CS4231_AUX1_LEFT_INPUT]); |
593 | snd_wss_dout(chip, CS4231_AUX1_RIGHT_INPUT, | 592 | snd_wss_dout(chip, CS4231_AUX1_RIGHT_INPUT, |
@@ -630,7 +629,6 @@ static void snd_wss_playback_format(struct snd_wss *chip, | |||
630 | int full_calib = 1; | 629 | int full_calib = 1; |
631 | 630 | ||
632 | mutex_lock(&chip->mce_mutex); | 631 | mutex_lock(&chip->mce_mutex); |
633 | snd_wss_calibrate_mute(chip, 1); | ||
634 | if (chip->hardware == WSS_HW_CS4231A || | 632 | if (chip->hardware == WSS_HW_CS4231A || |
635 | (chip->hardware & WSS_HW_CS4232_MASK)) { | 633 | (chip->hardware & WSS_HW_CS4232_MASK)) { |
636 | spin_lock_irqsave(&chip->reg_lock, flags); | 634 | spin_lock_irqsave(&chip->reg_lock, flags); |
@@ -646,6 +644,24 @@ static void snd_wss_playback_format(struct snd_wss *chip, | |||
646 | full_calib = 0; | 644 | full_calib = 0; |
647 | } | 645 | } |
648 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 646 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
647 | } else if (chip->hardware == WSS_HW_AD1845) { | ||
648 | unsigned rate = params_rate(params); | ||
649 | |||
650 | /* | ||
651 | * Program the AD1845 correctly for the playback stream. | ||
652 | * Note that we do NOT need to toggle the MCE bit because | ||
653 | * the PLAYBACK_ENABLE bit of the Interface Configuration | ||
654 | * register is set. | ||
655 | * | ||
656 | * NOTE: We seem to need to write to the MSB before the LSB | ||
657 | * to get the correct sample frequency. | ||
658 | */ | ||
659 | spin_lock_irqsave(&chip->reg_lock, flags); | ||
660 | snd_wss_out(chip, CS4231_PLAYBK_FORMAT, (pdfr & 0xf0)); | ||
661 | snd_wss_out(chip, AD1845_UPR_FREQ_SEL, (rate >> 8) & 0xff); | ||
662 | snd_wss_out(chip, AD1845_LWR_FREQ_SEL, rate & 0xff); | ||
663 | full_calib = 0; | ||
664 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
649 | } | 665 | } |
650 | if (full_calib) { | 666 | if (full_calib) { |
651 | snd_wss_mce_up(chip); | 667 | snd_wss_mce_up(chip); |
@@ -663,7 +679,6 @@ static void snd_wss_playback_format(struct snd_wss *chip, | |||
663 | udelay(100); /* this seems to help */ | 679 | udelay(100); /* this seems to help */ |
664 | snd_wss_mce_down(chip); | 680 | snd_wss_mce_down(chip); |
665 | } | 681 | } |
666 | snd_wss_calibrate_mute(chip, 0); | ||
667 | mutex_unlock(&chip->mce_mutex); | 682 | mutex_unlock(&chip->mce_mutex); |
668 | } | 683 | } |
669 | 684 | ||
@@ -675,7 +690,6 @@ static void snd_wss_capture_format(struct snd_wss *chip, | |||
675 | int full_calib = 1; | 690 | int full_calib = 1; |
676 | 691 | ||
677 | mutex_lock(&chip->mce_mutex); | 692 | mutex_lock(&chip->mce_mutex); |
678 | snd_wss_calibrate_mute(chip, 1); | ||
679 | if (chip->hardware == WSS_HW_CS4231A || | 693 | if (chip->hardware == WSS_HW_CS4231A || |
680 | (chip->hardware & WSS_HW_CS4232_MASK)) { | 694 | (chip->hardware & WSS_HW_CS4232_MASK)) { |
681 | spin_lock_irqsave(&chip->reg_lock, flags); | 695 | spin_lock_irqsave(&chip->reg_lock, flags); |
@@ -690,6 +704,24 @@ static void snd_wss_capture_format(struct snd_wss *chip, | |||
690 | full_calib = 0; | 704 | full_calib = 0; |
691 | } | 705 | } |
692 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 706 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
707 | } else if (chip->hardware == WSS_HW_AD1845) { | ||
708 | unsigned rate = params_rate(params); | ||
709 | |||
710 | /* | ||
711 | * Program the AD1845 correctly for the capture stream. | ||
712 | * Note that we do NOT need to toggle the MCE bit because | ||
713 | * the PLAYBACK_ENABLE bit of the Interface Configuration | ||
714 | * register is set. | ||
715 | * | ||
716 | * NOTE: We seem to need to write to the MSB before the LSB | ||
717 | * to get the correct sample frequency. | ||
718 | */ | ||
719 | spin_lock_irqsave(&chip->reg_lock, flags); | ||
720 | snd_wss_out(chip, CS4231_REC_FORMAT, (cdfr & 0xf0)); | ||
721 | snd_wss_out(chip, AD1845_UPR_FREQ_SEL, (rate >> 8) & 0xff); | ||
722 | snd_wss_out(chip, AD1845_LWR_FREQ_SEL, rate & 0xff); | ||
723 | full_calib = 0; | ||
724 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
693 | } | 725 | } |
694 | if (full_calib) { | 726 | if (full_calib) { |
695 | snd_wss_mce_up(chip); | 727 | snd_wss_mce_up(chip); |
@@ -714,7 +746,6 @@ static void snd_wss_capture_format(struct snd_wss *chip, | |||
714 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 746 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
715 | snd_wss_mce_down(chip); | 747 | snd_wss_mce_down(chip); |
716 | } | 748 | } |
717 | snd_wss_calibrate_mute(chip, 0); | ||
718 | mutex_unlock(&chip->mce_mutex); | 749 | mutex_unlock(&chip->mce_mutex); |
719 | } | 750 | } |
720 | 751 | ||
@@ -771,10 +802,11 @@ static void snd_wss_init(struct snd_wss *chip) | |||
771 | { | 802 | { |
772 | unsigned long flags; | 803 | unsigned long flags; |
773 | 804 | ||
805 | snd_wss_calibrate_mute(chip, 1); | ||
774 | snd_wss_mce_down(chip); | 806 | snd_wss_mce_down(chip); |
775 | 807 | ||
776 | #ifdef SNDRV_DEBUG_MCE | 808 | #ifdef SNDRV_DEBUG_MCE |
777 | snd_printk("init: (1)\n"); | 809 | snd_printk(KERN_DEBUG "init: (1)\n"); |
778 | #endif | 810 | #endif |
779 | snd_wss_mce_up(chip); | 811 | snd_wss_mce_up(chip); |
780 | spin_lock_irqsave(&chip->reg_lock, flags); | 812 | spin_lock_irqsave(&chip->reg_lock, flags); |
@@ -789,18 +821,20 @@ static void snd_wss_init(struct snd_wss *chip) | |||
789 | snd_wss_mce_down(chip); | 821 | snd_wss_mce_down(chip); |
790 | 822 | ||
791 | #ifdef SNDRV_DEBUG_MCE | 823 | #ifdef SNDRV_DEBUG_MCE |
792 | snd_printk("init: (2)\n"); | 824 | snd_printk(KERN_DEBUG "init: (2)\n"); |
793 | #endif | 825 | #endif |
794 | 826 | ||
795 | snd_wss_mce_up(chip); | 827 | snd_wss_mce_up(chip); |
796 | spin_lock_irqsave(&chip->reg_lock, flags); | 828 | spin_lock_irqsave(&chip->reg_lock, flags); |
829 | chip->image[CS4231_IFACE_CTRL] &= ~CS4231_AUTOCALIB; | ||
830 | snd_wss_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]); | ||
797 | snd_wss_out(chip, | 831 | snd_wss_out(chip, |
798 | CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1]); | 832 | CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1]); |
799 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 833 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
800 | snd_wss_mce_down(chip); | 834 | snd_wss_mce_down(chip); |
801 | 835 | ||
802 | #ifdef SNDRV_DEBUG_MCE | 836 | #ifdef SNDRV_DEBUG_MCE |
803 | snd_printk("init: (3) - afei = 0x%x\n", | 837 | snd_printk(KERN_DEBUG "init: (3) - afei = 0x%x\n", |
804 | chip->image[CS4231_ALT_FEATURE_1]); | 838 | chip->image[CS4231_ALT_FEATURE_1]); |
805 | #endif | 839 | #endif |
806 | 840 | ||
@@ -817,7 +851,7 @@ static void snd_wss_init(struct snd_wss *chip) | |||
817 | snd_wss_mce_down(chip); | 851 | snd_wss_mce_down(chip); |
818 | 852 | ||
819 | #ifdef SNDRV_DEBUG_MCE | 853 | #ifdef SNDRV_DEBUG_MCE |
820 | snd_printk("init: (4)\n"); | 854 | snd_printk(KERN_DEBUG "init: (4)\n"); |
821 | #endif | 855 | #endif |
822 | 856 | ||
823 | snd_wss_mce_up(chip); | 857 | snd_wss_mce_up(chip); |
@@ -827,9 +861,10 @@ static void snd_wss_init(struct snd_wss *chip) | |||
827 | chip->image[CS4231_REC_FORMAT]); | 861 | chip->image[CS4231_REC_FORMAT]); |
828 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 862 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
829 | snd_wss_mce_down(chip); | 863 | snd_wss_mce_down(chip); |
864 | snd_wss_calibrate_mute(chip, 0); | ||
830 | 865 | ||
831 | #ifdef SNDRV_DEBUG_MCE | 866 | #ifdef SNDRV_DEBUG_MCE |
832 | snd_printk("init: (5)\n"); | 867 | snd_printk(KERN_DEBUG "init: (5)\n"); |
833 | #endif | 868 | #endif |
834 | } | 869 | } |
835 | 870 | ||
@@ -885,8 +920,6 @@ static void snd_wss_close(struct snd_wss *chip, unsigned int mode) | |||
885 | mutex_unlock(&chip->open_mutex); | 920 | mutex_unlock(&chip->open_mutex); |
886 | return; | 921 | return; |
887 | } | 922 | } |
888 | snd_wss_calibrate_mute(chip, 1); | ||
889 | |||
890 | /* disable IRQ */ | 923 | /* disable IRQ */ |
891 | spin_lock_irqsave(&chip->reg_lock, flags); | 924 | spin_lock_irqsave(&chip->reg_lock, flags); |
892 | if (!(chip->hardware & WSS_HW_AD1848_MASK)) | 925 | if (!(chip->hardware & WSS_HW_AD1848_MASK)) |
@@ -919,8 +952,6 @@ static void snd_wss_close(struct snd_wss *chip, unsigned int mode) | |||
919 | wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ | 952 | wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ |
920 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 953 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
921 | 954 | ||
922 | snd_wss_calibrate_mute(chip, 0); | ||
923 | |||
924 | chip->mode = 0; | 955 | chip->mode = 0; |
925 | mutex_unlock(&chip->open_mutex); | 956 | mutex_unlock(&chip->open_mutex); |
926 | } | 957 | } |
@@ -1113,7 +1144,7 @@ irqreturn_t snd_wss_interrupt(int irq, void *dev_id) | |||
1113 | if (chip->hardware & WSS_HW_AD1848_MASK) | 1144 | if (chip->hardware & WSS_HW_AD1848_MASK) |
1114 | wss_outb(chip, CS4231P(STATUS), 0); | 1145 | wss_outb(chip, CS4231P(STATUS), 0); |
1115 | else | 1146 | else |
1116 | snd_wss_outm(chip, CS4231_IRQ_STATUS, status, 0); | 1147 | snd_wss_out(chip, CS4231_IRQ_STATUS, status); |
1117 | spin_unlock(&chip->reg_lock); | 1148 | spin_unlock(&chip->reg_lock); |
1118 | return IRQ_HANDLED; | 1149 | return IRQ_HANDLED; |
1119 | } | 1150 | } |
@@ -1278,7 +1309,8 @@ static int snd_wss_probe(struct snd_wss *chip) | |||
1278 | } else if (rev == 0x03) { | 1309 | } else if (rev == 0x03) { |
1279 | chip->hardware = WSS_HW_CS4236B; | 1310 | chip->hardware = WSS_HW_CS4236B; |
1280 | } else { | 1311 | } else { |
1281 | snd_printk("unknown CS chip with version 0x%x\n", rev); | 1312 | snd_printk(KERN_ERR |
1313 | "unknown CS chip with version 0x%x\n", rev); | ||
1282 | return -ENODEV; /* unknown CS4231 chip? */ | 1314 | return -ENODEV; /* unknown CS4231 chip? */ |
1283 | } | 1315 | } |
1284 | } | 1316 | } |
@@ -1314,6 +1346,10 @@ static int snd_wss_probe(struct snd_wss *chip) | |||
1314 | chip->image[CS4231_ALT_FEATURE_2] = | 1346 | chip->image[CS4231_ALT_FEATURE_2] = |
1315 | chip->hardware == WSS_HW_INTERWAVE ? 0xc2 : 0x01; | 1347 | chip->hardware == WSS_HW_INTERWAVE ? 0xc2 : 0x01; |
1316 | } | 1348 | } |
1349 | /* enable fine grained frequency selection */ | ||
1350 | if (chip->hardware == WSS_HW_AD1845) | ||
1351 | chip->image[AD1845_PWR_DOWN] = 8; | ||
1352 | |||
1317 | ptr = (unsigned char *) &chip->image; | 1353 | ptr = (unsigned char *) &chip->image; |
1318 | regnum = (chip->hardware & WSS_HW_AD1848_MASK) ? 16 : 32; | 1354 | regnum = (chip->hardware & WSS_HW_AD1848_MASK) ? 16 : 32; |
1319 | snd_wss_mce_down(chip); | 1355 | snd_wss_mce_down(chip); |
@@ -1342,7 +1378,10 @@ static int snd_wss_probe(struct snd_wss *chip) | |||
1342 | case 6: | 1378 | case 6: |
1343 | break; | 1379 | break; |
1344 | default: | 1380 | default: |
1345 | snd_printk("unknown CS4235 chip (enhanced version = 0x%x)\n", id); | 1381 | snd_printk(KERN_WARNING |
1382 | "unknown CS4235 chip " | ||
1383 | "(enhanced version = 0x%x)\n", | ||
1384 | id); | ||
1346 | } | 1385 | } |
1347 | } else if ((id & 0x1f) == 0x0b) { /* CS4236/B */ | 1386 | } else if ((id & 0x1f) == 0x0b) { /* CS4236/B */ |
1348 | switch (id >> 5) { | 1387 | switch (id >> 5) { |
@@ -1353,7 +1392,10 @@ static int snd_wss_probe(struct snd_wss *chip) | |||
1353 | chip->hardware = WSS_HW_CS4236B; | 1392 | chip->hardware = WSS_HW_CS4236B; |
1354 | break; | 1393 | break; |
1355 | default: | 1394 | default: |
1356 | snd_printk("unknown CS4236 chip (enhanced version = 0x%x)\n", id); | 1395 | snd_printk(KERN_WARNING |
1396 | "unknown CS4236 chip " | ||
1397 | "(enhanced version = 0x%x)\n", | ||
1398 | id); | ||
1357 | } | 1399 | } |
1358 | } else if ((id & 0x1f) == 0x08) { /* CS4237B */ | 1400 | } else if ((id & 0x1f) == 0x08) { /* CS4237B */ |
1359 | chip->hardware = WSS_HW_CS4237B; | 1401 | chip->hardware = WSS_HW_CS4237B; |
@@ -1364,7 +1406,10 @@ static int snd_wss_probe(struct snd_wss *chip) | |||
1364 | case 7: | 1406 | case 7: |
1365 | break; | 1407 | break; |
1366 | default: | 1408 | default: |
1367 | snd_printk("unknown CS4237B chip (enhanced version = 0x%x)\n", id); | 1409 | snd_printk(KERN_WARNING |
1410 | "unknown CS4237B chip " | ||
1411 | "(enhanced version = 0x%x)\n", | ||
1412 | id); | ||
1368 | } | 1413 | } |
1369 | } else if ((id & 0x1f) == 0x09) { /* CS4238B */ | 1414 | } else if ((id & 0x1f) == 0x09) { /* CS4238B */ |
1370 | chip->hardware = WSS_HW_CS4238B; | 1415 | chip->hardware = WSS_HW_CS4238B; |
@@ -1374,7 +1419,10 @@ static int snd_wss_probe(struct snd_wss *chip) | |||
1374 | case 7: | 1419 | case 7: |
1375 | break; | 1420 | break; |
1376 | default: | 1421 | default: |
1377 | snd_printk("unknown CS4238B chip (enhanced version = 0x%x)\n", id); | 1422 | snd_printk(KERN_WARNING |
1423 | "unknown CS4238B chip " | ||
1424 | "(enhanced version = 0x%x)\n", | ||
1425 | id); | ||
1378 | } | 1426 | } |
1379 | } else if ((id & 0x1f) == 0x1e) { /* CS4239 */ | 1427 | } else if ((id & 0x1f) == 0x1e) { /* CS4239 */ |
1380 | chip->hardware = WSS_HW_CS4239; | 1428 | chip->hardware = WSS_HW_CS4239; |
@@ -1384,10 +1432,15 @@ static int snd_wss_probe(struct snd_wss *chip) | |||
1384 | case 6: | 1432 | case 6: |
1385 | break; | 1433 | break; |
1386 | default: | 1434 | default: |
1387 | snd_printk("unknown CS4239 chip (enhanced version = 0x%x)\n", id); | 1435 | snd_printk(KERN_WARNING |
1436 | "unknown CS4239 chip " | ||
1437 | "(enhanced version = 0x%x)\n", | ||
1438 | id); | ||
1388 | } | 1439 | } |
1389 | } else { | 1440 | } else { |
1390 | snd_printk("unknown CS4236/CS423xB chip (enhanced version = 0x%x)\n", id); | 1441 | snd_printk(KERN_WARNING |
1442 | "unknown CS4236/CS423xB chip " | ||
1443 | "(enhanced version = 0x%x)\n", id); | ||
1391 | } | 1444 | } |
1392 | } | 1445 | } |
1393 | } | 1446 | } |
@@ -1618,7 +1671,8 @@ static void snd_wss_resume(struct snd_wss *chip) | |||
1618 | wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f)); | 1671 | wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f)); |
1619 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 1672 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
1620 | if (timeout == 0x80) | 1673 | if (timeout == 0x80) |
1621 | snd_printk("down [0x%lx]: serious init problem - codec still busy\n", chip->port); | 1674 | snd_printk(KERN_ERR "down [0x%lx]: serious init problem " |
1675 | "- codec still busy\n", chip->port); | ||
1622 | if ((timeout & CS4231_MCE) == 0 || | 1676 | if ((timeout & CS4231_MCE) == 0 || |
1623 | !(chip->hardware & (WSS_HW_CS4231_MASK | WSS_HW_CS4232_MASK))) { | 1677 | !(chip->hardware & (WSS_HW_CS4231_MASK | WSS_HW_CS4232_MASK))) { |
1624 | return; | 1678 | return; |
@@ -1628,7 +1682,7 @@ static void snd_wss_resume(struct snd_wss *chip) | |||
1628 | } | 1682 | } |
1629 | #endif /* CONFIG_PM */ | 1683 | #endif /* CONFIG_PM */ |
1630 | 1684 | ||
1631 | static int snd_wss_free(struct snd_wss *chip) | 1685 | int snd_wss_free(struct snd_wss *chip) |
1632 | { | 1686 | { |
1633 | release_and_free_resource(chip->res_port); | 1687 | release_and_free_resource(chip->res_port); |
1634 | release_and_free_resource(chip->res_cport); | 1688 | release_and_free_resource(chip->res_cport); |
@@ -1651,6 +1705,7 @@ static int snd_wss_free(struct snd_wss *chip) | |||
1651 | kfree(chip); | 1705 | kfree(chip); |
1652 | return 0; | 1706 | return 0; |
1653 | } | 1707 | } |
1708 | EXPORT_SYMBOL(snd_wss_free); | ||
1654 | 1709 | ||
1655 | static int snd_wss_dev_free(struct snd_device *device) | 1710 | static int snd_wss_dev_free(struct snd_device *device) |
1656 | { | 1711 | { |
@@ -1820,7 +1875,8 @@ int snd_wss_create(struct snd_card *card, | |||
1820 | #if 0 | 1875 | #if 0 |
1821 | if (chip->hardware & WSS_HW_CS4232_MASK) { | 1876 | if (chip->hardware & WSS_HW_CS4232_MASK) { |
1822 | if (chip->res_cport == NULL) | 1877 | if (chip->res_cport == NULL) |
1823 | snd_printk("CS4232 control port features are not accessible\n"); | 1878 | snd_printk(KERN_ERR "CS4232 control port features are " |
1879 | "not accessible\n"); | ||
1824 | } | 1880 | } |
1825 | #endif | 1881 | #endif |
1826 | 1882 | ||
diff --git a/sound/mips/au1x00.c b/sound/mips/au1x00.c index 1881cec11e78..3e763d6a5d67 100644 --- a/sound/mips/au1x00.c +++ b/sound/mips/au1x00.c | |||
@@ -636,9 +636,10 @@ au1000_init(void) | |||
636 | struct snd_card *card; | 636 | struct snd_card *card; |
637 | struct snd_au1000 *au1000; | 637 | struct snd_au1000 *au1000; |
638 | 638 | ||
639 | card = snd_card_new(-1, "AC97", THIS_MODULE, sizeof(struct snd_au1000)); | 639 | err = snd_card_create(-1, "AC97", THIS_MODULE, |
640 | if (card == NULL) | 640 | sizeof(struct snd_au1000), &card); |
641 | return -ENOMEM; | 641 | if (err < 0) |
642 | return err; | ||
642 | 643 | ||
643 | card->private_free = snd_au1000_free; | 644 | card->private_free = snd_au1000_free; |
644 | au1000 = card->private_data; | 645 | au1000 = card->private_data; |
@@ -678,7 +679,7 @@ au1000_init(void) | |||
678 | return err; | 679 | return err; |
679 | } | 680 | } |
680 | 681 | ||
681 | printk( KERN_INFO "ALSA AC97: Driver Initialized\n" ); | 682 | printk(KERN_INFO "ALSA AC97: Driver Initialized\n"); |
682 | au1000_card = card; | 683 | au1000_card = card; |
683 | return 0; | 684 | return 0; |
684 | } | 685 | } |
diff --git a/sound/mips/hal2.c b/sound/mips/hal2.c index db495be01861..c52691c2fc46 100644 --- a/sound/mips/hal2.c +++ b/sound/mips/hal2.c | |||
@@ -878,9 +878,9 @@ static int __devinit hal2_probe(struct platform_device *pdev) | |||
878 | struct snd_hal2 *chip; | 878 | struct snd_hal2 *chip; |
879 | int err; | 879 | int err; |
880 | 880 | ||
881 | card = snd_card_new(index, id, THIS_MODULE, 0); | 881 | err = snd_card_create(index, id, THIS_MODULE, 0, &card); |
882 | if (card == NULL) | 882 | if (err < 0) |
883 | return -ENOMEM; | 883 | return err; |
884 | 884 | ||
885 | err = hal2_create(card, &chip); | 885 | err = hal2_create(card, &chip); |
886 | if (err < 0) { | 886 | if (err < 0) { |
diff --git a/sound/mips/sgio2audio.c b/sound/mips/sgio2audio.c index 4c63504348dc..66f3b48ceafc 100644 --- a/sound/mips/sgio2audio.c +++ b/sound/mips/sgio2audio.c | |||
@@ -936,9 +936,9 @@ static int __devinit snd_sgio2audio_probe(struct platform_device *pdev) | |||
936 | struct snd_sgio2audio *chip; | 936 | struct snd_sgio2audio *chip; |
937 | int err; | 937 | int err; |
938 | 938 | ||
939 | card = snd_card_new(index, id, THIS_MODULE, 0); | 939 | err = snd_card_create(index, id, THIS_MODULE, 0, &card); |
940 | if (card == NULL) | 940 | if (err < 0) |
941 | return -ENOMEM; | 941 | return err; |
942 | 942 | ||
943 | err = snd_sgio2audio_create(card, &chip); | 943 | err = snd_sgio2audio_create(card, &chip); |
944 | if (err < 0) { | 944 | if (err < 0) { |
diff --git a/sound/oss/ad1848.c b/sound/oss/ad1848.c index 7cf9913a47b2..d12bd98a37ba 100644 --- a/sound/oss/ad1848.c +++ b/sound/oss/ad1848.c | |||
@@ -280,7 +280,7 @@ static void wait_for_calibration(ad1848_info * devc) | |||
280 | while (timeout > 0 && (ad_read(devc, 11) & 0x20)) | 280 | while (timeout > 0 && (ad_read(devc, 11) & 0x20)) |
281 | timeout--; | 281 | timeout--; |
282 | if (ad_read(devc, 11) & 0x20) | 282 | if (ad_read(devc, 11) & 0x20) |
283 | if ( (devc->model != MD_1845) || (devc->model != MD_1845_SSCAPE)) | 283 | if ((devc->model != MD_1845) && (devc->model != MD_1845_SSCAPE)) |
284 | printk(KERN_WARNING "ad1848: Auto calibration timed out(3).\n"); | 284 | printk(KERN_WARNING "ad1848: Auto calibration timed out(3).\n"); |
285 | } | 285 | } |
286 | 286 | ||
@@ -2107,7 +2107,7 @@ int ad1848_control(int cmd, int arg) | |||
2107 | switch (cmd) | 2107 | switch (cmd) |
2108 | { | 2108 | { |
2109 | case AD1848_SET_XTAL: /* Change clock frequency of AD1845 (only ) */ | 2109 | case AD1848_SET_XTAL: /* Change clock frequency of AD1845 (only ) */ |
2110 | if (devc->model != MD_1845 || devc->model != MD_1845_SSCAPE) | 2110 | if (devc->model != MD_1845 && devc->model != MD_1845_SSCAPE) |
2111 | return -EINVAL; | 2111 | return -EINVAL; |
2112 | spin_lock_irqsave(&devc->lock,flags); | 2112 | spin_lock_irqsave(&devc->lock,flags); |
2113 | ad_enter_MCE(devc); | 2113 | ad_enter_MCE(devc); |
diff --git a/sound/oss/au1550_ac97.c b/sound/oss/au1550_ac97.c index 81e1f443d094..4191acccbcdb 100644 --- a/sound/oss/au1550_ac97.c +++ b/sound/oss/au1550_ac97.c | |||
@@ -1627,7 +1627,9 @@ au1550_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
1627 | sizeof(abinfo)) ? -EFAULT : 0; | 1627 | sizeof(abinfo)) ? -EFAULT : 0; |
1628 | 1628 | ||
1629 | case SNDCTL_DSP_NONBLOCK: | 1629 | case SNDCTL_DSP_NONBLOCK: |
1630 | spin_lock(&file->f_lock); | ||
1630 | file->f_flags |= O_NONBLOCK; | 1631 | file->f_flags |= O_NONBLOCK; |
1632 | spin_unlock(&file->f_lock); | ||
1631 | return 0; | 1633 | return 0; |
1632 | 1634 | ||
1633 | case SNDCTL_DSP_GETODELAY: | 1635 | case SNDCTL_DSP_GETODELAY: |
diff --git a/sound/oss/audio.c b/sound/oss/audio.c index 89bd27a5e865..b69c05b7ea7b 100644 --- a/sound/oss/audio.c +++ b/sound/oss/audio.c | |||
@@ -433,7 +433,9 @@ int audio_ioctl(int dev, struct file *file, unsigned int cmd, void __user *arg) | |||
433 | return dma_ioctl(dev, cmd, arg); | 433 | return dma_ioctl(dev, cmd, arg); |
434 | 434 | ||
435 | case SNDCTL_DSP_NONBLOCK: | 435 | case SNDCTL_DSP_NONBLOCK: |
436 | spin_lock(&file->f_lock); | ||
436 | file->f_flags |= O_NONBLOCK; | 437 | file->f_flags |= O_NONBLOCK; |
438 | spin_unlock(&file->f_lock); | ||
437 | return 0; | 439 | return 0; |
438 | 440 | ||
439 | case SNDCTL_DSP_GETCAPS: | 441 | case SNDCTL_DSP_GETCAPS: |
diff --git a/sound/oss/dmabuf.c b/sound/oss/dmabuf.c index 1e90d769b62e..1bfcf7e88546 100644 --- a/sound/oss/dmabuf.c +++ b/sound/oss/dmabuf.c | |||
@@ -439,7 +439,7 @@ int DMAbuf_sync(int dev) | |||
439 | DMAbuf_launch_output(dev, dmap); | 439 | DMAbuf_launch_output(dev, dmap); |
440 | adev->dmap_out->flags |= DMA_SYNCING; | 440 | adev->dmap_out->flags |= DMA_SYNCING; |
441 | adev->dmap_out->underrun_count = 0; | 441 | adev->dmap_out->underrun_count = 0; |
442 | while (!signal_pending(current) && n++ <= adev->dmap_out->nbufs && | 442 | while (!signal_pending(current) && n++ < adev->dmap_out->nbufs && |
443 | adev->dmap_out->qlen && adev->dmap_out->underrun_count == 0) { | 443 | adev->dmap_out->qlen && adev->dmap_out->underrun_count == 0) { |
444 | long t = dmabuf_timeout(dmap); | 444 | long t = dmabuf_timeout(dmap); |
445 | spin_unlock_irqrestore(&dmap->lock,flags); | 445 | spin_unlock_irqrestore(&dmap->lock,flags); |
diff --git a/sound/oss/dmasound/dmasound_atari.c b/sound/oss/dmasound/dmasound_atari.c index 38931f2f6967..1f4774123064 100644 --- a/sound/oss/dmasound/dmasound_atari.c +++ b/sound/oss/dmasound/dmasound_atari.c | |||
@@ -1524,7 +1524,7 @@ static SETTINGS def_soft = { | |||
1524 | .speed = 8000 | 1524 | .speed = 8000 |
1525 | } ; | 1525 | } ; |
1526 | 1526 | ||
1527 | static MACHINE machTT = { | 1527 | static __initdata MACHINE machTT = { |
1528 | .name = "Atari", | 1528 | .name = "Atari", |
1529 | .name2 = "TT", | 1529 | .name2 = "TT", |
1530 | .owner = THIS_MODULE, | 1530 | .owner = THIS_MODULE, |
@@ -1553,7 +1553,7 @@ static MACHINE machTT = { | |||
1553 | .capabilities = DSP_CAP_BATCH /* As per SNDCTL_DSP_GETCAPS */ | 1553 | .capabilities = DSP_CAP_BATCH /* As per SNDCTL_DSP_GETCAPS */ |
1554 | }; | 1554 | }; |
1555 | 1555 | ||
1556 | static MACHINE machFalcon = { | 1556 | static __initdata MACHINE machFalcon = { |
1557 | .name = "Atari", | 1557 | .name = "Atari", |
1558 | .name2 = "FALCON", | 1558 | .name2 = "FALCON", |
1559 | .dma_alloc = AtaAlloc, | 1559 | .dma_alloc = AtaAlloc, |
diff --git a/sound/oss/pas2_card.c b/sound/oss/pas2_card.c index 25f3a22c52ee..7f377ec3486d 100644 --- a/sound/oss/pas2_card.c +++ b/sound/oss/pas2_card.c | |||
@@ -156,9 +156,7 @@ static int __init config_pas_hw(struct address_info *hw_config) | |||
156 | * 0x80 | 156 | * 0x80 |
157 | */ , 0xB88); | 157 | */ , 0xB88); |
158 | 158 | ||
159 | pas_write(0x80 | 159 | pas_write(0x80 | (joystick ? 0x40 : 0), 0xF388); |
160 | | joystick?0x40:0 | ||
161 | ,0xF388); | ||
162 | 160 | ||
163 | if (pas_irq < 0 || pas_irq > 15) | 161 | if (pas_irq < 0 || pas_irq > 15) |
164 | { | 162 | { |
diff --git a/sound/oss/pss.c b/sound/oss/pss.c index 16ed06950dc1..16517a5a1301 100644 --- a/sound/oss/pss.c +++ b/sound/oss/pss.c | |||
@@ -457,10 +457,9 @@ static void pss_mixer_reset(pss_confdata *devc) | |||
457 | } | 457 | } |
458 | } | 458 | } |
459 | 459 | ||
460 | static int set_volume_mono(unsigned __user *p, int *aleft) | 460 | static int set_volume_mono(unsigned __user *p, unsigned int *aleft) |
461 | { | 461 | { |
462 | int left; | 462 | unsigned int left, volume; |
463 | unsigned volume; | ||
464 | if (get_user(volume, p)) | 463 | if (get_user(volume, p)) |
465 | return -EFAULT; | 464 | return -EFAULT; |
466 | 465 | ||
@@ -471,10 +470,11 @@ static int set_volume_mono(unsigned __user *p, int *aleft) | |||
471 | return 0; | 470 | return 0; |
472 | } | 471 | } |
473 | 472 | ||
474 | static int set_volume_stereo(unsigned __user *p, int *aleft, int *aright) | 473 | static int set_volume_stereo(unsigned __user *p, |
474 | unsigned int *aleft, | ||
475 | unsigned int *aright) | ||
475 | { | 476 | { |
476 | int left, right; | 477 | unsigned int left, right, volume; |
477 | unsigned volume; | ||
478 | if (get_user(volume, p)) | 478 | if (get_user(volume, p)) |
479 | return -EFAULT; | 479 | return -EFAULT; |
480 | 480 | ||
diff --git a/sound/oss/sequencer.c b/sound/oss/sequencer.c index 5c215f787ca9..c79874696bec 100644 --- a/sound/oss/sequencer.c +++ b/sound/oss/sequencer.c | |||
@@ -212,7 +212,6 @@ int sequencer_write(int dev, struct file *file, const char __user *buf, int coun | |||
212 | { | 212 | { |
213 | unsigned char event_rec[EV_SZ], ev_code; | 213 | unsigned char event_rec[EV_SZ], ev_code; |
214 | int p = 0, c, ev_size; | 214 | int p = 0, c, ev_size; |
215 | int err; | ||
216 | int mode = translate_mode(file); | 215 | int mode = translate_mode(file); |
217 | 216 | ||
218 | dev = dev >> 4; | 217 | dev = dev >> 4; |
@@ -285,7 +284,7 @@ int sequencer_write(int dev, struct file *file, const char __user *buf, int coun | |||
285 | { | 284 | { |
286 | if (!midi_opened[event_rec[2]]) | 285 | if (!midi_opened[event_rec[2]]) |
287 | { | 286 | { |
288 | int mode; | 287 | int err, mode; |
289 | int dev = event_rec[2]; | 288 | int dev = event_rec[2]; |
290 | 289 | ||
291 | if (dev >= max_mididev || midi_devs[dev]==NULL) | 290 | if (dev >= max_mididev || midi_devs[dev]==NULL) |
diff --git a/sound/oss/sh_dac_audio.c b/sound/oss/sh_dac_audio.c index e5d423994918..78cfb66e4c59 100644 --- a/sound/oss/sh_dac_audio.c +++ b/sound/oss/sh_dac_audio.c | |||
@@ -135,7 +135,9 @@ static int dac_audio_ioctl(struct inode *inode, struct file *file, | |||
135 | return put_user(AFMT_U8, (int *)arg); | 135 | return put_user(AFMT_U8, (int *)arg); |
136 | 136 | ||
137 | case SNDCTL_DSP_NONBLOCK: | 137 | case SNDCTL_DSP_NONBLOCK: |
138 | spin_lock(&file->f_lock); | ||
138 | file->f_flags |= O_NONBLOCK; | 139 | file->f_flags |= O_NONBLOCK; |
140 | spin_unlock(&file->f_lock); | ||
139 | return 0; | 141 | return 0; |
140 | 142 | ||
141 | case SNDCTL_DSP_GETCAPS: | 143 | case SNDCTL_DSP_GETCAPS: |
diff --git a/sound/oss/swarm_cs4297a.c b/sound/oss/swarm_cs4297a.c index 41562ecde5bb..1edab7b4ea83 100644 --- a/sound/oss/swarm_cs4297a.c +++ b/sound/oss/swarm_cs4297a.c | |||
@@ -2200,7 +2200,9 @@ static int cs4297a_ioctl(struct inode *inode, struct file *file, | |||
2200 | sizeof(abinfo)) ? -EFAULT : 0; | 2200 | sizeof(abinfo)) ? -EFAULT : 0; |
2201 | 2201 | ||
2202 | case SNDCTL_DSP_NONBLOCK: | 2202 | case SNDCTL_DSP_NONBLOCK: |
2203 | spin_lock(&file->f_lock); | ||
2203 | file->f_flags |= O_NONBLOCK; | 2204 | file->f_flags |= O_NONBLOCK; |
2205 | spin_unlock(&file->f_lock); | ||
2204 | return 0; | 2206 | return 0; |
2205 | 2207 | ||
2206 | case SNDCTL_DSP_GETODELAY: | 2208 | case SNDCTL_DSP_GETODELAY: |
diff --git a/sound/oss/vwsnd.c b/sound/oss/vwsnd.c index 78b8acc7c3b9..187f72750e8f 100644 --- a/sound/oss/vwsnd.c +++ b/sound/oss/vwsnd.c | |||
@@ -2673,7 +2673,9 @@ static int vwsnd_audio_do_ioctl(struct inode *inode, | |||
2673 | 2673 | ||
2674 | case SNDCTL_DSP_NONBLOCK: /* _SIO ('P',14) */ | 2674 | case SNDCTL_DSP_NONBLOCK: /* _SIO ('P',14) */ |
2675 | DBGX("SNDCTL_DSP_NONBLOCK\n"); | 2675 | DBGX("SNDCTL_DSP_NONBLOCK\n"); |
2676 | spin_lock(&file->f_lock); | ||
2676 | file->f_flags |= O_NONBLOCK; | 2677 | file->f_flags |= O_NONBLOCK; |
2678 | spin_unlock(&file->f_lock); | ||
2677 | return 0; | 2679 | return 0; |
2678 | 2680 | ||
2679 | case SNDCTL_DSP_RESET: /* _SIO ('P', 0) */ | 2681 | case SNDCTL_DSP_RESET: /* _SIO ('P', 0) */ |
diff --git a/sound/parisc/harmony.c b/sound/parisc/harmony.c index 41f870f8a11d..6055fd6d3b38 100644 --- a/sound/parisc/harmony.c +++ b/sound/parisc/harmony.c | |||
@@ -975,9 +975,9 @@ snd_harmony_probe(struct parisc_device *padev) | |||
975 | struct snd_card *card; | 975 | struct snd_card *card; |
976 | struct snd_harmony *h; | 976 | struct snd_harmony *h; |
977 | 977 | ||
978 | card = snd_card_new(index, id, THIS_MODULE, 0); | 978 | err = snd_card_create(index, id, THIS_MODULE, 0, &card); |
979 | if (card == NULL) | 979 | if (err < 0) |
980 | return -ENOMEM; | 980 | return err; |
981 | 981 | ||
982 | err = snd_harmony_create(card, padev, &h); | 982 | err = snd_harmony_create(card, padev, &h); |
983 | if (err < 0) | 983 | if (err < 0) |
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index 82b9bddcdcd6..ca25e6179d76 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig | |||
@@ -400,6 +400,26 @@ config SND_INDIGODJ | |||
400 | To compile this driver as a module, choose M here: the module | 400 | To compile this driver as a module, choose M here: the module |
401 | will be called snd-indigodj | 401 | will be called snd-indigodj |
402 | 402 | ||
403 | config SND_INDIGOIOX | ||
404 | tristate "(Echoaudio) Indigo IOx" | ||
405 | select FW_LOADER | ||
406 | select SND_PCM | ||
407 | help | ||
408 | Say 'Y' or 'M' to include support for Echoaudio Indigo IOx. | ||
409 | |||
410 | To compile this driver as a module, choose M here: the module | ||
411 | will be called snd-indigoiox | ||
412 | |||
413 | config SND_INDIGODJX | ||
414 | tristate "(Echoaudio) Indigo DJx" | ||
415 | select FW_LOADER | ||
416 | select SND_PCM | ||
417 | help | ||
418 | Say 'Y' or 'M' to include support for Echoaudio Indigo DJx. | ||
419 | |||
420 | To compile this driver as a module, choose M here: the module | ||
421 | will be called snd-indigodjx | ||
422 | |||
403 | config SND_EMU10K1 | 423 | config SND_EMU10K1 |
404 | tristate "Emu10k1 (SB Live!, Audigy, E-mu APS)" | 424 | tristate "Emu10k1 (SB Live!, Audigy, E-mu APS)" |
405 | select FW_LOADER | 425 | select FW_LOADER |
@@ -744,7 +764,8 @@ config SND_VIRTUOSO | |||
744 | select SND_OXYGEN_LIB | 764 | select SND_OXYGEN_LIB |
745 | help | 765 | help |
746 | Say Y here to include support for sound cards based on the | 766 | Say Y here to include support for sound cards based on the |
747 | Asus AV100/AV200 chips, i.e., Xonar D1, DX, D2 and D2X. | 767 | Asus AV100/AV200 chips, i.e., Xonar D1, DX, D2, D2X, and |
768 | Essence STX. | ||
748 | Support for the HDAV1.3 (Deluxe) is very experimental. | 769 | Support for the HDAV1.3 (Deluxe) is very experimental. |
749 | 770 | ||
750 | To compile this driver as a module, choose M here: the module | 771 | To compile this driver as a module, choose M here: the module |
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index e2b843b4f9d0..97ee127ac33d 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c | |||
@@ -143,6 +143,7 @@ static const struct ac97_codec_id snd_ac97_codec_ids[] = { | |||
143 | { 0x43525970, 0xfffffff8, "CS4202", NULL, NULL }, | 143 | { 0x43525970, 0xfffffff8, "CS4202", NULL, NULL }, |
144 | { 0x43585421, 0xffffffff, "HSD11246", NULL, NULL }, // SmartMC II | 144 | { 0x43585421, 0xffffffff, "HSD11246", NULL, NULL }, // SmartMC II |
145 | { 0x43585428, 0xfffffff8, "Cx20468", patch_conexant, NULL }, // SmartAMC fixme: the mask might be different | 145 | { 0x43585428, 0xfffffff8, "Cx20468", patch_conexant, NULL }, // SmartAMC fixme: the mask might be different |
146 | { 0x43585430, 0xffffffff, "Cx20468-31", patch_conexant, NULL }, | ||
146 | { 0x43585431, 0xffffffff, "Cx20551", patch_cx20551, NULL }, | 147 | { 0x43585431, 0xffffffff, "Cx20551", patch_cx20551, NULL }, |
147 | { 0x44543031, 0xfffffff0, "DT0398", NULL, NULL }, | 148 | { 0x44543031, 0xfffffff0, "DT0398", NULL, NULL }, |
148 | { 0x454d4328, 0xffffffff, "EM28028", NULL, NULL }, // same as TR28028? | 149 | { 0x454d4328, 0xffffffff, "EM28028", NULL, NULL }, // same as TR28028? |
@@ -383,7 +384,7 @@ int snd_ac97_update_bits(struct snd_ac97 *ac97, unsigned short reg, unsigned sho | |||
383 | 384 | ||
384 | EXPORT_SYMBOL(snd_ac97_update_bits); | 385 | EXPORT_SYMBOL(snd_ac97_update_bits); |
385 | 386 | ||
386 | /* no lock version - see snd_ac97_updat_bits() */ | 387 | /* no lock version - see snd_ac97_update_bits() */ |
387 | int snd_ac97_update_bits_nolock(struct snd_ac97 *ac97, unsigned short reg, | 388 | int snd_ac97_update_bits_nolock(struct snd_ac97 *ac97, unsigned short reg, |
388 | unsigned short mask, unsigned short value) | 389 | unsigned short mask, unsigned short value) |
389 | { | 390 | { |
@@ -1643,7 +1644,10 @@ static int snd_ac97_modem_build(struct snd_card *card, struct snd_ac97 * ac97) | |||
1643 | { | 1644 | { |
1644 | int err, idx; | 1645 | int err, idx; |
1645 | 1646 | ||
1646 | //printk("AC97_GPIO_CFG = %x\n",snd_ac97_read(ac97,AC97_GPIO_CFG)); | 1647 | /* |
1648 | printk(KERN_DEBUG "AC97_GPIO_CFG = %x\n", | ||
1649 | snd_ac97_read(ac97,AC97_GPIO_CFG)); | ||
1650 | */ | ||
1647 | snd_ac97_write(ac97, AC97_GPIO_CFG, 0xffff & ~(AC97_GPIO_LINE1_OH)); | 1651 | snd_ac97_write(ac97, AC97_GPIO_CFG, 0xffff & ~(AC97_GPIO_LINE1_OH)); |
1648 | snd_ac97_write(ac97, AC97_GPIO_POLARITY, 0xffff & ~(AC97_GPIO_LINE1_OH)); | 1652 | snd_ac97_write(ac97, AC97_GPIO_POLARITY, 0xffff & ~(AC97_GPIO_LINE1_OH)); |
1649 | snd_ac97_write(ac97, AC97_GPIO_STICKY, 0xffff); | 1653 | snd_ac97_write(ac97, AC97_GPIO_STICKY, 0xffff); |
diff --git a/sound/pci/ac97/ac97_proc.c b/sound/pci/ac97/ac97_proc.c index 060ea59d5f02..73b17d526c8b 100644 --- a/sound/pci/ac97/ac97_proc.c +++ b/sound/pci/ac97/ac97_proc.c | |||
@@ -125,6 +125,8 @@ static void snd_ac97_proc_read_main(struct snd_ac97 *ac97, struct snd_info_buffe | |||
125 | snd_iprintf(buffer, "PCI Subsys Device: 0x%04x\n\n", | 125 | snd_iprintf(buffer, "PCI Subsys Device: 0x%04x\n\n", |
126 | ac97->subsystem_device); | 126 | ac97->subsystem_device); |
127 | 127 | ||
128 | snd_iprintf(buffer, "Flags: %x\n", ac97->flags); | ||
129 | |||
128 | if ((ac97->ext_id & AC97_EI_REV_MASK) >= AC97_EI_REV_23) { | 130 | if ((ac97->ext_id & AC97_EI_REV_MASK) >= AC97_EI_REV_23) { |
129 | val = snd_ac97_read(ac97, AC97_INT_PAGING); | 131 | val = snd_ac97_read(ac97, AC97_INT_PAGING); |
130 | snd_ac97_update_bits(ac97, AC97_INT_PAGING, | 132 | snd_ac97_update_bits(ac97, AC97_INT_PAGING, |
diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c index a7f38e63303f..d1f242bd0ac5 100644 --- a/sound/pci/ad1889.c +++ b/sound/pci/ad1889.c | |||
@@ -995,10 +995,10 @@ snd_ad1889_probe(struct pci_dev *pci, | |||
995 | } | 995 | } |
996 | 996 | ||
997 | /* (2) */ | 997 | /* (2) */ |
998 | card = snd_card_new(index[devno], id[devno], THIS_MODULE, 0); | 998 | err = snd_card_create(index[devno], id[devno], THIS_MODULE, 0, &card); |
999 | /* XXX REVISIT: we can probably allocate chip in this call */ | 999 | /* XXX REVISIT: we can probably allocate chip in this call */ |
1000 | if (card == NULL) | 1000 | if (err < 0) |
1001 | return -ENOMEM; | 1001 | return err; |
1002 | 1002 | ||
1003 | strcpy(card->driver, "AD1889"); | 1003 | strcpy(card->driver, "AD1889"); |
1004 | strcpy(card->shortname, "Analog Devices AD1889"); | 1004 | strcpy(card->shortname, "Analog Devices AD1889"); |
diff --git a/sound/pci/ak4531_codec.c b/sound/pci/ak4531_codec.c index 0f819ddb3ebf..fd135e3d8a84 100644 --- a/sound/pci/ak4531_codec.c +++ b/sound/pci/ak4531_codec.c | |||
@@ -51,7 +51,8 @@ static void snd_ak4531_dump(struct snd_ak4531 *ak4531) | |||
51 | int idx; | 51 | int idx; |
52 | 52 | ||
53 | for (idx = 0; idx < 0x19; idx++) | 53 | for (idx = 0; idx < 0x19; idx++) |
54 | printk("ak4531 0x%x: 0x%x\n", idx, ak4531->regs[idx]); | 54 | printk(KERN_DEBUG "ak4531 0x%x: 0x%x\n", |
55 | idx, ak4531->regs[idx]); | ||
55 | } | 56 | } |
56 | 57 | ||
57 | #endif | 58 | #endif |
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index 1a0fd65ec280..4edf270a7809 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c | |||
@@ -2142,7 +2142,7 @@ static int __devinit snd_ali_resources(struct snd_ali *codec) | |||
2142 | { | 2142 | { |
2143 | int err; | 2143 | int err; |
2144 | 2144 | ||
2145 | snd_ali_printk("resouces allocation ...\n"); | 2145 | snd_ali_printk("resources allocation ...\n"); |
2146 | err = pci_request_regions(codec->pci, "ALI 5451"); | 2146 | err = pci_request_regions(codec->pci, "ALI 5451"); |
2147 | if (err < 0) | 2147 | if (err < 0) |
2148 | return err; | 2148 | return err; |
@@ -2154,7 +2154,7 @@ static int __devinit snd_ali_resources(struct snd_ali *codec) | |||
2154 | return -EBUSY; | 2154 | return -EBUSY; |
2155 | } | 2155 | } |
2156 | codec->irq = codec->pci->irq; | 2156 | codec->irq = codec->pci->irq; |
2157 | snd_ali_printk("resouces allocated.\n"); | 2157 | snd_ali_printk("resources allocated.\n"); |
2158 | return 0; | 2158 | return 0; |
2159 | } | 2159 | } |
2160 | static int snd_ali_dev_free(struct snd_device *device) | 2160 | static int snd_ali_dev_free(struct snd_device *device) |
@@ -2307,9 +2307,9 @@ static int __devinit snd_ali_probe(struct pci_dev *pci, | |||
2307 | 2307 | ||
2308 | snd_ali_printk("probe ...\n"); | 2308 | snd_ali_printk("probe ...\n"); |
2309 | 2309 | ||
2310 | card = snd_card_new(index, id, THIS_MODULE, 0); | 2310 | err = snd_card_create(index, id, THIS_MODULE, 0, &card); |
2311 | if (!card) | 2311 | if (err < 0) |
2312 | return -ENOMEM; | 2312 | return err; |
2313 | 2313 | ||
2314 | err = snd_ali_create(card, pci, pcm_channels, spdif, &codec); | 2314 | err = snd_ali_create(card, pci, pcm_channels, spdif, &codec); |
2315 | if (err < 0) | 2315 | if (err < 0) |
diff --git a/sound/pci/als300.c b/sound/pci/als300.c index 8df6824b51cd..009b4c8225a5 100644 --- a/sound/pci/als300.c +++ b/sound/pci/als300.c | |||
@@ -91,7 +91,7 @@ | |||
91 | #define DEBUG_PLAY_REC 0 | 91 | #define DEBUG_PLAY_REC 0 |
92 | 92 | ||
93 | #if DEBUG_CALLS | 93 | #if DEBUG_CALLS |
94 | #define snd_als300_dbgcalls(format, args...) printk(format, ##args) | 94 | #define snd_als300_dbgcalls(format, args...) printk(KERN_DEBUG format, ##args) |
95 | #define snd_als300_dbgcallenter() printk(KERN_ERR "--> %s\n", __func__) | 95 | #define snd_als300_dbgcallenter() printk(KERN_ERR "--> %s\n", __func__) |
96 | #define snd_als300_dbgcallleave() printk(KERN_ERR "<-- %s\n", __func__) | 96 | #define snd_als300_dbgcallleave() printk(KERN_ERR "<-- %s\n", __func__) |
97 | #else | 97 | #else |
@@ -812,10 +812,10 @@ static int __devinit snd_als300_probe(struct pci_dev *pci, | |||
812 | return -ENOENT; | 812 | return -ENOENT; |
813 | } | 813 | } |
814 | 814 | ||
815 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 815 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); |
816 | 816 | ||
817 | if (card == NULL) | 817 | if (err < 0) |
818 | return -ENOMEM; | 818 | return err; |
819 | 819 | ||
820 | chip_type = pci_id->driver_data; | 820 | chip_type = pci_id->driver_data; |
821 | 821 | ||
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c index ba570053d4d5..542a0c65a92c 100644 --- a/sound/pci/als4000.c +++ b/sound/pci/als4000.c | |||
@@ -889,12 +889,13 @@ static int __devinit snd_card_als4000_probe(struct pci_dev *pci, | |||
889 | pci_write_config_word(pci, PCI_COMMAND, word | PCI_COMMAND_IO); | 889 | pci_write_config_word(pci, PCI_COMMAND, word | PCI_COMMAND_IO); |
890 | pci_set_master(pci); | 890 | pci_set_master(pci); |
891 | 891 | ||
892 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, | 892 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, |
893 | sizeof(*acard) /* private_data: acard */); | 893 | sizeof(*acard) /* private_data: acard */, |
894 | if (card == NULL) { | 894 | &card); |
895 | if (err < 0) { | ||
895 | pci_release_regions(pci); | 896 | pci_release_regions(pci); |
896 | pci_disable_device(pci); | 897 | pci_disable_device(pci); |
897 | return -ENOMEM; | 898 | return err; |
898 | } | 899 | } |
899 | 900 | ||
900 | acard = card->private_data; | 901 | acard = card->private_data; |
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index 226fe8237d31..9ce8548c03e4 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c | |||
@@ -1645,9 +1645,9 @@ static int __devinit snd_atiixp_probe(struct pci_dev *pci, | |||
1645 | struct atiixp *chip; | 1645 | struct atiixp *chip; |
1646 | int err; | 1646 | int err; |
1647 | 1647 | ||
1648 | card = snd_card_new(index, id, THIS_MODULE, 0); | 1648 | err = snd_card_create(index, id, THIS_MODULE, 0, &card); |
1649 | if (card == NULL) | 1649 | if (err < 0) |
1650 | return -ENOMEM; | 1650 | return err; |
1651 | 1651 | ||
1652 | strcpy(card->driver, spdif_aclink ? "ATIIXP" : "ATIIXP-SPDMA"); | 1652 | strcpy(card->driver, spdif_aclink ? "ATIIXP" : "ATIIXP-SPDMA"); |
1653 | strcpy(card->shortname, "ATI IXP"); | 1653 | strcpy(card->shortname, "ATI IXP"); |
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index 0e6e5cc1c501..c3136cccc559 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c | |||
@@ -1288,9 +1288,9 @@ static int __devinit snd_atiixp_probe(struct pci_dev *pci, | |||
1288 | struct atiixp_modem *chip; | 1288 | struct atiixp_modem *chip; |
1289 | int err; | 1289 | int err; |
1290 | 1290 | ||
1291 | card = snd_card_new(index, id, THIS_MODULE, 0); | 1291 | err = snd_card_create(index, id, THIS_MODULE, 0, &card); |
1292 | if (card == NULL) | 1292 | if (err < 0) |
1293 | return -ENOMEM; | 1293 | return err; |
1294 | 1294 | ||
1295 | strcpy(card->driver, "ATIIXP-MODEM"); | 1295 | strcpy(card->driver, "ATIIXP-MODEM"); |
1296 | strcpy(card->shortname, "ATI IXP Modem"); | 1296 | strcpy(card->shortname, "ATI IXP Modem"); |
diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c index a36d4d1fd419..9ec122383eef 100644 --- a/sound/pci/au88x0/au88x0.c +++ b/sound/pci/au88x0/au88x0.c | |||
@@ -250,9 +250,9 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) | |||
250 | return -ENOENT; | 250 | return -ENOENT; |
251 | } | 251 | } |
252 | // (2) | 252 | // (2) |
253 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 253 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); |
254 | if (card == NULL) | 254 | if (err < 0) |
255 | return -ENOMEM; | 255 | return err; |
256 | 256 | ||
257 | // (3) | 257 | // (3) |
258 | if ((err = snd_vortex_create(card, pci, &chip)) < 0) { | 258 | if ((err = snd_vortex_create(card, pci, &chip)) < 0) { |
diff --git a/sound/pci/au88x0/au88x0_a3d.c b/sound/pci/au88x0/au88x0_a3d.c index 649849e540d3..f4aa8ff6f5f9 100644 --- a/sound/pci/au88x0/au88x0_a3d.c +++ b/sound/pci/au88x0/au88x0_a3d.c | |||
@@ -462,9 +462,10 @@ static void a3dsrc_ZeroSliceIO(a3dsrc_t * a) | |||
462 | /* Reset Single A3D source. */ | 462 | /* Reset Single A3D source. */ |
463 | static void a3dsrc_ZeroState(a3dsrc_t * a) | 463 | static void a3dsrc_ZeroState(a3dsrc_t * a) |
464 | { | 464 | { |
465 | 465 | /* | |
466 | //printk("vortex: ZeroState slice: %d, source %d\n", a->slice, a->source); | 466 | printk(KERN_DEBUG "vortex: ZeroState slice: %d, source %d\n", |
467 | 467 | a->slice, a->source); | |
468 | */ | ||
468 | a3dsrc_SetAtmosState(a, 0, 0, 0, 0); | 469 | a3dsrc_SetAtmosState(a, 0, 0, 0, 0); |
469 | a3dsrc_SetHrtfState(a, A3dHrirZeros, A3dHrirZeros); | 470 | a3dsrc_SetHrtfState(a, A3dHrirZeros, A3dHrirZeros); |
470 | a3dsrc_SetItdDline(a, A3dItdDlineZeros); | 471 | a3dsrc_SetItdDline(a, A3dItdDlineZeros); |
diff --git a/sound/pci/au88x0/au88x0_core.c b/sound/pci/au88x0/au88x0_core.c index b070e5714514..3906f5afe27a 100644 --- a/sound/pci/au88x0/au88x0_core.c +++ b/sound/pci/au88x0/au88x0_core.c | |||
@@ -1135,7 +1135,10 @@ vortex_adbdma_setbuffers(vortex_t * vortex, int adbdma, | |||
1135 | snd_pcm_sgbuf_get_addr(dma->substream, 0)); | 1135 | snd_pcm_sgbuf_get_addr(dma->substream, 0)); |
1136 | break; | 1136 | break; |
1137 | } | 1137 | } |
1138 | //printk("vortex: cfg0 = 0x%x\nvortex: cfg1=0x%x\n", dma->cfg0, dma->cfg1); | 1138 | /* |
1139 | printk(KERN_DEBUG "vortex: cfg0 = 0x%x\nvortex: cfg1=0x%x\n", | ||
1140 | dma->cfg0, dma->cfg1); | ||
1141 | */ | ||
1139 | hwwrite(vortex->mmio, VORTEX_ADBDMA_BUFCFG0 + (adbdma << 3), dma->cfg0); | 1142 | hwwrite(vortex->mmio, VORTEX_ADBDMA_BUFCFG0 + (adbdma << 3), dma->cfg0); |
1140 | hwwrite(vortex->mmio, VORTEX_ADBDMA_BUFCFG1 + (adbdma << 3), dma->cfg1); | 1143 | hwwrite(vortex->mmio, VORTEX_ADBDMA_BUFCFG1 + (adbdma << 3), dma->cfg1); |
1141 | 1144 | ||
@@ -1959,7 +1962,7 @@ vortex_connect_codecplay(vortex_t * vortex, int en, unsigned char mixers[]) | |||
1959 | ADB_CODECOUT(0 + 4)); | 1962 | ADB_CODECOUT(0 + 4)); |
1960 | vortex_connection_mix_adb(vortex, en, 0x11, mixers[3], | 1963 | vortex_connection_mix_adb(vortex, en, 0x11, mixers[3], |
1961 | ADB_CODECOUT(1 + 4)); | 1964 | ADB_CODECOUT(1 + 4)); |
1962 | //printk("SDAC detected "); | 1965 | /* printk(KERN_DEBUG "SDAC detected "); */ |
1963 | } | 1966 | } |
1964 | #else | 1967 | #else |
1965 | // Use plain direct output to codec. | 1968 | // Use plain direct output to codec. |
@@ -2013,7 +2016,11 @@ vortex_adb_checkinout(vortex_t * vortex, int resmap[], int out, int restype) | |||
2013 | resmap[restype] |= (1 << i); | 2016 | resmap[restype] |= (1 << i); |
2014 | else | 2017 | else |
2015 | vortex->dma_adb[i].resources[restype] |= (1 << i); | 2018 | vortex->dma_adb[i].resources[restype] |= (1 << i); |
2016 | //printk("vortex: ResManager: type %d out %d\n", restype, i); | 2019 | /* |
2020 | printk(KERN_DEBUG | ||
2021 | "vortex: ResManager: type %d out %d\n", | ||
2022 | restype, i); | ||
2023 | */ | ||
2017 | return i; | 2024 | return i; |
2018 | } | 2025 | } |
2019 | } | 2026 | } |
@@ -2024,7 +2031,11 @@ vortex_adb_checkinout(vortex_t * vortex, int resmap[], int out, int restype) | |||
2024 | for (i = 0; i < qty; i++) { | 2031 | for (i = 0; i < qty; i++) { |
2025 | if (resmap[restype] & (1 << i)) { | 2032 | if (resmap[restype] & (1 << i)) { |
2026 | resmap[restype] &= ~(1 << i); | 2033 | resmap[restype] &= ~(1 << i); |
2027 | //printk("vortex: ResManager: type %d in %d\n",restype, i); | 2034 | /* |
2035 | printk(KERN_DEBUG | ||
2036 | "vortex: ResManager: type %d in %d\n", | ||
2037 | restype, i); | ||
2038 | */ | ||
2028 | return i; | 2039 | return i; |
2029 | } | 2040 | } |
2030 | } | 2041 | } |
@@ -2789,7 +2800,7 @@ vortex_translateformat(vortex_t * vortex, char bits, char nch, int encod) | |||
2789 | { | 2800 | { |
2790 | int a, this_194; | 2801 | int a, this_194; |
2791 | 2802 | ||
2792 | if ((bits != 8) || (bits != 16)) | 2803 | if ((bits != 8) && (bits != 16)) |
2793 | return -1; | 2804 | return -1; |
2794 | 2805 | ||
2795 | switch (encod) { | 2806 | switch (encod) { |
diff --git a/sound/pci/au88x0/au88x0_synth.c b/sound/pci/au88x0/au88x0_synth.c index 978b856f5621..2805e34bd41d 100644 --- a/sound/pci/au88x0/au88x0_synth.c +++ b/sound/pci/au88x0/au88x0_synth.c | |||
@@ -213,38 +213,59 @@ vortex_wt_SetReg(vortex_t * vortex, unsigned char reg, int wt, | |||
213 | switch (reg) { | 213 | switch (reg) { |
214 | /* Voice specific parameters */ | 214 | /* Voice specific parameters */ |
215 | case 0: /* running */ | 215 | case 0: /* running */ |
216 | //printk("vortex: WT SetReg(0x%x) = 0x%08x\n", WT_RUN(wt), (int)val); | 216 | /* |
217 | printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n", | ||
218 | WT_RUN(wt), (int)val); | ||
219 | */ | ||
217 | hwwrite(vortex->mmio, WT_RUN(wt), val); | 220 | hwwrite(vortex->mmio, WT_RUN(wt), val); |
218 | return 0xc; | 221 | return 0xc; |
219 | break; | 222 | break; |
220 | case 1: /* param 0 */ | 223 | case 1: /* param 0 */ |
221 | //printk("vortex: WT SetReg(0x%x) = 0x%08x\n", WT_PARM(wt,0), (int)val); | 224 | /* |
225 | printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n", | ||
226 | WT_PARM(wt,0), (int)val); | ||
227 | */ | ||
222 | hwwrite(vortex->mmio, WT_PARM(wt, 0), val); | 228 | hwwrite(vortex->mmio, WT_PARM(wt, 0), val); |
223 | return 0xc; | 229 | return 0xc; |
224 | break; | 230 | break; |
225 | case 2: /* param 1 */ | 231 | case 2: /* param 1 */ |
226 | //printk("vortex: WT SetReg(0x%x) = 0x%08x\n", WT_PARM(wt,1), (int)val); | 232 | /* |
233 | printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n", | ||
234 | WT_PARM(wt,1), (int)val); | ||
235 | */ | ||
227 | hwwrite(vortex->mmio, WT_PARM(wt, 1), val); | 236 | hwwrite(vortex->mmio, WT_PARM(wt, 1), val); |
228 | return 0xc; | 237 | return 0xc; |
229 | break; | 238 | break; |
230 | case 3: /* param 2 */ | 239 | case 3: /* param 2 */ |
231 | //printk("vortex: WT SetReg(0x%x) = 0x%08x\n", WT_PARM(wt,2), (int)val); | 240 | /* |
241 | printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n", | ||
242 | WT_PARM(wt,2), (int)val); | ||
243 | */ | ||
232 | hwwrite(vortex->mmio, WT_PARM(wt, 2), val); | 244 | hwwrite(vortex->mmio, WT_PARM(wt, 2), val); |
233 | return 0xc; | 245 | return 0xc; |
234 | break; | 246 | break; |
235 | case 4: /* param 3 */ | 247 | case 4: /* param 3 */ |
236 | //printk("vortex: WT SetReg(0x%x) = 0x%08x\n", WT_PARM(wt,3), (int)val); | 248 | /* |
249 | printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n", | ||
250 | WT_PARM(wt,3), (int)val); | ||
251 | */ | ||
237 | hwwrite(vortex->mmio, WT_PARM(wt, 3), val); | 252 | hwwrite(vortex->mmio, WT_PARM(wt, 3), val); |
238 | return 0xc; | 253 | return 0xc; |
239 | break; | 254 | break; |
240 | case 6: /* mute */ | 255 | case 6: /* mute */ |
241 | //printk("vortex: WT SetReg(0x%x) = 0x%08x\n", WT_MUTE(wt), (int)val); | 256 | /* |
257 | printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n", | ||
258 | WT_MUTE(wt), (int)val); | ||
259 | */ | ||
242 | hwwrite(vortex->mmio, WT_MUTE(wt), val); | 260 | hwwrite(vortex->mmio, WT_MUTE(wt), val); |
243 | return 0xc; | 261 | return 0xc; |
244 | break; | 262 | break; |
245 | case 0xb: | 263 | case 0xb: |
246 | { /* delay */ | 264 | { /* delay */ |
247 | //printk("vortex: WT SetReg(0x%x) = 0x%08x\n", WT_DELAY(wt,0), (int)val); | 265 | /* |
266 | printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n", | ||
267 | WT_DELAY(wt,0), (int)val); | ||
268 | */ | ||
248 | hwwrite(vortex->mmio, WT_DELAY(wt, 3), val); | 269 | hwwrite(vortex->mmio, WT_DELAY(wt, 3), val); |
249 | hwwrite(vortex->mmio, WT_DELAY(wt, 2), val); | 270 | hwwrite(vortex->mmio, WT_DELAY(wt, 2), val); |
250 | hwwrite(vortex->mmio, WT_DELAY(wt, 1), val); | 271 | hwwrite(vortex->mmio, WT_DELAY(wt, 1), val); |
@@ -272,7 +293,9 @@ vortex_wt_SetReg(vortex_t * vortex, unsigned char reg, int wt, | |||
272 | return 0; | 293 | return 0; |
273 | break; | 294 | break; |
274 | } | 295 | } |
275 | //printk("vortex: WT SetReg(0x%x) = 0x%08x\n", ecx, (int)val); | 296 | /* |
297 | printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n", ecx, (int)val); | ||
298 | */ | ||
276 | hwwrite(vortex->mmio, ecx, val); | 299 | hwwrite(vortex->mmio, ecx, val); |
277 | return 1; | 300 | return 1; |
278 | } | 301 | } |
diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c index c7c54e7748e9..8eea29fc42fe 100644 --- a/sound/pci/aw2/aw2-alsa.c +++ b/sound/pci/aw2/aw2-alsa.c | |||
@@ -368,9 +368,9 @@ static int __devinit snd_aw2_probe(struct pci_dev *pci, | |||
368 | } | 368 | } |
369 | 369 | ||
370 | /* (2) Create card instance */ | 370 | /* (2) Create card instance */ |
371 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 371 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); |
372 | if (card == NULL) | 372 | if (err < 0) |
373 | return -ENOMEM; | 373 | return err; |
374 | 374 | ||
375 | /* (3) Create main component */ | 375 | /* (3) Create main component */ |
376 | err = snd_aw2_create(card, pci, &chip); | 376 | err = snd_aw2_create(card, pci, &chip); |
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index 333007c523a1..e9e9b5821d41 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c | |||
@@ -211,25 +211,25 @@ MODULE_SUPPORTED_DEVICE("{{Aztech,AZF3328}}"); | |||
211 | #endif | 211 | #endif |
212 | 212 | ||
213 | #if DEBUG_MIXER | 213 | #if DEBUG_MIXER |
214 | #define snd_azf3328_dbgmixer(format, args...) printk(format, ##args) | 214 | #define snd_azf3328_dbgmixer(format, args...) printk(KERN_DEBUG format, ##args) |
215 | #else | 215 | #else |
216 | #define snd_azf3328_dbgmixer(format, args...) | 216 | #define snd_azf3328_dbgmixer(format, args...) |
217 | #endif | 217 | #endif |
218 | 218 | ||
219 | #if DEBUG_PLAY_REC | 219 | #if DEBUG_PLAY_REC |
220 | #define snd_azf3328_dbgplay(format, args...) printk(KERN_ERR format, ##args) | 220 | #define snd_azf3328_dbgplay(format, args...) printk(KERN_DEBUG format, ##args) |
221 | #else | 221 | #else |
222 | #define snd_azf3328_dbgplay(format, args...) | 222 | #define snd_azf3328_dbgplay(format, args...) |
223 | #endif | 223 | #endif |
224 | 224 | ||
225 | #if DEBUG_MISC | 225 | #if DEBUG_MISC |
226 | #define snd_azf3328_dbgtimer(format, args...) printk(KERN_ERR format, ##args) | 226 | #define snd_azf3328_dbgtimer(format, args...) printk(KERN_DEBUG format, ##args) |
227 | #else | 227 | #else |
228 | #define snd_azf3328_dbgtimer(format, args...) | 228 | #define snd_azf3328_dbgtimer(format, args...) |
229 | #endif | 229 | #endif |
230 | 230 | ||
231 | #if DEBUG_GAME | 231 | #if DEBUG_GAME |
232 | #define snd_azf3328_dbggame(format, args...) printk(KERN_ERR format, ##args) | 232 | #define snd_azf3328_dbggame(format, args...) printk(KERN_DEBUG format, ##args) |
233 | #else | 233 | #else |
234 | #define snd_azf3328_dbggame(format, args...) | 234 | #define snd_azf3328_dbggame(format, args...) |
235 | #endif | 235 | #endif |
@@ -2216,9 +2216,9 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) | |||
2216 | return -ENOENT; | 2216 | return -ENOENT; |
2217 | } | 2217 | } |
2218 | 2218 | ||
2219 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 2219 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); |
2220 | if (card == NULL) | 2220 | if (err < 0) |
2221 | return -ENOMEM; | 2221 | return err; |
2222 | 2222 | ||
2223 | strcpy(card->driver, "AZF3328"); | 2223 | strcpy(card->driver, "AZF3328"); |
2224 | strcpy(card->shortname, "Aztech AZF3328 (PCI168)"); | 2224 | strcpy(card->shortname, "Aztech AZF3328 (PCI168)"); |
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c index 1aa1c0402540..a299340519df 100644 --- a/sound/pci/bt87x.c +++ b/sound/pci/bt87x.c | |||
@@ -888,9 +888,9 @@ static int __devinit snd_bt87x_probe(struct pci_dev *pci, | |||
888 | return -ENOENT; | 888 | return -ENOENT; |
889 | } | 889 | } |
890 | 890 | ||
891 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 891 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); |
892 | if (!card) | 892 | if (err < 0) |
893 | return -ENOMEM; | 893 | return err; |
894 | 894 | ||
895 | err = snd_bt87x_create(card, pci, &chip); | 895 | err = snd_bt87x_create(card, pci, &chip); |
896 | if (err < 0) | 896 | if (err < 0) |
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index 0e62205d4081..df757575798a 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c | |||
@@ -255,6 +255,14 @@ static struct snd_ca0106_details ca0106_chip_details[] = { | |||
255 | .gpio_type = 2, | 255 | .gpio_type = 2, |
256 | .i2c_adc = 1, | 256 | .i2c_adc = 1, |
257 | .spi_dac = 1 } , | 257 | .spi_dac = 1 } , |
258 | /* Giga-byte GA-G1975X mobo | ||
259 | * Novell bnc#395807 | ||
260 | */ | ||
261 | /* FIXME: the GPIO and I2C setting aren't tested well */ | ||
262 | { .serial = 0x1458a006, | ||
263 | .name = "Giga-byte GA-G1975X", | ||
264 | .gpio_type = 1, | ||
265 | .i2c_adc = 1 }, | ||
258 | /* Shuttle XPC SD31P which has an onboard Creative Labs | 266 | /* Shuttle XPC SD31P which has an onboard Creative Labs |
259 | * Sound Blaster Live! 24-bit EAX | 267 | * Sound Blaster Live! 24-bit EAX |
260 | * high-definition 7.1 audio processor". | 268 | * high-definition 7.1 audio processor". |
@@ -404,7 +412,9 @@ int snd_ca0106_i2c_write(struct snd_ca0106 *emu, | |||
404 | } | 412 | } |
405 | 413 | ||
406 | tmp = reg << 25 | value << 16; | 414 | tmp = reg << 25 | value << 16; |
407 | // snd_printk("I2C-write:reg=0x%x, value=0x%x\n", reg, value); | 415 | /* |
416 | snd_printk(KERN_DEBUG "I2C-write:reg=0x%x, value=0x%x\n", reg, value); | ||
417 | */ | ||
408 | /* Not sure what this I2C channel controls. */ | 418 | /* Not sure what this I2C channel controls. */ |
409 | /* snd_ca0106_ptr_write(emu, I2C_D0, 0, tmp); */ | 419 | /* snd_ca0106_ptr_write(emu, I2C_D0, 0, tmp); */ |
410 | 420 | ||
@@ -422,7 +432,7 @@ int snd_ca0106_i2c_write(struct snd_ca0106 *emu, | |||
422 | /* Wait till the transaction ends */ | 432 | /* Wait till the transaction ends */ |
423 | while (1) { | 433 | while (1) { |
424 | status = snd_ca0106_ptr_read(emu, I2C_A, 0); | 434 | status = snd_ca0106_ptr_read(emu, I2C_A, 0); |
425 | //snd_printk("I2C:status=0x%x\n", status); | 435 | /*snd_printk(KERN_DEBUG "I2C:status=0x%x\n", status);*/ |
426 | timeout++; | 436 | timeout++; |
427 | if ((status & I2C_A_ADC_START) == 0) | 437 | if ((status & I2C_A_ADC_START) == 0) |
428 | break; | 438 | break; |
@@ -521,7 +531,10 @@ static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substr | |||
521 | channel->number = channel_id; | 531 | channel->number = channel_id; |
522 | 532 | ||
523 | channel->use = 1; | 533 | channel->use = 1; |
524 | //printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel); | 534 | /* |
535 | printk(KERN_DEBUG "open:channel_id=%d, chip=%p, channel=%p\n", | ||
536 | channel_id, chip, channel); | ||
537 | */ | ||
525 | //channel->interrupt = snd_ca0106_pcm_channel_interrupt; | 538 | //channel->interrupt = snd_ca0106_pcm_channel_interrupt; |
526 | channel->epcm = epcm; | 539 | channel->epcm = epcm; |
527 | if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) | 540 | if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) |
@@ -614,7 +627,10 @@ static int snd_ca0106_pcm_open_capture_channel(struct snd_pcm_substream *substre | |||
614 | channel->number = channel_id; | 627 | channel->number = channel_id; |
615 | 628 | ||
616 | channel->use = 1; | 629 | channel->use = 1; |
617 | //printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel); | 630 | /* |
631 | printk(KERN_DEBUG "open:channel_id=%d, chip=%p, channel=%p\n", | ||
632 | channel_id, chip, channel); | ||
633 | */ | ||
618 | //channel->interrupt = snd_ca0106_pcm_channel_interrupt; | 634 | //channel->interrupt = snd_ca0106_pcm_channel_interrupt; |
619 | channel->epcm = epcm; | 635 | channel->epcm = epcm; |
620 | if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) | 636 | if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) |
@@ -705,9 +721,20 @@ static int snd_ca0106_pcm_prepare_playback(struct snd_pcm_substream *substream) | |||
705 | u32 reg71; | 721 | u32 reg71; |
706 | int i; | 722 | int i; |
707 | 723 | ||
708 | //snd_printk("prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, periods=%u, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, runtime->periods, frames_to_bytes(runtime, 1)); | 724 | #if 0 /* debug */ |
709 | //snd_printk("dma_addr=%x, dma_area=%p, table_base=%p\n",runtime->dma_addr, runtime->dma_area, table_base); | 725 | snd_printk(KERN_DEBUG |
710 | //snd_printk("dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",emu->buffer.addr, emu->buffer.area, emu->buffer.bytes); | 726 | "prepare:channel_number=%d, rate=%d, format=0x%x, " |
727 | "channels=%d, buffer_size=%ld, period_size=%ld, " | ||
728 | "periods=%u, frames_to_bytes=%d\n", | ||
729 | channel, runtime->rate, runtime->format, | ||
730 | runtime->channels, runtime->buffer_size, | ||
731 | runtime->period_size, runtime->periods, | ||
732 | frames_to_bytes(runtime, 1)); | ||
733 | snd_printk(KERN_DEBUG "dma_addr=%x, dma_area=%p, table_base=%p\n", | ||
734 | runtime->dma_addr, runtime->dma_area, table_base); | ||
735 | snd_printk(KERN_DEBUG "dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n", | ||
736 | emu->buffer.addr, emu->buffer.area, emu->buffer.bytes); | ||
737 | #endif /* debug */ | ||
711 | /* Rate can be set per channel. */ | 738 | /* Rate can be set per channel. */ |
712 | /* reg40 control host to fifo */ | 739 | /* reg40 control host to fifo */ |
713 | /* reg71 controls DAC rate. */ | 740 | /* reg71 controls DAC rate. */ |
@@ -799,9 +826,20 @@ static int snd_ca0106_pcm_prepare_capture(struct snd_pcm_substream *substream) | |||
799 | u32 reg71_set = 0; | 826 | u32 reg71_set = 0; |
800 | u32 reg71; | 827 | u32 reg71; |
801 | 828 | ||
802 | //snd_printk("prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, periods=%u, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, runtime->periods, frames_to_bytes(runtime, 1)); | 829 | #if 0 /* debug */ |
803 | //snd_printk("dma_addr=%x, dma_area=%p, table_base=%p\n",runtime->dma_addr, runtime->dma_area, table_base); | 830 | snd_printk(KERN_DEBUG |
804 | //snd_printk("dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",emu->buffer.addr, emu->buffer.area, emu->buffer.bytes); | 831 | "prepare:channel_number=%d, rate=%d, format=0x%x, " |
832 | "channels=%d, buffer_size=%ld, period_size=%ld, " | ||
833 | "periods=%u, frames_to_bytes=%d\n", | ||
834 | channel, runtime->rate, runtime->format, | ||
835 | runtime->channels, runtime->buffer_size, | ||
836 | runtime->period_size, runtime->periods, | ||
837 | frames_to_bytes(runtime, 1)); | ||
838 | snd_printk(KERN_DEBUG "dma_addr=%x, dma_area=%p, table_base=%p\n", | ||
839 | runtime->dma_addr, runtime->dma_area, table_base); | ||
840 | snd_printk(KERN_DEBUG "dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n", | ||
841 | emu->buffer.addr, emu->buffer.area, emu->buffer.bytes); | ||
842 | #endif /* debug */ | ||
805 | /* reg71 controls ADC rate. */ | 843 | /* reg71 controls ADC rate. */ |
806 | switch (runtime->rate) { | 844 | switch (runtime->rate) { |
807 | case 44100: | 845 | case 44100: |
@@ -846,7 +884,14 @@ static int snd_ca0106_pcm_prepare_capture(struct snd_pcm_substream *substream) | |||
846 | } | 884 | } |
847 | 885 | ||
848 | 886 | ||
849 | //printk("prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, frames_to_bytes(runtime, 1)); | 887 | /* |
888 | printk(KERN_DEBUG | ||
889 | "prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, " | ||
890 | "buffer_size=%ld, period_size=%ld, frames_to_bytes=%d\n", | ||
891 | channel, runtime->rate, runtime->format, runtime->channels, | ||
892 | runtime->buffer_size, runtime->period_size, | ||
893 | frames_to_bytes(runtime, 1)); | ||
894 | */ | ||
850 | snd_ca0106_ptr_write(emu, 0x13, channel, 0); | 895 | snd_ca0106_ptr_write(emu, 0x13, channel, 0); |
851 | snd_ca0106_ptr_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr); | 896 | snd_ca0106_ptr_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr); |
852 | snd_ca0106_ptr_write(emu, CAPTURE_BUFFER_SIZE, channel, frames_to_bytes(runtime, runtime->buffer_size)<<16); // buffer size in bytes | 897 | snd_ca0106_ptr_write(emu, CAPTURE_BUFFER_SIZE, channel, frames_to_bytes(runtime, runtime->buffer_size)<<16); // buffer size in bytes |
@@ -888,13 +933,13 @@ static int snd_ca0106_pcm_trigger_playback(struct snd_pcm_substream *substream, | |||
888 | runtime = s->runtime; | 933 | runtime = s->runtime; |
889 | epcm = runtime->private_data; | 934 | epcm = runtime->private_data; |
890 | channel = epcm->channel_id; | 935 | channel = epcm->channel_id; |
891 | /* snd_printk("channel=%d\n",channel); */ | 936 | /* snd_printk(KERN_DEBUG "channel=%d\n", channel); */ |
892 | epcm->running = running; | 937 | epcm->running = running; |
893 | basic |= (0x1 << channel); | 938 | basic |= (0x1 << channel); |
894 | extended |= (0x10 << channel); | 939 | extended |= (0x10 << channel); |
895 | snd_pcm_trigger_done(s, substream); | 940 | snd_pcm_trigger_done(s, substream); |
896 | } | 941 | } |
897 | /* snd_printk("basic=0x%x, extended=0x%x\n",basic, extended); */ | 942 | /* snd_printk(KERN_DEBUG "basic=0x%x, extended=0x%x\n",basic, extended); */ |
898 | 943 | ||
899 | switch (cmd) { | 944 | switch (cmd) { |
900 | case SNDRV_PCM_TRIGGER_START: | 945 | case SNDRV_PCM_TRIGGER_START: |
@@ -972,8 +1017,13 @@ snd_ca0106_pcm_pointer_playback(struct snd_pcm_substream *substream) | |||
972 | ptr=ptr2; | 1017 | ptr=ptr2; |
973 | if (ptr >= runtime->buffer_size) | 1018 | if (ptr >= runtime->buffer_size) |
974 | ptr -= runtime->buffer_size; | 1019 | ptr -= runtime->buffer_size; |
975 | //printk("ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n", ptr1, ptr2, ptr, (int)runtime->buffer_size, (int)runtime->period_size, (int)runtime->frame_bits, (int)runtime->rate); | 1020 | /* |
976 | 1021 | printk(KERN_DEBUG "ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, " | |
1022 | "buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n", | ||
1023 | ptr1, ptr2, ptr, (int)runtime->buffer_size, | ||
1024 | (int)runtime->period_size, (int)runtime->frame_bits, | ||
1025 | (int)runtime->rate); | ||
1026 | */ | ||
977 | return ptr; | 1027 | return ptr; |
978 | } | 1028 | } |
979 | 1029 | ||
@@ -995,8 +1045,13 @@ snd_ca0106_pcm_pointer_capture(struct snd_pcm_substream *substream) | |||
995 | ptr=ptr2; | 1045 | ptr=ptr2; |
996 | if (ptr >= runtime->buffer_size) | 1046 | if (ptr >= runtime->buffer_size) |
997 | ptr -= runtime->buffer_size; | 1047 | ptr -= runtime->buffer_size; |
998 | //printk("ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n", ptr1, ptr2, ptr, (int)runtime->buffer_size, (int)runtime->period_size, (int)runtime->frame_bits, (int)runtime->rate); | 1048 | /* |
999 | 1049 | printk(KERN_DEBUG "ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, " | |
1050 | "buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n", | ||
1051 | ptr1, ptr2, ptr, (int)runtime->buffer_size, | ||
1052 | (int)runtime->period_size, (int)runtime->frame_bits, | ||
1053 | (int)runtime->rate); | ||
1054 | */ | ||
1000 | return ptr; | 1055 | return ptr; |
1001 | } | 1056 | } |
1002 | 1057 | ||
@@ -1181,8 +1236,12 @@ static irqreturn_t snd_ca0106_interrupt(int irq, void *dev_id) | |||
1181 | return IRQ_NONE; | 1236 | return IRQ_NONE; |
1182 | 1237 | ||
1183 | stat76 = snd_ca0106_ptr_read(chip, EXTENDED_INT, 0); | 1238 | stat76 = snd_ca0106_ptr_read(chip, EXTENDED_INT, 0); |
1184 | //snd_printk("interrupt status = 0x%08x, stat76=0x%08x\n", status, stat76); | 1239 | /* |
1185 | //snd_printk("ptr=0x%08x\n",snd_ca0106_ptr_read(chip, PLAYBACK_POINTER, 0)); | 1240 | snd_printk(KERN_DEBUG "interrupt status = 0x%08x, stat76=0x%08x\n", |
1241 | status, stat76); | ||
1242 | snd_printk(KERN_DEBUG "ptr=0x%08x\n", | ||
1243 | snd_ca0106_ptr_read(chip, PLAYBACK_POINTER, 0)); | ||
1244 | */ | ||
1186 | mask = 0x11; /* 0x1 for one half, 0x10 for the other half period. */ | 1245 | mask = 0x11; /* 0x1 for one half, 0x10 for the other half period. */ |
1187 | for(i = 0; i < 4; i++) { | 1246 | for(i = 0; i < 4; i++) { |
1188 | pchannel = &(chip->playback_channels[i]); | 1247 | pchannel = &(chip->playback_channels[i]); |
@@ -1470,7 +1529,7 @@ static void ca0106_init_chip(struct snd_ca0106 *chip, int resume) | |||
1470 | int size, n; | 1529 | int size, n; |
1471 | 1530 | ||
1472 | size = ARRAY_SIZE(i2c_adc_init); | 1531 | size = ARRAY_SIZE(i2c_adc_init); |
1473 | /* snd_printk("I2C:array size=0x%x\n", size); */ | 1532 | /* snd_printk(KERN_DEBUG "I2C:array size=0x%x\n", size); */ |
1474 | for (n = 0; n < size; n++) | 1533 | for (n = 0; n < size; n++) |
1475 | snd_ca0106_i2c_write(chip, i2c_adc_init[n][0], | 1534 | snd_ca0106_i2c_write(chip, i2c_adc_init[n][0], |
1476 | i2c_adc_init[n][1]); | 1535 | i2c_adc_init[n][1]); |
@@ -1707,9 +1766,9 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci, | |||
1707 | return -ENOENT; | 1766 | return -ENOENT; |
1708 | } | 1767 | } |
1709 | 1768 | ||
1710 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 1769 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); |
1711 | if (card == NULL) | 1770 | if (err < 0) |
1712 | return -ENOMEM; | 1771 | return err; |
1713 | 1772 | ||
1714 | err = snd_ca0106_create(dev, card, pci, &chip); | 1773 | err = snd_ca0106_create(dev, card, pci, &chip); |
1715 | if (err < 0) | 1774 | if (err < 0) |
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index 1a74ca62c314..c7899c32aba1 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c | |||
@@ -3272,9 +3272,9 @@ static int __devinit snd_cmipci_probe(struct pci_dev *pci, | |||
3272 | return -ENOENT; | 3272 | return -ENOENT; |
3273 | } | 3273 | } |
3274 | 3274 | ||
3275 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 3275 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); |
3276 | if (card == NULL) | 3276 | if (err < 0) |
3277 | return -ENOMEM; | 3277 | return err; |
3278 | 3278 | ||
3279 | switch (pci->device) { | 3279 | switch (pci->device) { |
3280 | case PCI_DEVICE_ID_CMEDIA_CM8738: | 3280 | case PCI_DEVICE_ID_CMEDIA_CM8738: |
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index 192e7842e181..f6286f84a221 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c | |||
@@ -834,7 +834,11 @@ static snd_pcm_uframes_t snd_cs4281_pointer(struct snd_pcm_substream *substream) | |||
834 | struct cs4281_dma *dma = runtime->private_data; | 834 | struct cs4281_dma *dma = runtime->private_data; |
835 | struct cs4281 *chip = snd_pcm_substream_chip(substream); | 835 | struct cs4281 *chip = snd_pcm_substream_chip(substream); |
836 | 836 | ||
837 | // printk("DCC = 0x%x, buffer_size = 0x%x, jiffies = %li\n", snd_cs4281_peekBA0(chip, dma->regDCC), runtime->buffer_size, jiffies); | 837 | /* |
838 | printk(KERN_DEBUG "DCC = 0x%x, buffer_size = 0x%x, jiffies = %li\n", | ||
839 | snd_cs4281_peekBA0(chip, dma->regDCC), runtime->buffer_size, | ||
840 | jiffies); | ||
841 | */ | ||
838 | return runtime->buffer_size - | 842 | return runtime->buffer_size - |
839 | snd_cs4281_peekBA0(chip, dma->regDCC) - 1; | 843 | snd_cs4281_peekBA0(chip, dma->regDCC) - 1; |
840 | } | 844 | } |
@@ -1925,9 +1929,9 @@ static int __devinit snd_cs4281_probe(struct pci_dev *pci, | |||
1925 | return -ENOENT; | 1929 | return -ENOENT; |
1926 | } | 1930 | } |
1927 | 1931 | ||
1928 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 1932 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); |
1929 | if (card == NULL) | 1933 | if (err < 0) |
1930 | return -ENOMEM; | 1934 | return err; |
1931 | 1935 | ||
1932 | if ((err = snd_cs4281_create(card, pci, &chip, dual_codec[dev])) < 0) { | 1936 | if ((err = snd_cs4281_create(card, pci, &chip, dual_codec[dev])) < 0) { |
1933 | snd_card_free(card); | 1937 | snd_card_free(card); |
diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c index e876b3263e46..c9b3e3d48cbc 100644 --- a/sound/pci/cs46xx/cs46xx.c +++ b/sound/pci/cs46xx/cs46xx.c | |||
@@ -88,9 +88,9 @@ static int __devinit snd_card_cs46xx_probe(struct pci_dev *pci, | |||
88 | return -ENOENT; | 88 | return -ENOENT; |
89 | } | 89 | } |
90 | 90 | ||
91 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 91 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); |
92 | if (card == NULL) | 92 | if (err < 0) |
93 | return -ENOMEM; | 93 | return err; |
94 | if ((err = snd_cs46xx_create(card, pci, | 94 | if ((err = snd_cs46xx_create(card, pci, |
95 | external_amp[dev], thinkpad[dev], | 95 | external_amp[dev], thinkpad[dev], |
96 | &chip)) < 0) { | 96 | &chip)) < 0) { |
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index 8ab07aa63652..1be96ead4244 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c | |||
@@ -194,7 +194,7 @@ static unsigned short snd_cs46xx_codec_read(struct snd_cs46xx *chip, | |||
194 | * ACSDA = Status Data Register = 474h | 194 | * ACSDA = Status Data Register = 474h |
195 | */ | 195 | */ |
196 | #if 0 | 196 | #if 0 |
197 | printk("e) reg = 0x%x, val = 0x%x, BA0_ACCAD = 0x%x\n", reg, | 197 | printk(KERN_DEBUG "e) reg = 0x%x, val = 0x%x, BA0_ACCAD = 0x%x\n", reg, |
198 | snd_cs46xx_peekBA0(chip, BA0_ACSDA), | 198 | snd_cs46xx_peekBA0(chip, BA0_ACSDA), |
199 | snd_cs46xx_peekBA0(chip, BA0_ACCAD)); | 199 | snd_cs46xx_peekBA0(chip, BA0_ACCAD)); |
200 | #endif | 200 | #endif |
@@ -428,8 +428,8 @@ static int cs46xx_wait_for_fifo(struct snd_cs46xx * chip,int retry_timeout) | |||
428 | } | 428 | } |
429 | 429 | ||
430 | if(status & SERBST_WBSY) { | 430 | if(status & SERBST_WBSY) { |
431 | snd_printk( KERN_ERR "cs46xx: failure waiting for FIFO command to complete\n"); | 431 | snd_printk(KERN_ERR "cs46xx: failure waiting for " |
432 | 432 | "FIFO command to complete\n"); | |
433 | return -EINVAL; | 433 | return -EINVAL; |
434 | } | 434 | } |
435 | 435 | ||
diff --git a/sound/pci/cs46xx/cs46xx_lib.h b/sound/pci/cs46xx/cs46xx_lib.h index 018a7de56017..4eb55aa33612 100644 --- a/sound/pci/cs46xx/cs46xx_lib.h +++ b/sound/pci/cs46xx/cs46xx_lib.h | |||
@@ -62,7 +62,11 @@ static inline void snd_cs46xx_poke(struct snd_cs46xx *chip, unsigned long reg, u | |||
62 | unsigned int bank = reg >> 16; | 62 | unsigned int bank = reg >> 16; |
63 | unsigned int offset = reg & 0xffff; | 63 | unsigned int offset = reg & 0xffff; |
64 | 64 | ||
65 | /*if (bank == 0) printk("snd_cs46xx_poke: %04X - %08X\n",reg >> 2,val); */ | 65 | /* |
66 | if (bank == 0) | ||
67 | printk(KERN_DEBUG "snd_cs46xx_poke: %04X - %08X\n", | ||
68 | reg >> 2,val); | ||
69 | */ | ||
66 | writel(val, chip->region.idx[bank+1].remap_addr + offset); | 70 | writel(val, chip->region.idx[bank+1].remap_addr + offset); |
67 | } | 71 | } |
68 | 72 | ||
diff --git a/sound/pci/cs5530.c b/sound/pci/cs5530.c index 6dea5b5cc774..dc464321d0f3 100644 --- a/sound/pci/cs5530.c +++ b/sound/pci/cs5530.c | |||
@@ -258,10 +258,10 @@ static int __devinit snd_cs5530_probe(struct pci_dev *pci, | |||
258 | return -ENOENT; | 258 | return -ENOENT; |
259 | } | 259 | } |
260 | 260 | ||
261 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 261 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); |
262 | 262 | ||
263 | if (card == NULL) | 263 | if (err < 0) |
264 | return -ENOMEM; | 264 | return err; |
265 | 265 | ||
266 | err = snd_cs5530_create(card, pci, &chip); | 266 | err = snd_cs5530_create(card, pci, &chip); |
267 | if (err < 0) { | 267 | if (err < 0) { |
diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c index 826e6dec2e97..c89ed1f5bc2b 100644 --- a/sound/pci/cs5535audio/cs5535audio.c +++ b/sound/pci/cs5535audio/cs5535audio.c | |||
@@ -312,7 +312,7 @@ static int __devinit snd_cs5535audio_create(struct snd_card *card, | |||
312 | 312 | ||
313 | if (request_irq(pci->irq, snd_cs5535audio_interrupt, | 313 | if (request_irq(pci->irq, snd_cs5535audio_interrupt, |
314 | IRQF_SHARED, "CS5535 Audio", cs5535au)) { | 314 | IRQF_SHARED, "CS5535 Audio", cs5535au)) { |
315 | snd_printk("unable to grab IRQ %d\n", pci->irq); | 315 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); |
316 | err = -EBUSY; | 316 | err = -EBUSY; |
317 | goto sndfail; | 317 | goto sndfail; |
318 | } | 318 | } |
@@ -353,9 +353,9 @@ static int __devinit snd_cs5535audio_probe(struct pci_dev *pci, | |||
353 | return -ENOENT; | 353 | return -ENOENT; |
354 | } | 354 | } |
355 | 355 | ||
356 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 356 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); |
357 | if (card == NULL) | 357 | if (err < 0) |
358 | return -ENOMEM; | 358 | return err; |
359 | 359 | ||
360 | if ((err = snd_cs5535audio_create(card, pci, &cs5535au)) < 0) | 360 | if ((err = snd_cs5535audio_create(card, pci, &cs5535au)) < 0) |
361 | goto probefail_out; | 361 | goto probefail_out; |
diff --git a/sound/pci/echoaudio/Makefile b/sound/pci/echoaudio/Makefile index 7b576aeb3f8d..1361de77e0cd 100644 --- a/sound/pci/echoaudio/Makefile +++ b/sound/pci/echoaudio/Makefile | |||
@@ -15,6 +15,8 @@ snd-echo3g-objs := echo3g.o | |||
15 | snd-indigo-objs := indigo.o | 15 | snd-indigo-objs := indigo.o |
16 | snd-indigoio-objs := indigoio.o | 16 | snd-indigoio-objs := indigoio.o |
17 | snd-indigodj-objs := indigodj.o | 17 | snd-indigodj-objs := indigodj.o |
18 | snd-indigoiox-objs := indigoiox.o | ||
19 | snd-indigodjx-objs := indigodjx.o | ||
18 | 20 | ||
19 | obj-$(CONFIG_SND_DARLA20) += snd-darla20.o | 21 | obj-$(CONFIG_SND_DARLA20) += snd-darla20.o |
20 | obj-$(CONFIG_SND_GINA20) += snd-gina20.o | 22 | obj-$(CONFIG_SND_GINA20) += snd-gina20.o |
@@ -28,3 +30,5 @@ obj-$(CONFIG_SND_ECHO3G) += snd-echo3g.o | |||
28 | obj-$(CONFIG_SND_INDIGO) += snd-indigo.o | 30 | obj-$(CONFIG_SND_INDIGO) += snd-indigo.o |
29 | obj-$(CONFIG_SND_INDIGOIO) += snd-indigoio.o | 31 | obj-$(CONFIG_SND_INDIGOIO) += snd-indigoio.o |
30 | obj-$(CONFIG_SND_INDIGODJ) += snd-indigodj.o | 32 | obj-$(CONFIG_SND_INDIGODJ) += snd-indigodj.o |
33 | obj-$(CONFIG_SND_INDIGOIOX) += snd-indigoiox.o | ||
34 | obj-$(CONFIG_SND_INDIGODJX) += snd-indigodjx.o | ||
diff --git a/sound/pci/echoaudio/echo3g_dsp.c b/sound/pci/echoaudio/echo3g_dsp.c index 417e25add82b..57967e580571 100644 --- a/sound/pci/echoaudio/echo3g_dsp.c +++ b/sound/pci/echoaudio/echo3g_dsp.c | |||
@@ -56,7 +56,7 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) | |||
56 | } | 56 | } |
57 | 57 | ||
58 | chip->comm_page->e3g_frq_register = | 58 | chip->comm_page->e3g_frq_register = |
59 | __constant_cpu_to_le32((E3G_MAGIC_NUMBER / 48000) - 2); | 59 | cpu_to_le32((E3G_MAGIC_NUMBER / 48000) - 2); |
60 | chip->device_id = device_id; | 60 | chip->device_id = device_id; |
61 | chip->subdevice_id = subdevice_id; | 61 | chip->subdevice_id = subdevice_id; |
62 | chip->bad_board = TRUE; | 62 | chip->bad_board = TRUE; |
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c index 8dbc5c4ba421..da2065cd2c0d 100644 --- a/sound/pci/echoaudio/echoaudio.c +++ b/sound/pci/echoaudio/echoaudio.c | |||
@@ -950,6 +950,8 @@ static int __devinit snd_echo_new_pcm(struct echoaudio *chip) | |||
950 | Control interface | 950 | Control interface |
951 | ******************************************************************************/ | 951 | ******************************************************************************/ |
952 | 952 | ||
953 | #ifndef ECHOCARD_HAS_VMIXER | ||
954 | |||
953 | /******************* PCM output volume *******************/ | 955 | /******************* PCM output volume *******************/ |
954 | static int snd_echo_output_gain_info(struct snd_kcontrol *kcontrol, | 956 | static int snd_echo_output_gain_info(struct snd_kcontrol *kcontrol, |
955 | struct snd_ctl_elem_info *uinfo) | 957 | struct snd_ctl_elem_info *uinfo) |
@@ -1001,18 +1003,6 @@ static int snd_echo_output_gain_put(struct snd_kcontrol *kcontrol, | |||
1001 | return changed; | 1003 | return changed; |
1002 | } | 1004 | } |
1003 | 1005 | ||
1004 | #ifdef ECHOCARD_HAS_VMIXER | ||
1005 | /* On Vmixer cards this one controls the line-out volume */ | ||
1006 | static struct snd_kcontrol_new snd_echo_line_output_gain __devinitdata = { | ||
1007 | .name = "Line Playback Volume", | ||
1008 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1009 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, | ||
1010 | .info = snd_echo_output_gain_info, | ||
1011 | .get = snd_echo_output_gain_get, | ||
1012 | .put = snd_echo_output_gain_put, | ||
1013 | .tlv = {.p = db_scale_output_gain}, | ||
1014 | }; | ||
1015 | #else | ||
1016 | static struct snd_kcontrol_new snd_echo_pcm_output_gain __devinitdata = { | 1006 | static struct snd_kcontrol_new snd_echo_pcm_output_gain __devinitdata = { |
1017 | .name = "PCM Playback Volume", | 1007 | .name = "PCM Playback Volume", |
1018 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1008 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -1022,6 +1012,7 @@ static struct snd_kcontrol_new snd_echo_pcm_output_gain __devinitdata = { | |||
1022 | .put = snd_echo_output_gain_put, | 1012 | .put = snd_echo_output_gain_put, |
1023 | .tlv = {.p = db_scale_output_gain}, | 1013 | .tlv = {.p = db_scale_output_gain}, |
1024 | }; | 1014 | }; |
1015 | |||
1025 | #endif | 1016 | #endif |
1026 | 1017 | ||
1027 | 1018 | ||
@@ -1997,9 +1988,9 @@ static int __devinit snd_echo_probe(struct pci_dev *pci, | |||
1997 | 1988 | ||
1998 | DE_INIT(("Echoaudio driver starting...\n")); | 1989 | DE_INIT(("Echoaudio driver starting...\n")); |
1999 | i = 0; | 1990 | i = 0; |
2000 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 1991 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); |
2001 | if (card == NULL) | 1992 | if (err < 0) |
2002 | return -ENOMEM; | 1993 | return err; |
2003 | 1994 | ||
2004 | snd_card_set_dev(card, &pci->dev); | 1995 | snd_card_set_dev(card, &pci->dev); |
2005 | 1996 | ||
@@ -2037,8 +2028,6 @@ static int __devinit snd_echo_probe(struct pci_dev *pci, | |||
2037 | 2028 | ||
2038 | #ifdef ECHOCARD_HAS_VMIXER | 2029 | #ifdef ECHOCARD_HAS_VMIXER |
2039 | snd_echo_vmixer.count = num_pipes_out(chip) * num_busses_out(chip); | 2030 | snd_echo_vmixer.count = num_pipes_out(chip) * num_busses_out(chip); |
2040 | if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_line_output_gain, chip))) < 0) | ||
2041 | goto ctl_error; | ||
2042 | if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_vmixer, chip))) < 0) | 2031 | if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_vmixer, chip))) < 0) |
2043 | goto ctl_error; | 2032 | goto ctl_error; |
2044 | #else | 2033 | #else |
diff --git a/sound/pci/echoaudio/echoaudio.h b/sound/pci/echoaudio/echoaudio.h index 1c88e051abf2..f9490ae36c2e 100644 --- a/sound/pci/echoaudio/echoaudio.h +++ b/sound/pci/echoaudio/echoaudio.h | |||
@@ -189,6 +189,9 @@ | |||
189 | #define INDIGO 0x0090 | 189 | #define INDIGO 0x0090 |
190 | #define INDIGO_IO 0x00a0 | 190 | #define INDIGO_IO 0x00a0 |
191 | #define INDIGO_DJ 0x00b0 | 191 | #define INDIGO_DJ 0x00b0 |
192 | #define DC8 0x00c0 | ||
193 | #define INDIGO_IOX 0x00d0 | ||
194 | #define INDIGO_DJX 0x00e0 | ||
192 | #define ECHO3G 0x0100 | 195 | #define ECHO3G 0x0100 |
193 | 196 | ||
194 | 197 | ||
diff --git a/sound/pci/echoaudio/echoaudio_3g.c b/sound/pci/echoaudio/echoaudio_3g.c index c3736bbd819e..e32a74897921 100644 --- a/sound/pci/echoaudio/echoaudio_3g.c +++ b/sound/pci/echoaudio/echoaudio_3g.c | |||
@@ -40,8 +40,7 @@ static int check_asic_status(struct echoaudio *chip) | |||
40 | if (wait_handshake(chip)) | 40 | if (wait_handshake(chip)) |
41 | return -EIO; | 41 | return -EIO; |
42 | 42 | ||
43 | chip->comm_page->ext_box_status = | 43 | chip->comm_page->ext_box_status = cpu_to_le32(E3G_ASIC_NOT_LOADED); |
44 | __constant_cpu_to_le32(E3G_ASIC_NOT_LOADED); | ||
45 | chip->asic_loaded = FALSE; | 44 | chip->asic_loaded = FALSE; |
46 | clear_handshake(chip); | 45 | clear_handshake(chip); |
47 | send_vector(chip, DSP_VC_TEST_ASIC); | 46 | send_vector(chip, DSP_VC_TEST_ASIC); |
diff --git a/sound/pci/echoaudio/echoaudio_dsp.c b/sound/pci/echoaudio/echoaudio_dsp.c index be0e18192de3..4df51ef5e095 100644 --- a/sound/pci/echoaudio/echoaudio_dsp.c +++ b/sound/pci/echoaudio/echoaudio_dsp.c | |||
@@ -926,11 +926,11 @@ static int init_dsp_comm_page(struct echoaudio *chip) | |||
926 | 926 | ||
927 | /* Init the comm page */ | 927 | /* Init the comm page */ |
928 | chip->comm_page->comm_size = | 928 | chip->comm_page->comm_size = |
929 | __constant_cpu_to_le32(sizeof(struct comm_page)); | 929 | cpu_to_le32(sizeof(struct comm_page)); |
930 | chip->comm_page->handshake = 0xffffffff; | 930 | chip->comm_page->handshake = 0xffffffff; |
931 | chip->comm_page->midi_out_free_count = | 931 | chip->comm_page->midi_out_free_count = |
932 | __constant_cpu_to_le32(DSP_MIDI_OUT_FIFO_SIZE); | 932 | cpu_to_le32(DSP_MIDI_OUT_FIFO_SIZE); |
933 | chip->comm_page->sample_rate = __constant_cpu_to_le32(44100); | 933 | chip->comm_page->sample_rate = cpu_to_le32(44100); |
934 | chip->sample_rate = 44100; | 934 | chip->sample_rate = 44100; |
935 | 935 | ||
936 | /* Set line levels so we don't blast any inputs on startup */ | 936 | /* Set line levels so we don't blast any inputs on startup */ |
diff --git a/sound/pci/echoaudio/echoaudio_dsp.h b/sound/pci/echoaudio/echoaudio_dsp.h index e352f3ae292c..cb7d75a0a503 100644 --- a/sound/pci/echoaudio/echoaudio_dsp.h +++ b/sound/pci/echoaudio/echoaudio_dsp.h | |||
@@ -576,8 +576,13 @@ SET_LAYLA24_FREQUENCY_REG command. | |||
576 | #define E3G_ASIC_NOT_LOADED 0xffff | 576 | #define E3G_ASIC_NOT_LOADED 0xffff |
577 | #define E3G_BOX_TYPE_MASK 0xf0 | 577 | #define E3G_BOX_TYPE_MASK 0xf0 |
578 | 578 | ||
579 | #define EXT_3GBOX_NC 0x01 | 579 | /* Indigo express control register values */ |
580 | #define EXT_3GBOX_NOT_SET 0x02 | 580 | #define INDIGO_EXPRESS_32000 0x02 |
581 | #define INDIGO_EXPRESS_44100 0x01 | ||
582 | #define INDIGO_EXPRESS_48000 0x00 | ||
583 | #define INDIGO_EXPRESS_DOUBLE_SPEED 0x10 | ||
584 | #define INDIGO_EXPRESS_QUAD_SPEED 0x04 | ||
585 | #define INDIGO_EXPRESS_CLOCK_MASK 0x17 | ||
581 | 586 | ||
582 | 587 | ||
583 | /* | 588 | /* |
diff --git a/sound/pci/echoaudio/gina20_dsp.c b/sound/pci/echoaudio/gina20_dsp.c index db6c952e9d7f..3f1e7475faea 100644 --- a/sound/pci/echoaudio/gina20_dsp.c +++ b/sound/pci/echoaudio/gina20_dsp.c | |||
@@ -208,10 +208,10 @@ static int set_professional_spdif(struct echoaudio *chip, char prof) | |||
208 | DE_ACT(("set_professional_spdif %d\n", prof)); | 208 | DE_ACT(("set_professional_spdif %d\n", prof)); |
209 | if (prof) | 209 | if (prof) |
210 | chip->comm_page->flags |= | 210 | chip->comm_page->flags |= |
211 | __constant_cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF); | 211 | cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF); |
212 | else | 212 | else |
213 | chip->comm_page->flags &= | 213 | chip->comm_page->flags &= |
214 | ~__constant_cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF); | 214 | ~cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF); |
215 | chip->professional_spdif = prof; | 215 | chip->professional_spdif = prof; |
216 | return update_flags(chip); | 216 | return update_flags(chip); |
217 | } | 217 | } |
diff --git a/sound/pci/echoaudio/indigo_dsp.c b/sound/pci/echoaudio/indigo_dsp.c index f05e39f7aad9..0b2cd9c86277 100644 --- a/sound/pci/echoaudio/indigo_dsp.c +++ b/sound/pci/echoaudio/indigo_dsp.c | |||
@@ -63,18 +63,6 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) | |||
63 | if ((err = init_line_levels(chip)) < 0) | 63 | if ((err = init_line_levels(chip)) < 0) |
64 | return err; | 64 | return err; |
65 | 65 | ||
66 | /* Default routing of the virtual channels: all vchannels are routed | ||
67 | to the stereo output */ | ||
68 | set_vmixer_gain(chip, 0, 0, 0); | ||
69 | set_vmixer_gain(chip, 1, 1, 0); | ||
70 | set_vmixer_gain(chip, 0, 2, 0); | ||
71 | set_vmixer_gain(chip, 1, 3, 0); | ||
72 | set_vmixer_gain(chip, 0, 4, 0); | ||
73 | set_vmixer_gain(chip, 1, 5, 0); | ||
74 | set_vmixer_gain(chip, 0, 6, 0); | ||
75 | set_vmixer_gain(chip, 1, 7, 0); | ||
76 | err = update_vmixer_level(chip); | ||
77 | |||
78 | DE_INIT(("init_hw done\n")); | 66 | DE_INIT(("init_hw done\n")); |
79 | return err; | 67 | return err; |
80 | } | 68 | } |
diff --git a/sound/pci/echoaudio/indigo_express_dsp.c b/sound/pci/echoaudio/indigo_express_dsp.c new file mode 100644 index 000000000000..9ab625e15652 --- /dev/null +++ b/sound/pci/echoaudio/indigo_express_dsp.c | |||
@@ -0,0 +1,119 @@ | |||
1 | /************************************************************************ | ||
2 | |||
3 | This file is part of Echo Digital Audio's generic driver library. | ||
4 | Copyright Echo Digital Audio Corporation (c) 1998 - 2005 | ||
5 | All rights reserved | ||
6 | www.echoaudio.com | ||
7 | |||
8 | This library is free software; you can redistribute it and/or | ||
9 | modify it under the terms of the GNU Lesser General Public | ||
10 | License as published by the Free Software Foundation; either | ||
11 | version 2.1 of the License, or (at your option) any later version. | ||
12 | |||
13 | This library is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | Lesser General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU Lesser General Public | ||
19 | License along with this library; if not, write to the Free Software | ||
20 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | |||
22 | ************************************************************************* | ||
23 | |||
24 | Translation from C++ and adaptation for use in ALSA-Driver | ||
25 | were made by Giuliano Pochini <pochini@shiny.it> | ||
26 | |||
27 | *************************************************************************/ | ||
28 | |||
29 | static int set_sample_rate(struct echoaudio *chip, u32 rate) | ||
30 | { | ||
31 | u32 clock, control_reg, old_control_reg; | ||
32 | |||
33 | if (wait_handshake(chip)) | ||
34 | return -EIO; | ||
35 | |||
36 | old_control_reg = le32_to_cpu(chip->comm_page->control_register); | ||
37 | control_reg = old_control_reg & ~INDIGO_EXPRESS_CLOCK_MASK; | ||
38 | |||
39 | switch (rate) { | ||
40 | case 32000: | ||
41 | clock = INDIGO_EXPRESS_32000; | ||
42 | break; | ||
43 | case 44100: | ||
44 | clock = INDIGO_EXPRESS_44100; | ||
45 | break; | ||
46 | case 48000: | ||
47 | clock = INDIGO_EXPRESS_48000; | ||
48 | break; | ||
49 | case 64000: | ||
50 | clock = INDIGO_EXPRESS_32000|INDIGO_EXPRESS_DOUBLE_SPEED; | ||
51 | break; | ||
52 | case 88200: | ||
53 | clock = INDIGO_EXPRESS_44100|INDIGO_EXPRESS_DOUBLE_SPEED; | ||
54 | break; | ||
55 | case 96000: | ||
56 | clock = INDIGO_EXPRESS_48000|INDIGO_EXPRESS_DOUBLE_SPEED; | ||
57 | break; | ||
58 | default: | ||
59 | return -EINVAL; | ||
60 | } | ||
61 | |||
62 | control_reg |= clock; | ||
63 | if (control_reg != old_control_reg) { | ||
64 | chip->comm_page->control_register = cpu_to_le32(control_reg); | ||
65 | chip->sample_rate = rate; | ||
66 | clear_handshake(chip); | ||
67 | return send_vector(chip, DSP_VC_UPDATE_CLOCKS); | ||
68 | } | ||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | |||
73 | |||
74 | /* This function routes the sound from a virtual channel to a real output */ | ||
75 | static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe, | ||
76 | int gain) | ||
77 | { | ||
78 | int index; | ||
79 | |||
80 | if (snd_BUG_ON(pipe >= num_pipes_out(chip) || | ||
81 | output >= num_busses_out(chip))) | ||
82 | return -EINVAL; | ||
83 | |||
84 | if (wait_handshake(chip)) | ||
85 | return -EIO; | ||
86 | |||
87 | chip->vmixer_gain[output][pipe] = gain; | ||
88 | index = output * num_pipes_out(chip) + pipe; | ||
89 | chip->comm_page->vmixer[index] = gain; | ||
90 | |||
91 | DE_ACT(("set_vmixer_gain: pipe %d, out %d = %d\n", pipe, output, gain)); | ||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | |||
96 | |||
97 | /* Tell the DSP to read and update virtual mixer levels in comm page. */ | ||
98 | static int update_vmixer_level(struct echoaudio *chip) | ||
99 | { | ||
100 | if (wait_handshake(chip)) | ||
101 | return -EIO; | ||
102 | clear_handshake(chip); | ||
103 | return send_vector(chip, DSP_VC_SET_VMIXER_GAIN); | ||
104 | } | ||
105 | |||
106 | |||
107 | |||
108 | static u32 detect_input_clocks(const struct echoaudio *chip) | ||
109 | { | ||
110 | return ECHO_CLOCK_BIT_INTERNAL; | ||
111 | } | ||
112 | |||
113 | |||
114 | |||
115 | /* The IndigoIO has no ASIC. Just do nothing */ | ||
116 | static int load_asic(struct echoaudio *chip) | ||
117 | { | ||
118 | return 0; | ||
119 | } | ||
diff --git a/sound/pci/echoaudio/indigodj_dsp.c b/sound/pci/echoaudio/indigodj_dsp.c index 90730a5ecb42..08392916691e 100644 --- a/sound/pci/echoaudio/indigodj_dsp.c +++ b/sound/pci/echoaudio/indigodj_dsp.c | |||
@@ -63,18 +63,6 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) | |||
63 | if ((err = init_line_levels(chip)) < 0) | 63 | if ((err = init_line_levels(chip)) < 0) |
64 | return err; | 64 | return err; |
65 | 65 | ||
66 | /* Default routing of the virtual channels: vchannels 0-3 and | ||
67 | vchannels 4-7 are routed to real channels 0-4 */ | ||
68 | set_vmixer_gain(chip, 0, 0, 0); | ||
69 | set_vmixer_gain(chip, 1, 1, 0); | ||
70 | set_vmixer_gain(chip, 2, 2, 0); | ||
71 | set_vmixer_gain(chip, 3, 3, 0); | ||
72 | set_vmixer_gain(chip, 0, 4, 0); | ||
73 | set_vmixer_gain(chip, 1, 5, 0); | ||
74 | set_vmixer_gain(chip, 2, 6, 0); | ||
75 | set_vmixer_gain(chip, 3, 7, 0); | ||
76 | err = update_vmixer_level(chip); | ||
77 | |||
78 | DE_INIT(("init_hw done\n")); | 66 | DE_INIT(("init_hw done\n")); |
79 | return err; | 67 | return err; |
80 | } | 68 | } |
diff --git a/sound/pci/echoaudio/indigodjx.c b/sound/pci/echoaudio/indigodjx.c new file mode 100644 index 000000000000..3482ef69f491 --- /dev/null +++ b/sound/pci/echoaudio/indigodjx.c | |||
@@ -0,0 +1,107 @@ | |||
1 | /* | ||
2 | * ALSA driver for Echoaudio soundcards. | ||
3 | * Copyright (C) 2009 Giuliano Pochini <pochini@shiny.it> | ||
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; version 2 of the License. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
17 | */ | ||
18 | |||
19 | #define INDIGO_FAMILY | ||
20 | #define ECHOCARD_INDIGO_DJX | ||
21 | #define ECHOCARD_NAME "Indigo DJx" | ||
22 | #define ECHOCARD_HAS_SUPER_INTERLEAVE | ||
23 | #define ECHOCARD_HAS_VMIXER | ||
24 | #define ECHOCARD_HAS_STEREO_BIG_ENDIAN32 | ||
25 | |||
26 | /* Pipe indexes */ | ||
27 | #define PX_ANALOG_OUT 0 /* 8 */ | ||
28 | #define PX_DIGITAL_OUT 8 /* 0 */ | ||
29 | #define PX_ANALOG_IN 8 /* 0 */ | ||
30 | #define PX_DIGITAL_IN 8 /* 0 */ | ||
31 | #define PX_NUM 8 | ||
32 | |||
33 | /* Bus indexes */ | ||
34 | #define BX_ANALOG_OUT 0 /* 4 */ | ||
35 | #define BX_DIGITAL_OUT 4 /* 0 */ | ||
36 | #define BX_ANALOG_IN 4 /* 0 */ | ||
37 | #define BX_DIGITAL_IN 4 /* 0 */ | ||
38 | #define BX_NUM 4 | ||
39 | |||
40 | |||
41 | #include <linux/delay.h> | ||
42 | #include <linux/init.h> | ||
43 | #include <linux/interrupt.h> | ||
44 | #include <linux/pci.h> | ||
45 | #include <linux/slab.h> | ||
46 | #include <linux/moduleparam.h> | ||
47 | #include <linux/firmware.h> | ||
48 | #include <linux/io.h> | ||
49 | #include <sound/core.h> | ||
50 | #include <sound/info.h> | ||
51 | #include <sound/control.h> | ||
52 | #include <sound/tlv.h> | ||
53 | #include <sound/pcm.h> | ||
54 | #include <sound/pcm_params.h> | ||
55 | #include <sound/asoundef.h> | ||
56 | #include <sound/initval.h> | ||
57 | #include <asm/atomic.h> | ||
58 | #include "echoaudio.h" | ||
59 | |||
60 | MODULE_FIRMWARE("ea/loader_dsp.fw"); | ||
61 | MODULE_FIRMWARE("ea/indigo_djx_dsp.fw"); | ||
62 | |||
63 | #define FW_361_LOADER 0 | ||
64 | #define FW_INDIGO_DJX_DSP 1 | ||
65 | |||
66 | static const struct firmware card_fw[] = { | ||
67 | {0, "loader_dsp.fw"}, | ||
68 | {0, "indigo_djx_dsp.fw"} | ||
69 | }; | ||
70 | |||
71 | static struct pci_device_id snd_echo_ids[] = { | ||
72 | {0x1057, 0x3410, 0xECC0, 0x00E0, 0, 0, 0}, /* Indigo DJx*/ | ||
73 | {0,} | ||
74 | }; | ||
75 | |||
76 | static struct snd_pcm_hardware pcm_hardware_skel = { | ||
77 | .info = SNDRV_PCM_INFO_MMAP | | ||
78 | SNDRV_PCM_INFO_INTERLEAVED | | ||
79 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
80 | SNDRV_PCM_INFO_MMAP_VALID | | ||
81 | SNDRV_PCM_INFO_PAUSE | | ||
82 | SNDRV_PCM_INFO_SYNC_START, | ||
83 | .formats = SNDRV_PCM_FMTBIT_U8 | | ||
84 | SNDRV_PCM_FMTBIT_S16_LE | | ||
85 | SNDRV_PCM_FMTBIT_S24_3LE | | ||
86 | SNDRV_PCM_FMTBIT_S32_LE | | ||
87 | SNDRV_PCM_FMTBIT_S32_BE, | ||
88 | .rates = SNDRV_PCM_RATE_32000 | | ||
89 | SNDRV_PCM_RATE_44100 | | ||
90 | SNDRV_PCM_RATE_48000 | | ||
91 | SNDRV_PCM_RATE_88200 | | ||
92 | SNDRV_PCM_RATE_96000, | ||
93 | .rate_min = 32000, | ||
94 | .rate_max = 96000, | ||
95 | .channels_min = 1, | ||
96 | .channels_max = 4, | ||
97 | .buffer_bytes_max = 262144, | ||
98 | .period_bytes_min = 32, | ||
99 | .period_bytes_max = 131072, | ||
100 | .periods_min = 2, | ||
101 | .periods_max = 220, | ||
102 | }; | ||
103 | |||
104 | #include "indigodjx_dsp.c" | ||
105 | #include "indigo_express_dsp.c" | ||
106 | #include "echoaudio_dsp.c" | ||
107 | #include "echoaudio.c" | ||
diff --git a/sound/pci/echoaudio/indigodjx_dsp.c b/sound/pci/echoaudio/indigodjx_dsp.c new file mode 100644 index 000000000000..f591fc2ed960 --- /dev/null +++ b/sound/pci/echoaudio/indigodjx_dsp.c | |||
@@ -0,0 +1,68 @@ | |||
1 | /************************************************************************ | ||
2 | |||
3 | This file is part of Echo Digital Audio's generic driver library. | ||
4 | Copyright Echo Digital Audio Corporation (c) 1998 - 2005 | ||
5 | All rights reserved | ||
6 | www.echoaudio.com | ||
7 | |||
8 | This library is free software; you can redistribute it and/or | ||
9 | modify it under the terms of the GNU Lesser General Public | ||
10 | License as published by the Free Software Foundation; either | ||
11 | version 2.1 of the License, or (at your option) any later version. | ||
12 | |||
13 | This library is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | Lesser General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU Lesser General Public | ||
19 | License along with this library; if not, write to the Free Software | ||
20 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | |||
22 | ************************************************************************* | ||
23 | |||
24 | Translation from C++ and adaptation for use in ALSA-Driver | ||
25 | were made by Giuliano Pochini <pochini@shiny.it> | ||
26 | |||
27 | *************************************************************************/ | ||
28 | |||
29 | static int update_vmixer_level(struct echoaudio *chip); | ||
30 | static int set_vmixer_gain(struct echoaudio *chip, u16 output, | ||
31 | u16 pipe, int gain); | ||
32 | |||
33 | |||
34 | static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) | ||
35 | { | ||
36 | int err; | ||
37 | |||
38 | DE_INIT(("init_hw() - Indigo DJx\n")); | ||
39 | if (snd_BUG_ON((subdevice_id & 0xfff0) != INDIGO_DJX)) | ||
40 | return -ENODEV; | ||
41 | |||
42 | err = init_dsp_comm_page(chip); | ||
43 | if (err < 0) { | ||
44 | DE_INIT(("init_hw - could not initialize DSP comm page\n")); | ||
45 | return err; | ||
46 | } | ||
47 | |||
48 | chip->device_id = device_id; | ||
49 | chip->subdevice_id = subdevice_id; | ||
50 | chip->bad_board = TRUE; | ||
51 | chip->dsp_code_to_load = &card_fw[FW_INDIGO_DJX_DSP]; | ||
52 | /* Since this card has no ASIC, mark it as loaded so everything | ||
53 | works OK */ | ||
54 | chip->asic_loaded = TRUE; | ||
55 | chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL; | ||
56 | |||
57 | err = load_firmware(chip); | ||
58 | if (err < 0) | ||
59 | return err; | ||
60 | chip->bad_board = FALSE; | ||
61 | |||
62 | err = init_line_levels(chip); | ||
63 | if (err < 0) | ||
64 | return err; | ||
65 | |||
66 | DE_INIT(("init_hw done\n")); | ||
67 | return err; | ||
68 | } | ||
diff --git a/sound/pci/echoaudio/indigoio_dsp.c b/sound/pci/echoaudio/indigoio_dsp.c index a7e09ec21079..0604c8a85223 100644 --- a/sound/pci/echoaudio/indigoio_dsp.c +++ b/sound/pci/echoaudio/indigoio_dsp.c | |||
@@ -63,18 +63,6 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) | |||
63 | if ((err = init_line_levels(chip)) < 0) | 63 | if ((err = init_line_levels(chip)) < 0) |
64 | return err; | 64 | return err; |
65 | 65 | ||
66 | /* Default routing of the virtual channels: all vchannels are routed | ||
67 | to the stereo output */ | ||
68 | set_vmixer_gain(chip, 0, 0, 0); | ||
69 | set_vmixer_gain(chip, 1, 1, 0); | ||
70 | set_vmixer_gain(chip, 0, 2, 0); | ||
71 | set_vmixer_gain(chip, 1, 3, 0); | ||
72 | set_vmixer_gain(chip, 0, 4, 0); | ||
73 | set_vmixer_gain(chip, 1, 5, 0); | ||
74 | set_vmixer_gain(chip, 0, 6, 0); | ||
75 | set_vmixer_gain(chip, 1, 7, 0); | ||
76 | err = update_vmixer_level(chip); | ||
77 | |||
78 | DE_INIT(("init_hw done\n")); | 66 | DE_INIT(("init_hw done\n")); |
79 | return err; | 67 | return err; |
80 | } | 68 | } |
diff --git a/sound/pci/echoaudio/indigoiox.c b/sound/pci/echoaudio/indigoiox.c new file mode 100644 index 000000000000..aebee27a40ff --- /dev/null +++ b/sound/pci/echoaudio/indigoiox.c | |||
@@ -0,0 +1,109 @@ | |||
1 | /* | ||
2 | * ALSA driver for Echoaudio soundcards. | ||
3 | * Copyright (C) 2009 Giuliano Pochini <pochini@shiny.it> | ||
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; version 2 of the License. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
17 | */ | ||
18 | |||
19 | #define INDIGO_FAMILY | ||
20 | #define ECHOCARD_INDIGO_IOX | ||
21 | #define ECHOCARD_NAME "Indigo IOx" | ||
22 | #define ECHOCARD_HAS_MONITOR | ||
23 | #define ECHOCARD_HAS_SUPER_INTERLEAVE | ||
24 | #define ECHOCARD_HAS_VMIXER | ||
25 | #define ECHOCARD_HAS_STEREO_BIG_ENDIAN32 | ||
26 | |||
27 | /* Pipe indexes */ | ||
28 | #define PX_ANALOG_OUT 0 /* 8 */ | ||
29 | #define PX_DIGITAL_OUT 8 /* 0 */ | ||
30 | #define PX_ANALOG_IN 8 /* 2 */ | ||
31 | #define PX_DIGITAL_IN 10 /* 0 */ | ||
32 | #define PX_NUM 10 | ||
33 | |||
34 | /* Bus indexes */ | ||
35 | #define BX_ANALOG_OUT 0 /* 2 */ | ||
36 | #define BX_DIGITAL_OUT 2 /* 0 */ | ||
37 | #define BX_ANALOG_IN 2 /* 2 */ | ||
38 | #define BX_DIGITAL_IN 4 /* 0 */ | ||
39 | #define BX_NUM 4 | ||
40 | |||
41 | |||
42 | #include <linux/delay.h> | ||
43 | #include <linux/init.h> | ||
44 | #include <linux/interrupt.h> | ||
45 | #include <linux/pci.h> | ||
46 | #include <linux/slab.h> | ||
47 | #include <linux/moduleparam.h> | ||
48 | #include <linux/firmware.h> | ||
49 | #include <linux/io.h> | ||
50 | #include <sound/core.h> | ||
51 | #include <sound/info.h> | ||
52 | #include <sound/control.h> | ||
53 | #include <sound/tlv.h> | ||
54 | #include <sound/pcm.h> | ||
55 | #include <sound/pcm_params.h> | ||
56 | #include <sound/asoundef.h> | ||
57 | #include <sound/initval.h> | ||
58 | #include <asm/atomic.h> | ||
59 | #include "echoaudio.h" | ||
60 | |||
61 | MODULE_FIRMWARE("ea/loader_dsp.fw"); | ||
62 | MODULE_FIRMWARE("ea/indigo_iox_dsp.fw"); | ||
63 | |||
64 | #define FW_361_LOADER 0 | ||
65 | #define FW_INDIGO_IOX_DSP 1 | ||
66 | |||
67 | static const struct firmware card_fw[] = { | ||
68 | {0, "loader_dsp.fw"}, | ||
69 | {0, "indigo_iox_dsp.fw"} | ||
70 | }; | ||
71 | |||
72 | static struct pci_device_id snd_echo_ids[] = { | ||
73 | {0x1057, 0x3410, 0xECC0, 0x00D0, 0, 0, 0}, /* Indigo IOx */ | ||
74 | {0,} | ||
75 | }; | ||
76 | |||
77 | static struct snd_pcm_hardware pcm_hardware_skel = { | ||
78 | .info = SNDRV_PCM_INFO_MMAP | | ||
79 | SNDRV_PCM_INFO_INTERLEAVED | | ||
80 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
81 | SNDRV_PCM_INFO_MMAP_VALID | | ||
82 | SNDRV_PCM_INFO_PAUSE | | ||
83 | SNDRV_PCM_INFO_SYNC_START, | ||
84 | .formats = SNDRV_PCM_FMTBIT_U8 | | ||
85 | SNDRV_PCM_FMTBIT_S16_LE | | ||
86 | SNDRV_PCM_FMTBIT_S24_3LE | | ||
87 | SNDRV_PCM_FMTBIT_S32_LE | | ||
88 | SNDRV_PCM_FMTBIT_S32_BE, | ||
89 | .rates = SNDRV_PCM_RATE_32000 | | ||
90 | SNDRV_PCM_RATE_44100 | | ||
91 | SNDRV_PCM_RATE_48000 | | ||
92 | SNDRV_PCM_RATE_88200 | | ||
93 | SNDRV_PCM_RATE_96000, | ||
94 | .rate_min = 32000, | ||
95 | .rate_max = 96000, | ||
96 | .channels_min = 1, | ||
97 | .channels_max = 8, | ||
98 | .buffer_bytes_max = 262144, | ||
99 | .period_bytes_min = 32, | ||
100 | .period_bytes_max = 131072, | ||
101 | .periods_min = 2, | ||
102 | .periods_max = 220, | ||
103 | }; | ||
104 | |||
105 | #include "indigoiox_dsp.c" | ||
106 | #include "indigo_express_dsp.c" | ||
107 | #include "echoaudio_dsp.c" | ||
108 | #include "echoaudio.c" | ||
109 | |||
diff --git a/sound/pci/echoaudio/indigoiox_dsp.c b/sound/pci/echoaudio/indigoiox_dsp.c new file mode 100644 index 000000000000..f357521c79e6 --- /dev/null +++ b/sound/pci/echoaudio/indigoiox_dsp.c | |||
@@ -0,0 +1,68 @@ | |||
1 | /************************************************************************ | ||
2 | |||
3 | This file is part of Echo Digital Audio's generic driver library. | ||
4 | Copyright Echo Digital Audio Corporation (c) 1998 - 2005 | ||
5 | All rights reserved | ||
6 | www.echoaudio.com | ||
7 | |||
8 | This library is free software; you can redistribute it and/or | ||
9 | modify it under the terms of the GNU Lesser General Public | ||
10 | License as published by the Free Software Foundation; either | ||
11 | version 2.1 of the License, or (at your option) any later version. | ||
12 | |||
13 | This library is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | Lesser General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU Lesser General Public | ||
19 | License along with this library; if not, write to the Free Software | ||
20 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | |||
22 | ************************************************************************* | ||
23 | |||
24 | Translation from C++ and adaptation for use in ALSA-Driver | ||
25 | were made by Giuliano Pochini <pochini@shiny.it> | ||
26 | |||
27 | *************************************************************************/ | ||
28 | |||
29 | static int update_vmixer_level(struct echoaudio *chip); | ||
30 | static int set_vmixer_gain(struct echoaudio *chip, u16 output, | ||
31 | u16 pipe, int gain); | ||
32 | |||
33 | |||
34 | static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) | ||
35 | { | ||
36 | int err; | ||
37 | |||
38 | DE_INIT(("init_hw() - Indigo IOx\n")); | ||
39 | if (snd_BUG_ON((subdevice_id & 0xfff0) != INDIGO_IOX)) | ||
40 | return -ENODEV; | ||
41 | |||
42 | err = init_dsp_comm_page(chip); | ||
43 | if (err < 0) { | ||
44 | DE_INIT(("init_hw - could not initialize DSP comm page\n")); | ||
45 | return err; | ||
46 | } | ||
47 | |||
48 | chip->device_id = device_id; | ||
49 | chip->subdevice_id = subdevice_id; | ||
50 | chip->bad_board = TRUE; | ||
51 | chip->dsp_code_to_load = &card_fw[FW_INDIGO_IOX_DSP]; | ||
52 | /* Since this card has no ASIC, mark it as loaded so everything | ||
53 | works OK */ | ||
54 | chip->asic_loaded = TRUE; | ||
55 | chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL; | ||
56 | |||
57 | err = load_firmware(chip); | ||
58 | if (err < 0) | ||
59 | return err; | ||
60 | chip->bad_board = FALSE; | ||
61 | |||
62 | err = init_line_levels(chip); | ||
63 | if (err < 0) | ||
64 | return err; | ||
65 | |||
66 | DE_INIT(("init_hw done\n")); | ||
67 | return err; | ||
68 | } | ||
diff --git a/sound/pci/echoaudio/layla20_dsp.c b/sound/pci/echoaudio/layla20_dsp.c index ede75c6ca0fb..83750e9fd7b4 100644 --- a/sound/pci/echoaudio/layla20_dsp.c +++ b/sound/pci/echoaudio/layla20_dsp.c | |||
@@ -284,10 +284,10 @@ static int set_professional_spdif(struct echoaudio *chip, char prof) | |||
284 | DE_ACT(("set_professional_spdif %d\n", prof)); | 284 | DE_ACT(("set_professional_spdif %d\n", prof)); |
285 | if (prof) | 285 | if (prof) |
286 | chip->comm_page->flags |= | 286 | chip->comm_page->flags |= |
287 | __constant_cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF); | 287 | cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF); |
288 | else | 288 | else |
289 | chip->comm_page->flags &= | 289 | chip->comm_page->flags &= |
290 | ~__constant_cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF); | 290 | ~cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF); |
291 | chip->professional_spdif = prof; | 291 | chip->professional_spdif = prof; |
292 | return update_flags(chip); | 292 | return update_flags(chip); |
293 | } | 293 | } |
diff --git a/sound/pci/echoaudio/mia_dsp.c b/sound/pci/echoaudio/mia_dsp.c index 227386602f9b..551405114cbc 100644 --- a/sound/pci/echoaudio/mia_dsp.c +++ b/sound/pci/echoaudio/mia_dsp.c | |||
@@ -69,18 +69,6 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) | |||
69 | if ((err = init_line_levels(chip))) | 69 | if ((err = init_line_levels(chip))) |
70 | return err; | 70 | return err; |
71 | 71 | ||
72 | /* Default routing of the virtual channels: vchannels 0-3 go to analog | ||
73 | outputs and vchannels 4-7 go to S/PDIF outputs */ | ||
74 | set_vmixer_gain(chip, 0, 0, 0); | ||
75 | set_vmixer_gain(chip, 1, 1, 0); | ||
76 | set_vmixer_gain(chip, 0, 2, 0); | ||
77 | set_vmixer_gain(chip, 1, 3, 0); | ||
78 | set_vmixer_gain(chip, 2, 4, 0); | ||
79 | set_vmixer_gain(chip, 3, 5, 0); | ||
80 | set_vmixer_gain(chip, 2, 6, 0); | ||
81 | set_vmixer_gain(chip, 3, 7, 0); | ||
82 | err = update_vmixer_level(chip); | ||
83 | |||
84 | DE_INIT(("init_hw done\n")); | 72 | DE_INIT(("init_hw done\n")); |
85 | return err; | 73 | return err; |
86 | } | 74 | } |
@@ -222,10 +210,10 @@ static int set_professional_spdif(struct echoaudio *chip, char prof) | |||
222 | DE_ACT(("set_professional_spdif %d\n", prof)); | 210 | DE_ACT(("set_professional_spdif %d\n", prof)); |
223 | if (prof) | 211 | if (prof) |
224 | chip->comm_page->flags |= | 212 | chip->comm_page->flags |= |
225 | __constant_cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF); | 213 | cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF); |
226 | else | 214 | else |
227 | chip->comm_page->flags &= | 215 | chip->comm_page->flags &= |
228 | ~__constant_cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF); | 216 | ~cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF); |
229 | chip->professional_spdif = prof; | 217 | chip->professional_spdif = prof; |
230 | return update_flags(chip); | 218 | return update_flags(chip); |
231 | } | 219 | } |
diff --git a/sound/pci/echoaudio/midi.c b/sound/pci/echoaudio/midi.c index 77bf2a83d997..a953d142cb4b 100644 --- a/sound/pci/echoaudio/midi.c +++ b/sound/pci/echoaudio/midi.c | |||
@@ -44,10 +44,10 @@ static int enable_midi_input(struct echoaudio *chip, char enable) | |||
44 | if (enable) { | 44 | if (enable) { |
45 | chip->mtc_state = MIDI_IN_STATE_NORMAL; | 45 | chip->mtc_state = MIDI_IN_STATE_NORMAL; |
46 | chip->comm_page->flags |= | 46 | chip->comm_page->flags |= |
47 | __constant_cpu_to_le32(DSP_FLAG_MIDI_INPUT); | 47 | cpu_to_le32(DSP_FLAG_MIDI_INPUT); |
48 | } else | 48 | } else |
49 | chip->comm_page->flags &= | 49 | chip->comm_page->flags &= |
50 | ~__constant_cpu_to_le32(DSP_FLAG_MIDI_INPUT); | 50 | ~cpu_to_le32(DSP_FLAG_MIDI_INPUT); |
51 | 51 | ||
52 | clear_handshake(chip); | 52 | clear_handshake(chip); |
53 | return send_vector(chip, DSP_VC_UPDATE_FLAGS); | 53 | return send_vector(chip, DSP_VC_UPDATE_FLAGS); |
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c index 8354c1a83312..c7f3b994101c 100644 --- a/sound/pci/emu10k1/emu10k1.c +++ b/sound/pci/emu10k1/emu10k1.c | |||
@@ -114,9 +114,9 @@ static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci, | |||
114 | return -ENOENT; | 114 | return -ENOENT; |
115 | } | 115 | } |
116 | 116 | ||
117 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 117 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); |
118 | if (card == NULL) | 118 | if (err < 0) |
119 | return -ENOMEM; | 119 | return err; |
120 | if (max_buffer_size[dev] < 32) | 120 | if (max_buffer_size[dev] < 32) |
121 | max_buffer_size[dev] = 32; | 121 | max_buffer_size[dev] = 32; |
122 | else if (max_buffer_size[dev] > 1024) | 122 | else if (max_buffer_size[dev] > 1024) |
diff --git a/sound/pci/emu10k1/emu10k1_callback.c b/sound/pci/emu10k1/emu10k1_callback.c index 0e649dcdbf64..7ef949d99a50 100644 --- a/sound/pci/emu10k1/emu10k1_callback.c +++ b/sound/pci/emu10k1/emu10k1_callback.c | |||
@@ -103,7 +103,10 @@ snd_emu10k1_synth_get_voice(struct snd_emu10k1 *hw) | |||
103 | int ch; | 103 | int ch; |
104 | vp = &emu->voices[best[i].voice]; | 104 | vp = &emu->voices[best[i].voice]; |
105 | if ((ch = vp->ch) < 0) { | 105 | if ((ch = vp->ch) < 0) { |
106 | //printk("synth_get_voice: ch < 0 (%d) ??", i); | 106 | /* |
107 | printk(KERN_WARNING | ||
108 | "synth_get_voice: ch < 0 (%d) ??", i); | ||
109 | */ | ||
107 | continue; | 110 | continue; |
108 | } | 111 | } |
109 | vp->emu->num_voices--; | 112 | vp->emu->num_voices--; |
@@ -335,7 +338,7 @@ start_voice(struct snd_emux_voice *vp) | |||
335 | return -EINVAL; | 338 | return -EINVAL; |
336 | emem->map_locked++; | 339 | emem->map_locked++; |
337 | if (snd_emu10k1_memblk_map(hw, emem) < 0) { | 340 | if (snd_emu10k1_memblk_map(hw, emem) < 0) { |
338 | // printk("emu: cannot map!\n"); | 341 | /* printk(KERN_ERR "emu: cannot map!\n"); */ |
339 | return -ENOMEM; | 342 | return -ENOMEM; |
340 | } | 343 | } |
341 | mapped_offset = snd_emu10k1_memblk_offset(emem) >> 1; | 344 | mapped_offset = snd_emu10k1_memblk_offset(emem) >> 1; |
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index 101a1c13a20d..f18bd6207c50 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c | |||
@@ -711,8 +711,7 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu, const char *filena | |||
711 | static int emu1010_firmware_thread(void *data) | 711 | static int emu1010_firmware_thread(void *data) |
712 | { | 712 | { |
713 | struct snd_emu10k1 *emu = data; | 713 | struct snd_emu10k1 *emu = data; |
714 | int tmp, tmp2; | 714 | u32 tmp, tmp2, reg; |
715 | int reg; | ||
716 | int err; | 715 | int err; |
717 | 716 | ||
718 | for (;;) { | 717 | for (;;) { |
@@ -758,7 +757,8 @@ static int emu1010_firmware_thread(void *data) | |||
758 | snd_printk(KERN_INFO "emu1010: Audio Dock Firmware loaded\n"); | 757 | snd_printk(KERN_INFO "emu1010: Audio Dock Firmware loaded\n"); |
759 | snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp); | 758 | snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp); |
760 | snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2); | 759 | snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2); |
761 | snd_printk("Audio Dock ver:%d.%d\n", tmp, tmp2); | 760 | snd_printk(KERN_INFO "Audio Dock ver: %u.%u\n", |
761 | tmp, tmp2); | ||
762 | /* Sync clocking between 1010 and Dock */ | 762 | /* Sync clocking between 1010 and Dock */ |
763 | /* Allow DLL to settle */ | 763 | /* Allow DLL to settle */ |
764 | msleep(10); | 764 | msleep(10); |
@@ -804,8 +804,7 @@ static int emu1010_firmware_thread(void *data) | |||
804 | static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) | 804 | static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) |
805 | { | 805 | { |
806 | unsigned int i; | 806 | unsigned int i; |
807 | int tmp, tmp2; | 807 | u32 tmp, tmp2, reg; |
808 | int reg; | ||
809 | int err; | 808 | int err; |
810 | const char *filename = NULL; | 809 | const char *filename = NULL; |
811 | 810 | ||
@@ -887,7 +886,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) | |||
887 | snd_printk(KERN_INFO "emu1010: Hana Firmware loaded\n"); | 886 | snd_printk(KERN_INFO "emu1010: Hana Firmware loaded\n"); |
888 | snd_emu1010_fpga_read(emu, EMU_HANA_MAJOR_REV, &tmp); | 887 | snd_emu1010_fpga_read(emu, EMU_HANA_MAJOR_REV, &tmp); |
889 | snd_emu1010_fpga_read(emu, EMU_HANA_MINOR_REV, &tmp2); | 888 | snd_emu1010_fpga_read(emu, EMU_HANA_MINOR_REV, &tmp2); |
890 | snd_printk("emu1010: Hana version: %d.%d\n", tmp, tmp2); | 889 | snd_printk(KERN_INFO "emu1010: Hana version: %u.%u\n", tmp, tmp2); |
891 | /* Enable 48Volt power to Audio Dock */ | 890 | /* Enable 48Volt power to Audio Dock */ |
892 | snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, EMU_HANA_DOCK_PWR_ON); | 891 | snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, EMU_HANA_DOCK_PWR_ON); |
893 | 892 | ||
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c index 5ff4dbb62dad..31542adc6b7e 100644 --- a/sound/pci/emu10k1/emu10k1x.c +++ b/sound/pci/emu10k1/emu10k1x.c | |||
@@ -1544,9 +1544,9 @@ static int __devinit snd_emu10k1x_probe(struct pci_dev *pci, | |||
1544 | return -ENOENT; | 1544 | return -ENOENT; |
1545 | } | 1545 | } |
1546 | 1546 | ||
1547 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 1547 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); |
1548 | if (card == NULL) | 1548 | if (err < 0) |
1549 | return -ENOMEM; | 1549 | return err; |
1550 | 1550 | ||
1551 | if ((err = snd_emu10k1x_create(card, pci, &chip)) < 0) { | 1551 | if ((err = snd_emu10k1x_create(card, pci, &chip)) < 0) { |
1552 | snd_card_free(card); | 1552 | snd_card_free(card); |
diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c index 7dba08f0ab8e..191e1cd9997d 100644 --- a/sound/pci/emu10k1/emufx.c +++ b/sound/pci/emu10k1/emufx.c | |||
@@ -1519,7 +1519,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) | |||
1519 | /* A_PUT_STEREO_OUTPUT(A_EXTOUT_FRONT_L, A_EXTOUT_FRONT_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS); */ | 1519 | /* A_PUT_STEREO_OUTPUT(A_EXTOUT_FRONT_L, A_EXTOUT_FRONT_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS); */ |
1520 | if (emu->card_capabilities->emu_model) { | 1520 | if (emu->card_capabilities->emu_model) { |
1521 | /* EMU1010 Outputs from PCM Front, Rear, Center, LFE, Side */ | 1521 | /* EMU1010 Outputs from PCM Front, Rear, Center, LFE, Side */ |
1522 | snd_printk("EMU outputs on\n"); | 1522 | snd_printk(KERN_INFO "EMU outputs on\n"); |
1523 | for (z = 0; z < 8; z++) { | 1523 | for (z = 0; z < 8; z++) { |
1524 | if (emu->card_capabilities->ca0108_chip) { | 1524 | if (emu->card_capabilities->ca0108_chip) { |
1525 | A_OP(icode, &ptr, iACC3, A3_EMU32OUT(z), A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), A_C_00000000, A_C_00000000); | 1525 | A_OP(icode, &ptr, iACC3, A3_EMU32OUT(z), A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), A_C_00000000, A_C_00000000); |
@@ -1567,7 +1567,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) | |||
1567 | 1567 | ||
1568 | if (emu->card_capabilities->emu_model) { | 1568 | if (emu->card_capabilities->emu_model) { |
1569 | if (emu->card_capabilities->ca0108_chip) { | 1569 | if (emu->card_capabilities->ca0108_chip) { |
1570 | snd_printk("EMU2 inputs on\n"); | 1570 | snd_printk(KERN_INFO "EMU2 inputs on\n"); |
1571 | for (z = 0; z < 0x10; z++) { | 1571 | for (z = 0; z < 0x10; z++) { |
1572 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, | 1572 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, |
1573 | bit_shifter16, | 1573 | bit_shifter16, |
@@ -1575,10 +1575,13 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) | |||
1575 | A_FXBUS2(z*2) ); | 1575 | A_FXBUS2(z*2) ); |
1576 | } | 1576 | } |
1577 | } else { | 1577 | } else { |
1578 | snd_printk("EMU inputs on\n"); | 1578 | snd_printk(KERN_INFO "EMU inputs on\n"); |
1579 | /* Capture 16 (originally 8) channels of S32_LE sound */ | 1579 | /* Capture 16 (originally 8) channels of S32_LE sound */ |
1580 | 1580 | ||
1581 | /* printk("emufx.c: gpr=0x%x, tmp=0x%x\n",gpr, tmp); */ | 1581 | /* |
1582 | printk(KERN_DEBUG "emufx.c: gpr=0x%x, tmp=0x%x\n", | ||
1583 | gpr, tmp); | ||
1584 | */ | ||
1582 | /* For the EMU1010: How to get 32bit values from the DSP. High 16bits into L, low 16bits into R. */ | 1585 | /* For the EMU1010: How to get 32bit values from the DSP. High 16bits into L, low 16bits into R. */ |
1583 | /* A_P16VIN(0) is delayed by one sample, | 1586 | /* A_P16VIN(0) is delayed by one sample, |
1584 | * so all other A_P16VIN channels will need to also be delayed | 1587 | * so all other A_P16VIN channels will need to also be delayed |
diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c index cf9276ddad42..78f62fd404c2 100644 --- a/sound/pci/emu10k1/emupcm.c +++ b/sound/pci/emu10k1/emupcm.c | |||
@@ -44,7 +44,7 @@ static void snd_emu10k1_pcm_interrupt(struct snd_emu10k1 *emu, | |||
44 | if (epcm->substream == NULL) | 44 | if (epcm->substream == NULL) |
45 | return; | 45 | return; |
46 | #if 0 | 46 | #if 0 |
47 | printk("IRQ: position = 0x%x, period = 0x%x, size = 0x%x\n", | 47 | printk(KERN_DEBUG "IRQ: position = 0x%x, period = 0x%x, size = 0x%x\n", |
48 | epcm->substream->runtime->hw->pointer(emu, epcm->substream), | 48 | epcm->substream->runtime->hw->pointer(emu, epcm->substream), |
49 | snd_pcm_lib_period_bytes(epcm->substream), | 49 | snd_pcm_lib_period_bytes(epcm->substream), |
50 | snd_pcm_lib_buffer_bytes(epcm->substream)); | 50 | snd_pcm_lib_buffer_bytes(epcm->substream)); |
@@ -146,7 +146,11 @@ static int snd_emu10k1_pcm_channel_alloc(struct snd_emu10k1_pcm * epcm, int voic | |||
146 | 1, | 146 | 1, |
147 | &epcm->extra); | 147 | &epcm->extra); |
148 | if (err < 0) { | 148 | if (err < 0) { |
149 | /* printk("pcm_channel_alloc: failed extra: voices=%d, frame=%d\n", voices, frame); */ | 149 | /* |
150 | printk(KERN_DEBUG "pcm_channel_alloc: " | ||
151 | "failed extra: voices=%d, frame=%d\n", | ||
152 | voices, frame); | ||
153 | */ | ||
150 | for (i = 0; i < voices; i++) { | 154 | for (i = 0; i < voices; i++) { |
151 | snd_emu10k1_voice_free(epcm->emu, epcm->voices[i]); | 155 | snd_emu10k1_voice_free(epcm->emu, epcm->voices[i]); |
152 | epcm->voices[i] = NULL; | 156 | epcm->voices[i] = NULL; |
@@ -737,7 +741,10 @@ static int snd_emu10k1_playback_trigger(struct snd_pcm_substream *substream, | |||
737 | struct snd_emu10k1_pcm_mixer *mix; | 741 | struct snd_emu10k1_pcm_mixer *mix; |
738 | int result = 0; | 742 | int result = 0; |
739 | 743 | ||
740 | /* printk("trigger - emu10k1 = 0x%x, cmd = %i, pointer = %i\n", (int)emu, cmd, substream->ops->pointer(substream)); */ | 744 | /* |
745 | printk(KERN_DEBUG "trigger - emu10k1 = 0x%x, cmd = %i, pointer = %i\n", | ||
746 | (int)emu, cmd, substream->ops->pointer(substream)) | ||
747 | */ | ||
741 | spin_lock(&emu->reg_lock); | 748 | spin_lock(&emu->reg_lock); |
742 | switch (cmd) { | 749 | switch (cmd) { |
743 | case SNDRV_PCM_TRIGGER_START: | 750 | case SNDRV_PCM_TRIGGER_START: |
@@ -786,7 +793,10 @@ static int snd_emu10k1_capture_trigger(struct snd_pcm_substream *substream, | |||
786 | /* hmm this should cause full and half full interrupt to be raised? */ | 793 | /* hmm this should cause full and half full interrupt to be raised? */ |
787 | outl(epcm->capture_ipr, emu->port + IPR); | 794 | outl(epcm->capture_ipr, emu->port + IPR); |
788 | snd_emu10k1_intr_enable(emu, epcm->capture_inte); | 795 | snd_emu10k1_intr_enable(emu, epcm->capture_inte); |
789 | /* printk("adccr = 0x%x, adcbs = 0x%x\n", epcm->adccr, epcm->adcbs); */ | 796 | /* |
797 | printk(KERN_DEBUG "adccr = 0x%x, adcbs = 0x%x\n", | ||
798 | epcm->adccr, epcm->adcbs); | ||
799 | */ | ||
790 | switch (epcm->type) { | 800 | switch (epcm->type) { |
791 | case CAPTURE_AC97ADC: | 801 | case CAPTURE_AC97ADC: |
792 | snd_emu10k1_ptr_write(emu, ADCCR, 0, epcm->capture_cr_val); | 802 | snd_emu10k1_ptr_write(emu, ADCCR, 0, epcm->capture_cr_val); |
@@ -857,7 +867,11 @@ static snd_pcm_uframes_t snd_emu10k1_playback_pointer(struct snd_pcm_substream * | |||
857 | ptr -= runtime->buffer_size; | 867 | ptr -= runtime->buffer_size; |
858 | } | 868 | } |
859 | #endif | 869 | #endif |
860 | /* printk("ptr = 0x%x, buffer_size = 0x%x, period_size = 0x%x\n", ptr, runtime->buffer_size, runtime->period_size); */ | 870 | /* |
871 | printk(KERN_DEBUG | ||
872 | "ptr = 0x%x, buffer_size = 0x%x, period_size = 0x%x\n", | ||
873 | ptr, runtime->buffer_size, runtime->period_size); | ||
874 | */ | ||
861 | return ptr; | 875 | return ptr; |
862 | } | 876 | } |
863 | 877 | ||
@@ -1546,7 +1560,11 @@ static void snd_emu10k1_fx8010_playback_tram_poke1(unsigned short *dst_left, | |||
1546 | unsigned int count, | 1560 | unsigned int count, |
1547 | unsigned int tram_shift) | 1561 | unsigned int tram_shift) |
1548 | { | 1562 | { |
1549 | /* printk("tram_poke1: dst_left = 0x%p, dst_right = 0x%p, src = 0x%p, count = 0x%x\n", dst_left, dst_right, src, count); */ | 1563 | /* |
1564 | printk(KERN_DEBUG "tram_poke1: dst_left = 0x%p, dst_right = 0x%p, " | ||
1565 | "src = 0x%p, count = 0x%x\n", | ||
1566 | dst_left, dst_right, src, count); | ||
1567 | */ | ||
1550 | if ((tram_shift & 1) == 0) { | 1568 | if ((tram_shift & 1) == 0) { |
1551 | while (count--) { | 1569 | while (count--) { |
1552 | *dst_left-- = *src++; | 1570 | *dst_left-- = *src++; |
@@ -1623,7 +1641,12 @@ static int snd_emu10k1_fx8010_playback_prepare(struct snd_pcm_substream *substre | |||
1623 | struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number]; | 1641 | struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number]; |
1624 | unsigned int i; | 1642 | unsigned int i; |
1625 | 1643 | ||
1626 | /* printk("prepare: etram_pages = 0x%p, dma_area = 0x%x, buffer_size = 0x%x (0x%x)\n", emu->fx8010.etram_pages, runtime->dma_area, runtime->buffer_size, runtime->buffer_size << 2); */ | 1644 | /* |
1645 | printk(KERN_DEBUG "prepare: etram_pages = 0x%p, dma_area = 0x%x, " | ||
1646 | "buffer_size = 0x%x (0x%x)\n", | ||
1647 | emu->fx8010.etram_pages, runtime->dma_area, | ||
1648 | runtime->buffer_size, runtime->buffer_size << 2); | ||
1649 | */ | ||
1627 | memset(&pcm->pcm_rec, 0, sizeof(pcm->pcm_rec)); | 1650 | memset(&pcm->pcm_rec, 0, sizeof(pcm->pcm_rec)); |
1628 | pcm->pcm_rec.hw_buffer_size = pcm->buffer_size * 2; /* byte size */ | 1651 | pcm->pcm_rec.hw_buffer_size = pcm->buffer_size * 2; /* byte size */ |
1629 | pcm->pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream); | 1652 | pcm->pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream); |
diff --git a/sound/pci/emu10k1/io.c b/sound/pci/emu10k1/io.c index b5a802bdeb7c..4bfc31d1b281 100644 --- a/sound/pci/emu10k1/io.c +++ b/sound/pci/emu10k1/io.c | |||
@@ -226,7 +226,9 @@ int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu, | |||
226 | break; | 226 | break; |
227 | 227 | ||
228 | if (timeout > 1000) { | 228 | if (timeout > 1000) { |
229 | snd_printk("emu10k1:I2C:timeout status=0x%x\n", status); | 229 | snd_printk(KERN_WARNING |
230 | "emu10k1:I2C:timeout status=0x%x\n", | ||
231 | status); | ||
230 | break; | 232 | break; |
231 | } | 233 | } |
232 | } | 234 | } |
diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c index 749a21b6bd06..e617acaf10e3 100644 --- a/sound/pci/emu10k1/p16v.c +++ b/sound/pci/emu10k1/p16v.c | |||
@@ -168,7 +168,7 @@ static void snd_p16v_pcm_free_substream(struct snd_pcm_runtime *runtime) | |||
168 | struct snd_emu10k1_pcm *epcm = runtime->private_data; | 168 | struct snd_emu10k1_pcm *epcm = runtime->private_data; |
169 | 169 | ||
170 | if (epcm) { | 170 | if (epcm) { |
171 | //snd_printk("epcm free: %p\n", epcm); | 171 | /* snd_printk(KERN_DEBUG "epcm free: %p\n", epcm); */ |
172 | kfree(epcm); | 172 | kfree(epcm); |
173 | } | 173 | } |
174 | } | 174 | } |
@@ -183,14 +183,16 @@ static int snd_p16v_pcm_open_playback_channel(struct snd_pcm_substream *substrea | |||
183 | int err; | 183 | int err; |
184 | 184 | ||
185 | epcm = kzalloc(sizeof(*epcm), GFP_KERNEL); | 185 | epcm = kzalloc(sizeof(*epcm), GFP_KERNEL); |
186 | //snd_printk("epcm kcalloc: %p\n", epcm); | 186 | /* snd_printk(KERN_DEBUG "epcm kcalloc: %p\n", epcm); */ |
187 | 187 | ||
188 | if (epcm == NULL) | 188 | if (epcm == NULL) |
189 | return -ENOMEM; | 189 | return -ENOMEM; |
190 | epcm->emu = emu; | 190 | epcm->emu = emu; |
191 | epcm->substream = substream; | 191 | epcm->substream = substream; |
192 | //snd_printk("epcm device=%d, channel_id=%d\n", substream->pcm->device, channel_id); | 192 | /* |
193 | 193 | snd_printk(KERN_DEBUG "epcm device=%d, channel_id=%d\n", | |
194 | substream->pcm->device, channel_id); | ||
195 | */ | ||
194 | runtime->private_data = epcm; | 196 | runtime->private_data = epcm; |
195 | runtime->private_free = snd_p16v_pcm_free_substream; | 197 | runtime->private_free = snd_p16v_pcm_free_substream; |
196 | 198 | ||
@@ -200,10 +202,15 @@ static int snd_p16v_pcm_open_playback_channel(struct snd_pcm_substream *substrea | |||
200 | channel->number = channel_id; | 202 | channel->number = channel_id; |
201 | 203 | ||
202 | channel->use=1; | 204 | channel->use=1; |
203 | //snd_printk("p16v: open channel_id=%d, channel=%p, use=0x%x\n", channel_id, channel, channel->use); | 205 | #if 0 /* debug */ |
204 | //printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel); | 206 | snd_printk(KERN_DEBUG |
205 | //channel->interrupt = snd_p16v_pcm_channel_interrupt; | 207 | "p16v: open channel_id=%d, channel=%p, use=0x%x\n", |
206 | channel->epcm=epcm; | 208 | channel_id, channel, channel->use); |
209 | printk(KERN_DEBUG "open:channel_id=%d, chip=%p, channel=%p\n", | ||
210 | channel_id, chip, channel); | ||
211 | #endif /* debug */ | ||
212 | /* channel->interrupt = snd_p16v_pcm_channel_interrupt; */ | ||
213 | channel->epcm = epcm; | ||
207 | if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) | 214 | if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) |
208 | return err; | 215 | return err; |
209 | 216 | ||
@@ -224,14 +231,16 @@ static int snd_p16v_pcm_open_capture_channel(struct snd_pcm_substream *substream | |||
224 | int err; | 231 | int err; |
225 | 232 | ||
226 | epcm = kzalloc(sizeof(*epcm), GFP_KERNEL); | 233 | epcm = kzalloc(sizeof(*epcm), GFP_KERNEL); |
227 | //snd_printk("epcm kcalloc: %p\n", epcm); | 234 | /* snd_printk(KERN_DEBUG "epcm kcalloc: %p\n", epcm); */ |
228 | 235 | ||
229 | if (epcm == NULL) | 236 | if (epcm == NULL) |
230 | return -ENOMEM; | 237 | return -ENOMEM; |
231 | epcm->emu = emu; | 238 | epcm->emu = emu; |
232 | epcm->substream = substream; | 239 | epcm->substream = substream; |
233 | //snd_printk("epcm device=%d, channel_id=%d\n", substream->pcm->device, channel_id); | 240 | /* |
234 | 241 | snd_printk(KERN_DEBUG "epcm device=%d, channel_id=%d\n", | |
242 | substream->pcm->device, channel_id); | ||
243 | */ | ||
235 | runtime->private_data = epcm; | 244 | runtime->private_data = epcm; |
236 | runtime->private_free = snd_p16v_pcm_free_substream; | 245 | runtime->private_free = snd_p16v_pcm_free_substream; |
237 | 246 | ||
@@ -241,10 +250,15 @@ static int snd_p16v_pcm_open_capture_channel(struct snd_pcm_substream *substream | |||
241 | channel->number = channel_id; | 250 | channel->number = channel_id; |
242 | 251 | ||
243 | channel->use=1; | 252 | channel->use=1; |
244 | //snd_printk("p16v: open channel_id=%d, channel=%p, use=0x%x\n", channel_id, channel, channel->use); | 253 | #if 0 /* debug */ |
245 | //printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel); | 254 | snd_printk(KERN_DEBUG |
246 | //channel->interrupt = snd_p16v_pcm_channel_interrupt; | 255 | "p16v: open channel_id=%d, channel=%p, use=0x%x\n", |
247 | channel->epcm=epcm; | 256 | channel_id, channel, channel->use); |
257 | printk(KERN_DEBUG "open:channel_id=%d, chip=%p, channel=%p\n", | ||
258 | channel_id, chip, channel); | ||
259 | #endif /* debug */ | ||
260 | /* channel->interrupt = snd_p16v_pcm_channel_interrupt; */ | ||
261 | channel->epcm = epcm; | ||
248 | if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) | 262 | if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) |
249 | return err; | 263 | return err; |
250 | 264 | ||
@@ -334,9 +348,19 @@ static int snd_p16v_pcm_prepare_playback(struct snd_pcm_substream *substream) | |||
334 | int i; | 348 | int i; |
335 | u32 tmp; | 349 | u32 tmp; |
336 | 350 | ||
337 | //snd_printk("prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, periods=%u, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, runtime->periods, frames_to_bytes(runtime, 1)); | 351 | #if 0 /* debug */ |
338 | //snd_printk("dma_addr=%x, dma_area=%p, table_base=%p\n",runtime->dma_addr, runtime->dma_area, table_base); | 352 | snd_printk(KERN_DEBUG "prepare:channel_number=%d, rate=%d, " |
339 | //snd_printk("dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",emu->p16v_buffer.addr, emu->p16v_buffer.area, emu->p16v_buffer.bytes); | 353 | "format=0x%x, channels=%d, buffer_size=%ld, " |
354 | "period_size=%ld, periods=%u, frames_to_bytes=%d\n", | ||
355 | channel, runtime->rate, runtime->format, runtime->channels, | ||
356 | runtime->buffer_size, runtime->period_size, | ||
357 | runtime->periods, frames_to_bytes(runtime, 1)); | ||
358 | snd_printk(KERN_DEBUG "dma_addr=%x, dma_area=%p, table_base=%p\n", | ||
359 | runtime->dma_addr, runtime->dma_area, table_base); | ||
360 | snd_printk(KERN_DEBUG "dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n", | ||
361 | emu->p16v_buffer.addr, emu->p16v_buffer.area, | ||
362 | emu->p16v_buffer.bytes); | ||
363 | #endif /* debug */ | ||
340 | tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel); | 364 | tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel); |
341 | switch (runtime->rate) { | 365 | switch (runtime->rate) { |
342 | case 44100: | 366 | case 44100: |
@@ -379,7 +403,15 @@ static int snd_p16v_pcm_prepare_capture(struct snd_pcm_substream *substream) | |||
379 | struct snd_pcm_runtime *runtime = substream->runtime; | 403 | struct snd_pcm_runtime *runtime = substream->runtime; |
380 | int channel = substream->pcm->device - emu->p16v_device_offset; | 404 | int channel = substream->pcm->device - emu->p16v_device_offset; |
381 | u32 tmp; | 405 | u32 tmp; |
382 | //printk("prepare capture:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, frames_to_bytes(runtime, 1)); | 406 | |
407 | /* | ||
408 | printk(KERN_DEBUG "prepare capture:channel_number=%d, rate=%d, " | ||
409 | "format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, " | ||
410 | "frames_to_bytes=%d\n", | ||
411 | channel, runtime->rate, runtime->format, runtime->channels, | ||
412 | runtime->buffer_size, runtime->period_size, | ||
413 | frames_to_bytes(runtime, 1)); | ||
414 | */ | ||
383 | tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel); | 415 | tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel); |
384 | switch (runtime->rate) { | 416 | switch (runtime->rate) { |
385 | case 44100: | 417 | case 44100: |
@@ -459,13 +491,13 @@ static int snd_p16v_pcm_trigger_playback(struct snd_pcm_substream *substream, | |||
459 | runtime = s->runtime; | 491 | runtime = s->runtime; |
460 | epcm = runtime->private_data; | 492 | epcm = runtime->private_data; |
461 | channel = substream->pcm->device-emu->p16v_device_offset; | 493 | channel = substream->pcm->device-emu->p16v_device_offset; |
462 | //snd_printk("p16v channel=%d\n",channel); | 494 | /* snd_printk(KERN_DEBUG "p16v channel=%d\n", channel); */ |
463 | epcm->running = running; | 495 | epcm->running = running; |
464 | basic |= (0x1<<channel); | 496 | basic |= (0x1<<channel); |
465 | inte |= (INTE2_PLAYBACK_CH_0_LOOP<<channel); | 497 | inte |= (INTE2_PLAYBACK_CH_0_LOOP<<channel); |
466 | snd_pcm_trigger_done(s, substream); | 498 | snd_pcm_trigger_done(s, substream); |
467 | } | 499 | } |
468 | //snd_printk("basic=0x%x, inte=0x%x\n",basic, inte); | 500 | /* snd_printk(KERN_DEBUG "basic=0x%x, inte=0x%x\n", basic, inte); */ |
469 | 501 | ||
470 | switch (cmd) { | 502 | switch (cmd) { |
471 | case SNDRV_PCM_TRIGGER_START: | 503 | case SNDRV_PCM_TRIGGER_START: |
@@ -558,8 +590,13 @@ snd_p16v_pcm_pointer_capture(struct snd_pcm_substream *substream) | |||
558 | ptr -= runtime->buffer_size; | 590 | ptr -= runtime->buffer_size; |
559 | printk(KERN_WARNING "buffer capture limited!\n"); | 591 | printk(KERN_WARNING "buffer capture limited!\n"); |
560 | } | 592 | } |
561 | //printk("ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n", ptr1, ptr2, ptr, (int)runtime->buffer_size, (int)runtime->period_size, (int)runtime->frame_bits, (int)runtime->rate); | 593 | /* |
562 | 594 | printk(KERN_DEBUG "ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, " | |
595 | "buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n", | ||
596 | ptr1, ptr2, ptr, (int)runtime->buffer_size, | ||
597 | (int)runtime->period_size, (int)runtime->frame_bits, | ||
598 | (int)runtime->rate); | ||
599 | */ | ||
563 | return ptr; | 600 | return ptr; |
564 | } | 601 | } |
565 | 602 | ||
@@ -592,7 +629,10 @@ int snd_p16v_free(struct snd_emu10k1 *chip) | |||
592 | // release the data | 629 | // release the data |
593 | if (chip->p16v_buffer.area) { | 630 | if (chip->p16v_buffer.area) { |
594 | snd_dma_free_pages(&chip->p16v_buffer); | 631 | snd_dma_free_pages(&chip->p16v_buffer); |
595 | //snd_printk("period lables free: %p\n", &chip->p16v_buffer); | 632 | /* |
633 | snd_printk(KERN_DEBUG "period lables free: %p\n", | ||
634 | &chip->p16v_buffer); | ||
635 | */ | ||
596 | } | 636 | } |
597 | return 0; | 637 | return 0; |
598 | } | 638 | } |
@@ -604,7 +644,7 @@ int __devinit snd_p16v_pcm(struct snd_emu10k1 *emu, int device, struct snd_pcm * | |||
604 | int err; | 644 | int err; |
605 | int capture=1; | 645 | int capture=1; |
606 | 646 | ||
607 | //snd_printk("snd_p16v_pcm called. device=%d\n", device); | 647 | /* snd_printk("KERN_DEBUG snd_p16v_pcm called. device=%d\n", device); */ |
608 | emu->p16v_device_offset = device; | 648 | emu->p16v_device_offset = device; |
609 | if (rpcm) | 649 | if (rpcm) |
610 | *rpcm = NULL; | 650 | *rpcm = NULL; |
@@ -631,7 +671,10 @@ int __devinit snd_p16v_pcm(struct snd_emu10k1 *emu, int device, struct snd_pcm * | |||
631 | snd_dma_pci_data(emu->pci), | 671 | snd_dma_pci_data(emu->pci), |
632 | ((65536 - 64) * 8), ((65536 - 64) * 8))) < 0) | 672 | ((65536 - 64) * 8), ((65536 - 64) * 8))) < 0) |
633 | return err; | 673 | return err; |
634 | //snd_printk("preallocate playback substream: err=%d\n", err); | 674 | /* |
675 | snd_printk(KERN_DEBUG | ||
676 | "preallocate playback substream: err=%d\n", err); | ||
677 | */ | ||
635 | } | 678 | } |
636 | 679 | ||
637 | for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; | 680 | for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; |
@@ -642,7 +685,10 @@ int __devinit snd_p16v_pcm(struct snd_emu10k1 *emu, int device, struct snd_pcm * | |||
642 | snd_dma_pci_data(emu->pci), | 685 | snd_dma_pci_data(emu->pci), |
643 | 65536 - 64, 65536 - 64)) < 0) | 686 | 65536 - 64, 65536 - 64)) < 0) |
644 | return err; | 687 | return err; |
645 | //snd_printk("preallocate capture substream: err=%d\n", err); | 688 | /* |
689 | snd_printk(KERN_DEBUG | ||
690 | "preallocate capture substream: err=%d\n", err); | ||
691 | */ | ||
646 | } | 692 | } |
647 | 693 | ||
648 | if (rpcm) | 694 | if (rpcm) |
diff --git a/sound/pci/emu10k1/voice.c b/sound/pci/emu10k1/voice.c index d7300a1aa262..20b8da250bd0 100644 --- a/sound/pci/emu10k1/voice.c +++ b/sound/pci/emu10k1/voice.c | |||
@@ -53,7 +53,10 @@ static int voice_alloc(struct snd_emu10k1 *emu, int type, int number, | |||
53 | *rvoice = NULL; | 53 | *rvoice = NULL; |
54 | first_voice = last_voice = 0; | 54 | first_voice = last_voice = 0; |
55 | for (i = emu->next_free_voice, j = 0; j < NUM_G ; i += number, j += number) { | 55 | for (i = emu->next_free_voice, j = 0; j < NUM_G ; i += number, j += number) { |
56 | // printk("i %d j %d next free %d!\n", i, j, emu->next_free_voice); | 56 | /* |
57 | printk(KERN_DEBUG "i %d j %d next free %d!\n", | ||
58 | i, j, emu->next_free_voice); | ||
59 | */ | ||
57 | i %= NUM_G; | 60 | i %= NUM_G; |
58 | 61 | ||
59 | /* stereo voices must be even/odd */ | 62 | /* stereo voices must be even/odd */ |
@@ -71,7 +74,7 @@ static int voice_alloc(struct snd_emu10k1 *emu, int type, int number, | |||
71 | } | 74 | } |
72 | } | 75 | } |
73 | if (!skip) { | 76 | if (!skip) { |
74 | // printk("allocated voice %d\n", i); | 77 | /* printk(KERN_DEBUG "allocated voice %d\n", i); */ |
75 | first_voice = i; | 78 | first_voice = i; |
76 | last_voice = (i + number) % NUM_G; | 79 | last_voice = (i + number) % NUM_G; |
77 | emu->next_free_voice = last_voice; | 80 | emu->next_free_voice = last_voice; |
@@ -84,7 +87,10 @@ static int voice_alloc(struct snd_emu10k1 *emu, int type, int number, | |||
84 | 87 | ||
85 | for (i = 0; i < number; i++) { | 88 | for (i = 0; i < number; i++) { |
86 | voice = &emu->voices[(first_voice + i) % NUM_G]; | 89 | voice = &emu->voices[(first_voice + i) % NUM_G]; |
87 | // printk("voice alloc - %i, %i of %i\n", voice->number, idx-first_voice+1, number); | 90 | /* |
91 | printk(kERN_DEBUG "voice alloc - %i, %i of %i\n", | ||
92 | voice->number, idx-first_voice+1, number); | ||
93 | */ | ||
88 | voice->use = 1; | 94 | voice->use = 1; |
89 | switch (type) { | 95 | switch (type) { |
90 | case EMU10K1_PCM: | 96 | case EMU10K1_PCM: |
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index 9bf95367c882..18f4d1e98c46 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c | |||
@@ -584,7 +584,8 @@ static void snd_es1370_codec_write(struct snd_ak4531 *ak4531, | |||
584 | unsigned long end_time = jiffies + HZ / 10; | 584 | unsigned long end_time = jiffies + HZ / 10; |
585 | 585 | ||
586 | #if 0 | 586 | #if 0 |
587 | printk("CODEC WRITE: reg = 0x%x, val = 0x%x (0x%x), creg = 0x%x\n", | 587 | printk(KERN_DEBUG |
588 | "CODEC WRITE: reg = 0x%x, val = 0x%x (0x%x), creg = 0x%x\n", | ||
588 | reg, val, ES_1370_CODEC_WRITE(reg, val), ES_REG(ensoniq, 1370_CODEC)); | 589 | reg, val, ES_1370_CODEC_WRITE(reg, val), ES_REG(ensoniq, 1370_CODEC)); |
589 | #endif | 590 | #endif |
590 | do { | 591 | do { |
@@ -2409,9 +2410,9 @@ static int __devinit snd_audiopci_probe(struct pci_dev *pci, | |||
2409 | return -ENOENT; | 2410 | return -ENOENT; |
2410 | } | 2411 | } |
2411 | 2412 | ||
2412 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 2413 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); |
2413 | if (card == NULL) | 2414 | if (err < 0) |
2414 | return -ENOMEM; | 2415 | return err; |
2415 | 2416 | ||
2416 | if ((err = snd_ensoniq_create(card, pci, &ensoniq)) < 0) { | 2417 | if ((err = snd_ensoniq_create(card, pci, &ensoniq)) < 0) { |
2417 | snd_card_free(card); | 2418 | snd_card_free(card); |
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index 4cd9a1faaecc..dd63b132fb8e 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c | |||
@@ -1673,18 +1673,22 @@ static irqreturn_t snd_es1938_interrupt(int irq, void *dev_id) | |||
1673 | 1673 | ||
1674 | status = inb(SLIO_REG(chip, IRQCONTROL)); | 1674 | status = inb(SLIO_REG(chip, IRQCONTROL)); |
1675 | #if 0 | 1675 | #if 0 |
1676 | printk("Es1938debug - interrupt status: =0x%x\n", status); | 1676 | printk(KERN_DEBUG "Es1938debug - interrupt status: =0x%x\n", status); |
1677 | #endif | 1677 | #endif |
1678 | 1678 | ||
1679 | /* AUDIO 1 */ | 1679 | /* AUDIO 1 */ |
1680 | if (status & 0x10) { | 1680 | if (status & 0x10) { |
1681 | #if 0 | 1681 | #if 0 |
1682 | printk("Es1938debug - AUDIO channel 1 interrupt\n"); | 1682 | printk(KERN_DEBUG |
1683 | printk("Es1938debug - AUDIO channel 1 DMAC DMA count: %u\n", | 1683 | "Es1938debug - AUDIO channel 1 interrupt\n"); |
1684 | printk(KERN_DEBUG | ||
1685 | "Es1938debug - AUDIO channel 1 DMAC DMA count: %u\n", | ||
1684 | inw(SLDM_REG(chip, DMACOUNT))); | 1686 | inw(SLDM_REG(chip, DMACOUNT))); |
1685 | printk("Es1938debug - AUDIO channel 1 DMAC DMA base: %u\n", | 1687 | printk(KERN_DEBUG |
1688 | "Es1938debug - AUDIO channel 1 DMAC DMA base: %u\n", | ||
1686 | inl(SLDM_REG(chip, DMAADDR))); | 1689 | inl(SLDM_REG(chip, DMAADDR))); |
1687 | printk("Es1938debug - AUDIO channel 1 DMAC DMA status: 0x%x\n", | 1690 | printk(KERN_DEBUG |
1691 | "Es1938debug - AUDIO channel 1 DMAC DMA status: 0x%x\n", | ||
1688 | inl(SLDM_REG(chip, DMASTATUS))); | 1692 | inl(SLDM_REG(chip, DMASTATUS))); |
1689 | #endif | 1693 | #endif |
1690 | /* clear irq */ | 1694 | /* clear irq */ |
@@ -1699,10 +1703,13 @@ static irqreturn_t snd_es1938_interrupt(int irq, void *dev_id) | |||
1699 | /* AUDIO 2 */ | 1703 | /* AUDIO 2 */ |
1700 | if (status & 0x20) { | 1704 | if (status & 0x20) { |
1701 | #if 0 | 1705 | #if 0 |
1702 | printk("Es1938debug - AUDIO channel 2 interrupt\n"); | 1706 | printk(KERN_DEBUG |
1703 | printk("Es1938debug - AUDIO channel 2 DMAC DMA count: %u\n", | 1707 | "Es1938debug - AUDIO channel 2 interrupt\n"); |
1708 | printk(KERN_DEBUG | ||
1709 | "Es1938debug - AUDIO channel 2 DMAC DMA count: %u\n", | ||
1704 | inw(SLIO_REG(chip, AUDIO2DMACOUNT))); | 1710 | inw(SLIO_REG(chip, AUDIO2DMACOUNT))); |
1705 | printk("Es1938debug - AUDIO channel 2 DMAC DMA base: %u\n", | 1711 | printk(KERN_DEBUG |
1712 | "Es1938debug - AUDIO channel 2 DMAC DMA base: %u\n", | ||
1706 | inl(SLIO_REG(chip, AUDIO2DMAADDR))); | 1713 | inl(SLIO_REG(chip, AUDIO2DMAADDR))); |
1707 | 1714 | ||
1708 | #endif | 1715 | #endif |
@@ -1799,9 +1806,9 @@ static int __devinit snd_es1938_probe(struct pci_dev *pci, | |||
1799 | return -ENOENT; | 1806 | return -ENOENT; |
1800 | } | 1807 | } |
1801 | 1808 | ||
1802 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 1809 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); |
1803 | if (card == NULL) | 1810 | if (err < 0) |
1804 | return -ENOMEM; | 1811 | return err; |
1805 | for (idx = 0; idx < 5; idx++) { | 1812 | for (idx = 0; idx < 5; idx++) { |
1806 | if (pci_resource_start(pci, idx) == 0 || | 1813 | if (pci_resource_start(pci, idx) == 0 || |
1807 | !(pci_resource_flags(pci, idx) & IORESOURCE_IO)) { | 1814 | !(pci_resource_flags(pci, idx) & IORESOURCE_IO)) { |
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index e9c3794bbcb8..dc97e8116141 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c | |||
@@ -2645,9 +2645,9 @@ static int __devinit snd_es1968_probe(struct pci_dev *pci, | |||
2645 | return -ENOENT; | 2645 | return -ENOENT; |
2646 | } | 2646 | } |
2647 | 2647 | ||
2648 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 2648 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); |
2649 | if (!card) | 2649 | if (err < 0) |
2650 | return -ENOMEM; | 2650 | return err; |
2651 | 2651 | ||
2652 | if (total_bufsize[dev] < 128) | 2652 | if (total_bufsize[dev] < 128) |
2653 | total_bufsize[dev] = 128; | 2653 | total_bufsize[dev] = 128; |
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index c129f9e2072c..60cdb9e0b68d 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c | |||
@@ -1468,9 +1468,9 @@ static int __devinit snd_card_fm801_probe(struct pci_dev *pci, | |||
1468 | return -ENOENT; | 1468 | return -ENOENT; |
1469 | } | 1469 | } |
1470 | 1470 | ||
1471 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 1471 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); |
1472 | if (card == NULL) | 1472 | if (err < 0) |
1473 | return -ENOMEM; | 1473 | return err; |
1474 | if ((err = snd_fm801_create(card, pci, tea575x_tuner[dev], &chip)) < 0) { | 1474 | if ((err = snd_fm801_create(card, pci, tea575x_tuner[dev], &chip)) < 0) { |
1475 | snd_card_free(card); | 1475 | snd_card_free(card); |
1476 | return err; | 1476 | return err; |
diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c index 960fd7970384..4de5bacd3929 100644 --- a/sound/pci/hda/hda_beep.c +++ b/sound/pci/hda/hda_beep.c | |||
@@ -138,6 +138,7 @@ void snd_hda_detach_beep_device(struct hda_codec *codec) | |||
138 | 138 | ||
139 | input_unregister_device(beep->dev); | 139 | input_unregister_device(beep->dev); |
140 | kfree(beep); | 140 | kfree(beep); |
141 | codec->beep = NULL; | ||
141 | } | 142 | } |
142 | } | 143 | } |
143 | EXPORT_SYMBOL_HDA(snd_hda_detach_beep_device); | 144 | EXPORT_SYMBOL_HDA(snd_hda_detach_beep_device); |
diff --git a/sound/pci/hda/hda_beep.h b/sound/pci/hda/hda_beep.h index b9679f081cae..51bf6a5daf39 100644 --- a/sound/pci/hda/hda_beep.h +++ b/sound/pci/hda/hda_beep.h | |||
@@ -39,7 +39,7 @@ struct hda_beep { | |||
39 | int snd_hda_attach_beep_device(struct hda_codec *codec, int nid); | 39 | int snd_hda_attach_beep_device(struct hda_codec *codec, int nid); |
40 | void snd_hda_detach_beep_device(struct hda_codec *codec); | 40 | void snd_hda_detach_beep_device(struct hda_codec *codec); |
41 | #else | 41 | #else |
42 | #define snd_hda_attach_beep_device(...) | 42 | #define snd_hda_attach_beep_device(...) 0 |
43 | #define snd_hda_detach_beep_device(...) | 43 | #define snd_hda_detach_beep_device(...) |
44 | #endif | 44 | #endif |
45 | #endif | 45 | #endif |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index d03f99298be9..a4e5e5952115 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -647,9 +647,9 @@ static void /*__devinit*/ setup_fg_nodes(struct hda_codec *codec) | |||
647 | 647 | ||
648 | total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid); | 648 | total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid); |
649 | for (i = 0; i < total_nodes; i++, nid++) { | 649 | for (i = 0; i < total_nodes; i++, nid++) { |
650 | unsigned int func; | 650 | codec->function_id = snd_hda_param_read(codec, nid, |
651 | func = snd_hda_param_read(codec, nid, AC_PAR_FUNCTION_TYPE); | 651 | AC_PAR_FUNCTION_TYPE) & 0xff; |
652 | switch (func & 0xff) { | 652 | switch (codec->function_id) { |
653 | case AC_GRP_AUDIO_FUNCTION: | 653 | case AC_GRP_AUDIO_FUNCTION: |
654 | codec->afg = nid; | 654 | codec->afg = nid; |
655 | break; | 655 | break; |
@@ -682,11 +682,140 @@ static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node) | |||
682 | return 0; | 682 | return 0; |
683 | } | 683 | } |
684 | 684 | ||
685 | /* read all pin default configurations and save codec->init_pins */ | ||
686 | static int read_pin_defaults(struct hda_codec *codec) | ||
687 | { | ||
688 | int i; | ||
689 | hda_nid_t nid = codec->start_nid; | ||
690 | |||
691 | for (i = 0; i < codec->num_nodes; i++, nid++) { | ||
692 | struct hda_pincfg *pin; | ||
693 | unsigned int wcaps = get_wcaps(codec, nid); | ||
694 | unsigned int wid_type = (wcaps & AC_WCAP_TYPE) >> | ||
695 | AC_WCAP_TYPE_SHIFT; | ||
696 | if (wid_type != AC_WID_PIN) | ||
697 | continue; | ||
698 | pin = snd_array_new(&codec->init_pins); | ||
699 | if (!pin) | ||
700 | return -ENOMEM; | ||
701 | pin->nid = nid; | ||
702 | pin->cfg = snd_hda_codec_read(codec, nid, 0, | ||
703 | AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
704 | } | ||
705 | return 0; | ||
706 | } | ||
707 | |||
708 | /* look up the given pin config list and return the item matching with NID */ | ||
709 | static struct hda_pincfg *look_up_pincfg(struct hda_codec *codec, | ||
710 | struct snd_array *array, | ||
711 | hda_nid_t nid) | ||
712 | { | ||
713 | int i; | ||
714 | for (i = 0; i < array->used; i++) { | ||
715 | struct hda_pincfg *pin = snd_array_elem(array, i); | ||
716 | if (pin->nid == nid) | ||
717 | return pin; | ||
718 | } | ||
719 | return NULL; | ||
720 | } | ||
721 | |||
722 | /* write a config value for the given NID */ | ||
723 | static void set_pincfg(struct hda_codec *codec, hda_nid_t nid, | ||
724 | unsigned int cfg) | ||
725 | { | ||
726 | int i; | ||
727 | for (i = 0; i < 4; i++) { | ||
728 | snd_hda_codec_write(codec, nid, 0, | ||
729 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 + i, | ||
730 | cfg & 0xff); | ||
731 | cfg >>= 8; | ||
732 | } | ||
733 | } | ||
734 | |||
735 | /* set the current pin config value for the given NID. | ||
736 | * the value is cached, and read via snd_hda_codec_get_pincfg() | ||
737 | */ | ||
738 | int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list, | ||
739 | hda_nid_t nid, unsigned int cfg) | ||
740 | { | ||
741 | struct hda_pincfg *pin; | ||
742 | unsigned int oldcfg; | ||
743 | |||
744 | oldcfg = snd_hda_codec_get_pincfg(codec, nid); | ||
745 | pin = look_up_pincfg(codec, list, nid); | ||
746 | if (!pin) { | ||
747 | pin = snd_array_new(list); | ||
748 | if (!pin) | ||
749 | return -ENOMEM; | ||
750 | pin->nid = nid; | ||
751 | } | ||
752 | pin->cfg = cfg; | ||
753 | |||
754 | /* change only when needed; e.g. if the pincfg is already present | ||
755 | * in user_pins[], don't write it | ||
756 | */ | ||
757 | cfg = snd_hda_codec_get_pincfg(codec, nid); | ||
758 | if (oldcfg != cfg) | ||
759 | set_pincfg(codec, nid, cfg); | ||
760 | return 0; | ||
761 | } | ||
762 | |||
763 | int snd_hda_codec_set_pincfg(struct hda_codec *codec, | ||
764 | hda_nid_t nid, unsigned int cfg) | ||
765 | { | ||
766 | return snd_hda_add_pincfg(codec, &codec->driver_pins, nid, cfg); | ||
767 | } | ||
768 | EXPORT_SYMBOL_HDA(snd_hda_codec_set_pincfg); | ||
769 | |||
770 | /* get the current pin config value of the given pin NID */ | ||
771 | unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid) | ||
772 | { | ||
773 | struct hda_pincfg *pin; | ||
774 | |||
775 | #ifdef CONFIG_SND_HDA_HWDEP | ||
776 | pin = look_up_pincfg(codec, &codec->user_pins, nid); | ||
777 | if (pin) | ||
778 | return pin->cfg; | ||
779 | #endif | ||
780 | pin = look_up_pincfg(codec, &codec->driver_pins, nid); | ||
781 | if (pin) | ||
782 | return pin->cfg; | ||
783 | pin = look_up_pincfg(codec, &codec->init_pins, nid); | ||
784 | if (pin) | ||
785 | return pin->cfg; | ||
786 | return 0; | ||
787 | } | ||
788 | EXPORT_SYMBOL_HDA(snd_hda_codec_get_pincfg); | ||
789 | |||
790 | /* restore all current pin configs */ | ||
791 | static void restore_pincfgs(struct hda_codec *codec) | ||
792 | { | ||
793 | int i; | ||
794 | for (i = 0; i < codec->init_pins.used; i++) { | ||
795 | struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i); | ||
796 | set_pincfg(codec, pin->nid, | ||
797 | snd_hda_codec_get_pincfg(codec, pin->nid)); | ||
798 | } | ||
799 | } | ||
685 | 800 | ||
686 | static void init_hda_cache(struct hda_cache_rec *cache, | 801 | static void init_hda_cache(struct hda_cache_rec *cache, |
687 | unsigned int record_size); | 802 | unsigned int record_size); |
688 | static void free_hda_cache(struct hda_cache_rec *cache); | 803 | static void free_hda_cache(struct hda_cache_rec *cache); |
689 | 804 | ||
805 | /* restore the initial pin cfgs and release all pincfg lists */ | ||
806 | static void restore_init_pincfgs(struct hda_codec *codec) | ||
807 | { | ||
808 | /* first free driver_pins and user_pins, then call restore_pincfg | ||
809 | * so that only the values in init_pins are restored | ||
810 | */ | ||
811 | snd_array_free(&codec->driver_pins); | ||
812 | #ifdef CONFIG_SND_HDA_HWDEP | ||
813 | snd_array_free(&codec->user_pins); | ||
814 | #endif | ||
815 | restore_pincfgs(codec); | ||
816 | snd_array_free(&codec->init_pins); | ||
817 | } | ||
818 | |||
690 | /* | 819 | /* |
691 | * codec destructor | 820 | * codec destructor |
692 | */ | 821 | */ |
@@ -694,6 +823,7 @@ static void snd_hda_codec_free(struct hda_codec *codec) | |||
694 | { | 823 | { |
695 | if (!codec) | 824 | if (!codec) |
696 | return; | 825 | return; |
826 | restore_init_pincfgs(codec); | ||
697 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 827 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
698 | cancel_delayed_work(&codec->power_work); | 828 | cancel_delayed_work(&codec->power_work); |
699 | flush_workqueue(codec->bus->workq); | 829 | flush_workqueue(codec->bus->workq); |
@@ -712,6 +842,9 @@ static void snd_hda_codec_free(struct hda_codec *codec) | |||
712 | kfree(codec); | 842 | kfree(codec); |
713 | } | 843 | } |
714 | 844 | ||
845 | static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, | ||
846 | unsigned int power_state); | ||
847 | |||
715 | /** | 848 | /** |
716 | * snd_hda_codec_new - create a HDA codec | 849 | * snd_hda_codec_new - create a HDA codec |
717 | * @bus: the bus to assign | 850 | * @bus: the bus to assign |
@@ -751,6 +884,8 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr | |||
751 | init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); | 884 | init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); |
752 | init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); | 885 | init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); |
753 | snd_array_init(&codec->mixers, sizeof(struct snd_kcontrol *), 32); | 886 | snd_array_init(&codec->mixers, sizeof(struct snd_kcontrol *), 32); |
887 | snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16); | ||
888 | snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16); | ||
754 | if (codec->bus->modelname) { | 889 | if (codec->bus->modelname) { |
755 | codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL); | 890 | codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL); |
756 | if (!codec->modelname) { | 891 | if (!codec->modelname) { |
@@ -787,15 +922,18 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr | |||
787 | setup_fg_nodes(codec); | 922 | setup_fg_nodes(codec); |
788 | if (!codec->afg && !codec->mfg) { | 923 | if (!codec->afg && !codec->mfg) { |
789 | snd_printdd("hda_codec: no AFG or MFG node found\n"); | 924 | snd_printdd("hda_codec: no AFG or MFG node found\n"); |
790 | snd_hda_codec_free(codec); | 925 | err = -ENODEV; |
791 | return -ENODEV; | 926 | goto error; |
792 | } | 927 | } |
793 | 928 | ||
794 | if (read_widget_caps(codec, codec->afg ? codec->afg : codec->mfg) < 0) { | 929 | err = read_widget_caps(codec, codec->afg ? codec->afg : codec->mfg); |
930 | if (err < 0) { | ||
795 | snd_printk(KERN_ERR "hda_codec: cannot malloc\n"); | 931 | snd_printk(KERN_ERR "hda_codec: cannot malloc\n"); |
796 | snd_hda_codec_free(codec); | 932 | goto error; |
797 | return -ENOMEM; | ||
798 | } | 933 | } |
934 | err = read_pin_defaults(codec); | ||
935 | if (err < 0) | ||
936 | goto error; | ||
799 | 937 | ||
800 | if (!codec->subsystem_id) { | 938 | if (!codec->subsystem_id) { |
801 | hda_nid_t nid = codec->afg ? codec->afg : codec->mfg; | 939 | hda_nid_t nid = codec->afg ? codec->afg : codec->mfg; |
@@ -806,12 +944,15 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr | |||
806 | if (bus->modelname) | 944 | if (bus->modelname) |
807 | codec->modelname = kstrdup(bus->modelname, GFP_KERNEL); | 945 | codec->modelname = kstrdup(bus->modelname, GFP_KERNEL); |
808 | 946 | ||
947 | /* power-up all before initialization */ | ||
948 | hda_set_power_state(codec, | ||
949 | codec->afg ? codec->afg : codec->mfg, | ||
950 | AC_PWRST_D0); | ||
951 | |||
809 | if (do_init) { | 952 | if (do_init) { |
810 | err = snd_hda_codec_configure(codec); | 953 | err = snd_hda_codec_configure(codec); |
811 | if (err < 0) { | 954 | if (err < 0) |
812 | snd_hda_codec_free(codec); | 955 | goto error; |
813 | return err; | ||
814 | } | ||
815 | } | 956 | } |
816 | snd_hda_codec_proc_new(codec); | 957 | snd_hda_codec_proc_new(codec); |
817 | 958 | ||
@@ -824,6 +965,10 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr | |||
824 | if (codecp) | 965 | if (codecp) |
825 | *codecp = codec; | 966 | *codecp = codec; |
826 | return 0; | 967 | return 0; |
968 | |||
969 | error: | ||
970 | snd_hda_codec_free(codec); | ||
971 | return err; | ||
827 | } | 972 | } |
828 | EXPORT_SYMBOL_HDA(snd_hda_codec_new); | 973 | EXPORT_SYMBOL_HDA(snd_hda_codec_new); |
829 | 974 | ||
@@ -907,6 +1052,7 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream); | |||
907 | 1052 | ||
908 | /* FIXME: more better hash key? */ | 1053 | /* FIXME: more better hash key? */ |
909 | #define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24)) | 1054 | #define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24)) |
1055 | #define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24)) | ||
910 | #define INFO_AMP_CAPS (1<<0) | 1056 | #define INFO_AMP_CAPS (1<<0) |
911 | #define INFO_AMP_VOL(ch) (1 << (1 + (ch))) | 1057 | #define INFO_AMP_VOL(ch) (1 << (1 + (ch))) |
912 | 1058 | ||
@@ -997,6 +1143,21 @@ int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, | |||
997 | } | 1143 | } |
998 | EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps); | 1144 | EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps); |
999 | 1145 | ||
1146 | u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid) | ||
1147 | { | ||
1148 | struct hda_amp_info *info; | ||
1149 | |||
1150 | info = get_alloc_amp_hash(codec, HDA_HASH_PINCAP_KEY(nid)); | ||
1151 | if (!info) | ||
1152 | return 0; | ||
1153 | if (!info->head.val) { | ||
1154 | info->amp_caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); | ||
1155 | info->head.val |= INFO_AMP_CAPS; | ||
1156 | } | ||
1157 | return info->amp_caps; | ||
1158 | } | ||
1159 | EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps); | ||
1160 | |||
1000 | /* | 1161 | /* |
1001 | * read the current volume to info | 1162 | * read the current volume to info |
1002 | * if the cache exists, read the cache value. | 1163 | * if the cache exists, read the cache value. |
@@ -1120,6 +1281,7 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, | |||
1120 | u16 nid = get_amp_nid(kcontrol); | 1281 | u16 nid = get_amp_nid(kcontrol); |
1121 | u8 chs = get_amp_channels(kcontrol); | 1282 | u8 chs = get_amp_channels(kcontrol); |
1122 | int dir = get_amp_direction(kcontrol); | 1283 | int dir = get_amp_direction(kcontrol); |
1284 | unsigned int ofs = get_amp_offset(kcontrol); | ||
1123 | u32 caps; | 1285 | u32 caps; |
1124 | 1286 | ||
1125 | caps = query_amp_caps(codec, nid, dir); | 1287 | caps = query_amp_caps(codec, nid, dir); |
@@ -1131,6 +1293,8 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, | |||
1131 | kcontrol->id.name); | 1293 | kcontrol->id.name); |
1132 | return -EINVAL; | 1294 | return -EINVAL; |
1133 | } | 1295 | } |
1296 | if (ofs < caps) | ||
1297 | caps -= ofs; | ||
1134 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | 1298 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
1135 | uinfo->count = chs == 3 ? 2 : 1; | 1299 | uinfo->count = chs == 3 ? 2 : 1; |
1136 | uinfo->value.integer.min = 0; | 1300 | uinfo->value.integer.min = 0; |
@@ -1139,6 +1303,32 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, | |||
1139 | } | 1303 | } |
1140 | EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info); | 1304 | EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info); |
1141 | 1305 | ||
1306 | |||
1307 | static inline unsigned int | ||
1308 | read_amp_value(struct hda_codec *codec, hda_nid_t nid, | ||
1309 | int ch, int dir, int idx, unsigned int ofs) | ||
1310 | { | ||
1311 | unsigned int val; | ||
1312 | val = snd_hda_codec_amp_read(codec, nid, ch, dir, idx); | ||
1313 | val &= HDA_AMP_VOLMASK; | ||
1314 | if (val >= ofs) | ||
1315 | val -= ofs; | ||
1316 | else | ||
1317 | val = 0; | ||
1318 | return val; | ||
1319 | } | ||
1320 | |||
1321 | static inline int | ||
1322 | update_amp_value(struct hda_codec *codec, hda_nid_t nid, | ||
1323 | int ch, int dir, int idx, unsigned int ofs, | ||
1324 | unsigned int val) | ||
1325 | { | ||
1326 | if (val > 0) | ||
1327 | val += ofs; | ||
1328 | return snd_hda_codec_amp_update(codec, nid, ch, dir, idx, | ||
1329 | HDA_AMP_VOLMASK, val); | ||
1330 | } | ||
1331 | |||
1142 | int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, | 1332 | int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, |
1143 | struct snd_ctl_elem_value *ucontrol) | 1333 | struct snd_ctl_elem_value *ucontrol) |
1144 | { | 1334 | { |
@@ -1147,14 +1337,13 @@ int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, | |||
1147 | int chs = get_amp_channels(kcontrol); | 1337 | int chs = get_amp_channels(kcontrol); |
1148 | int dir = get_amp_direction(kcontrol); | 1338 | int dir = get_amp_direction(kcontrol); |
1149 | int idx = get_amp_index(kcontrol); | 1339 | int idx = get_amp_index(kcontrol); |
1340 | unsigned int ofs = get_amp_offset(kcontrol); | ||
1150 | long *valp = ucontrol->value.integer.value; | 1341 | long *valp = ucontrol->value.integer.value; |
1151 | 1342 | ||
1152 | if (chs & 1) | 1343 | if (chs & 1) |
1153 | *valp++ = snd_hda_codec_amp_read(codec, nid, 0, dir, idx) | 1344 | *valp++ = read_amp_value(codec, nid, 0, dir, idx, ofs); |
1154 | & HDA_AMP_VOLMASK; | ||
1155 | if (chs & 2) | 1345 | if (chs & 2) |
1156 | *valp = snd_hda_codec_amp_read(codec, nid, 1, dir, idx) | 1346 | *valp = read_amp_value(codec, nid, 1, dir, idx, ofs); |
1157 | & HDA_AMP_VOLMASK; | ||
1158 | return 0; | 1347 | return 0; |
1159 | } | 1348 | } |
1160 | EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get); | 1349 | EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get); |
@@ -1167,18 +1356,17 @@ int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, | |||
1167 | int chs = get_amp_channels(kcontrol); | 1356 | int chs = get_amp_channels(kcontrol); |
1168 | int dir = get_amp_direction(kcontrol); | 1357 | int dir = get_amp_direction(kcontrol); |
1169 | int idx = get_amp_index(kcontrol); | 1358 | int idx = get_amp_index(kcontrol); |
1359 | unsigned int ofs = get_amp_offset(kcontrol); | ||
1170 | long *valp = ucontrol->value.integer.value; | 1360 | long *valp = ucontrol->value.integer.value; |
1171 | int change = 0; | 1361 | int change = 0; |
1172 | 1362 | ||
1173 | snd_hda_power_up(codec); | 1363 | snd_hda_power_up(codec); |
1174 | if (chs & 1) { | 1364 | if (chs & 1) { |
1175 | change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx, | 1365 | change = update_amp_value(codec, nid, 0, dir, idx, ofs, *valp); |
1176 | 0x7f, *valp); | ||
1177 | valp++; | 1366 | valp++; |
1178 | } | 1367 | } |
1179 | if (chs & 2) | 1368 | if (chs & 2) |
1180 | change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx, | 1369 | change |= update_amp_value(codec, nid, 1, dir, idx, ofs, *valp); |
1181 | 0x7f, *valp); | ||
1182 | snd_hda_power_down(codec); | 1370 | snd_hda_power_down(codec); |
1183 | return change; | 1371 | return change; |
1184 | } | 1372 | } |
@@ -1190,6 +1378,7 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, | |||
1190 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 1378 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
1191 | hda_nid_t nid = get_amp_nid(kcontrol); | 1379 | hda_nid_t nid = get_amp_nid(kcontrol); |
1192 | int dir = get_amp_direction(kcontrol); | 1380 | int dir = get_amp_direction(kcontrol); |
1381 | unsigned int ofs = get_amp_offset(kcontrol); | ||
1193 | u32 caps, val1, val2; | 1382 | u32 caps, val1, val2; |
1194 | 1383 | ||
1195 | if (size < 4 * sizeof(unsigned int)) | 1384 | if (size < 4 * sizeof(unsigned int)) |
@@ -1198,6 +1387,7 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, | |||
1198 | val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT; | 1387 | val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT; |
1199 | val2 = (val2 + 1) * 25; | 1388 | val2 = (val2 + 1) * 25; |
1200 | val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT); | 1389 | val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT); |
1390 | val1 += ofs; | ||
1201 | val1 = ((int)val1) * ((int)val2); | 1391 | val1 = ((int)val1) * ((int)val2); |
1202 | if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv)) | 1392 | if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv)) |
1203 | return -EFAULT; | 1393 | return -EFAULT; |
@@ -1268,7 +1458,6 @@ int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl) | |||
1268 | } | 1458 | } |
1269 | EXPORT_SYMBOL_HDA(snd_hda_ctl_add); | 1459 | EXPORT_SYMBOL_HDA(snd_hda_ctl_add); |
1270 | 1460 | ||
1271 | #ifdef CONFIG_SND_HDA_RECONFIG | ||
1272 | /* Clear all controls assigned to the given codec */ | 1461 | /* Clear all controls assigned to the given codec */ |
1273 | void snd_hda_ctls_clear(struct hda_codec *codec) | 1462 | void snd_hda_ctls_clear(struct hda_codec *codec) |
1274 | { | 1463 | { |
@@ -1279,9 +1468,52 @@ void snd_hda_ctls_clear(struct hda_codec *codec) | |||
1279 | snd_array_free(&codec->mixers); | 1468 | snd_array_free(&codec->mixers); |
1280 | } | 1469 | } |
1281 | 1470 | ||
1282 | void snd_hda_codec_reset(struct hda_codec *codec) | 1471 | /* pseudo device locking |
1472 | * toggle card->shutdown to allow/disallow the device access (as a hack) | ||
1473 | */ | ||
1474 | static int hda_lock_devices(struct snd_card *card) | ||
1283 | { | 1475 | { |
1284 | int i; | 1476 | spin_lock(&card->files_lock); |
1477 | if (card->shutdown) { | ||
1478 | spin_unlock(&card->files_lock); | ||
1479 | return -EINVAL; | ||
1480 | } | ||
1481 | card->shutdown = 1; | ||
1482 | spin_unlock(&card->files_lock); | ||
1483 | return 0; | ||
1484 | } | ||
1485 | |||
1486 | static void hda_unlock_devices(struct snd_card *card) | ||
1487 | { | ||
1488 | spin_lock(&card->files_lock); | ||
1489 | card->shutdown = 0; | ||
1490 | spin_unlock(&card->files_lock); | ||
1491 | } | ||
1492 | |||
1493 | int snd_hda_codec_reset(struct hda_codec *codec) | ||
1494 | { | ||
1495 | struct snd_card *card = codec->bus->card; | ||
1496 | int i, pcm; | ||
1497 | |||
1498 | if (hda_lock_devices(card) < 0) | ||
1499 | return -EBUSY; | ||
1500 | /* check whether the codec isn't used by any mixer or PCM streams */ | ||
1501 | if (!list_empty(&card->ctl_files)) { | ||
1502 | hda_unlock_devices(card); | ||
1503 | return -EBUSY; | ||
1504 | } | ||
1505 | for (pcm = 0; pcm < codec->num_pcms; pcm++) { | ||
1506 | struct hda_pcm *cpcm = &codec->pcm_info[pcm]; | ||
1507 | if (!cpcm->pcm) | ||
1508 | continue; | ||
1509 | if (cpcm->pcm->streams[0].substream_opened || | ||
1510 | cpcm->pcm->streams[1].substream_opened) { | ||
1511 | hda_unlock_devices(card); | ||
1512 | return -EBUSY; | ||
1513 | } | ||
1514 | } | ||
1515 | |||
1516 | /* OK, let it free */ | ||
1285 | 1517 | ||
1286 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 1518 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
1287 | cancel_delayed_work(&codec->power_work); | 1519 | cancel_delayed_work(&codec->power_work); |
@@ -1291,8 +1523,7 @@ void snd_hda_codec_reset(struct hda_codec *codec) | |||
1291 | /* relase PCMs */ | 1523 | /* relase PCMs */ |
1292 | for (i = 0; i < codec->num_pcms; i++) { | 1524 | for (i = 0; i < codec->num_pcms; i++) { |
1293 | if (codec->pcm_info[i].pcm) { | 1525 | if (codec->pcm_info[i].pcm) { |
1294 | snd_device_free(codec->bus->card, | 1526 | snd_device_free(card, codec->pcm_info[i].pcm); |
1295 | codec->pcm_info[i].pcm); | ||
1296 | clear_bit(codec->pcm_info[i].device, | 1527 | clear_bit(codec->pcm_info[i].device, |
1297 | codec->bus->pcm_dev_bits); | 1528 | codec->bus->pcm_dev_bits); |
1298 | } | 1529 | } |
@@ -1305,13 +1536,22 @@ void snd_hda_codec_reset(struct hda_codec *codec) | |||
1305 | free_hda_cache(&codec->cmd_cache); | 1536 | free_hda_cache(&codec->cmd_cache); |
1306 | init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); | 1537 | init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); |
1307 | init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); | 1538 | init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); |
1539 | /* free only driver_pins so that init_pins + user_pins are restored */ | ||
1540 | snd_array_free(&codec->driver_pins); | ||
1541 | restore_pincfgs(codec); | ||
1308 | codec->num_pcms = 0; | 1542 | codec->num_pcms = 0; |
1309 | codec->pcm_info = NULL; | 1543 | codec->pcm_info = NULL; |
1310 | codec->preset = NULL; | 1544 | codec->preset = NULL; |
1545 | memset(&codec->patch_ops, 0, sizeof(codec->patch_ops)); | ||
1546 | codec->slave_dig_outs = NULL; | ||
1547 | codec->spdif_status_reset = 0; | ||
1311 | module_put(codec->owner); | 1548 | module_put(codec->owner); |
1312 | codec->owner = NULL; | 1549 | codec->owner = NULL; |
1550 | |||
1551 | /* allow device access again */ | ||
1552 | hda_unlock_devices(card); | ||
1553 | return 0; | ||
1313 | } | 1554 | } |
1314 | #endif /* CONFIG_SND_HDA_RECONFIG */ | ||
1315 | 1555 | ||
1316 | /* create a virtual master control and add slaves */ | 1556 | /* create a virtual master control and add slaves */ |
1317 | int snd_hda_add_vmaster(struct hda_codec *codec, char *name, | 1557 | int snd_hda_add_vmaster(struct hda_codec *codec, char *name, |
@@ -1336,15 +1576,20 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name, | |||
1336 | 1576 | ||
1337 | for (s = slaves; *s; s++) { | 1577 | for (s = slaves; *s; s++) { |
1338 | struct snd_kcontrol *sctl; | 1578 | struct snd_kcontrol *sctl; |
1339 | 1579 | int i = 0; | |
1340 | sctl = snd_hda_find_mixer_ctl(codec, *s); | 1580 | for (;;) { |
1341 | if (!sctl) { | 1581 | sctl = _snd_hda_find_mixer_ctl(codec, *s, i); |
1342 | snd_printdd("Cannot find slave %s, skipped\n", *s); | 1582 | if (!sctl) { |
1343 | continue; | 1583 | if (!i) |
1584 | snd_printdd("Cannot find slave %s, " | ||
1585 | "skipped\n", *s); | ||
1586 | break; | ||
1587 | } | ||
1588 | err = snd_ctl_add_slave(kctl, sctl); | ||
1589 | if (err < 0) | ||
1590 | return err; | ||
1591 | i++; | ||
1344 | } | 1592 | } |
1345 | err = snd_ctl_add_slave(kctl, sctl); | ||
1346 | if (err < 0) | ||
1347 | return err; | ||
1348 | } | 1593 | } |
1349 | return 0; | 1594 | return 0; |
1350 | } | 1595 | } |
@@ -1955,6 +2200,8 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid) | |||
1955 | } | 2200 | } |
1956 | for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) { | 2201 | for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) { |
1957 | kctl = snd_ctl_new1(dig_mix, codec); | 2202 | kctl = snd_ctl_new1(dig_mix, codec); |
2203 | if (!kctl) | ||
2204 | return -ENOMEM; | ||
1958 | kctl->private_value = nid; | 2205 | kctl->private_value = nid; |
1959 | err = snd_hda_ctl_add(codec, kctl); | 2206 | err = snd_hda_ctl_add(codec, kctl); |
1960 | if (err < 0) | 2207 | if (err < 0) |
@@ -2074,8 +2321,7 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, | |||
2074 | * don't power down the widget if it controls | 2321 | * don't power down the widget if it controls |
2075 | * eapd and EAPD_BTLENABLE is set. | 2322 | * eapd and EAPD_BTLENABLE is set. |
2076 | */ | 2323 | */ |
2077 | pincap = snd_hda_param_read(codec, nid, | 2324 | pincap = snd_hda_query_pin_caps(codec, nid); |
2078 | AC_PAR_PIN_CAP); | ||
2079 | if (pincap & AC_PINCAP_EAPD) { | 2325 | if (pincap & AC_PINCAP_EAPD) { |
2080 | int eapd = snd_hda_codec_read(codec, | 2326 | int eapd = snd_hda_codec_read(codec, |
2081 | nid, 0, | 2327 | nid, 0, |
@@ -2144,6 +2390,7 @@ static void hda_call_codec_resume(struct hda_codec *codec) | |||
2144 | hda_set_power_state(codec, | 2390 | hda_set_power_state(codec, |
2145 | codec->afg ? codec->afg : codec->mfg, | 2391 | codec->afg ? codec->afg : codec->mfg, |
2146 | AC_PWRST_D0); | 2392 | AC_PWRST_D0); |
2393 | restore_pincfgs(codec); /* restore all current pin configs */ | ||
2147 | hda_exec_init_verbs(codec); | 2394 | hda_exec_init_verbs(codec); |
2148 | if (codec->patch_ops.resume) | 2395 | if (codec->patch_ops.resume) |
2149 | codec->patch_ops.resume(codec); | 2396 | codec->patch_ops.resume(codec); |
@@ -2171,8 +2418,16 @@ int /*__devinit*/ snd_hda_build_controls(struct hda_bus *bus) | |||
2171 | 2418 | ||
2172 | list_for_each_entry(codec, &bus->codec_list, list) { | 2419 | list_for_each_entry(codec, &bus->codec_list, list) { |
2173 | int err = snd_hda_codec_build_controls(codec); | 2420 | int err = snd_hda_codec_build_controls(codec); |
2174 | if (err < 0) | 2421 | if (err < 0) { |
2175 | return err; | 2422 | printk(KERN_ERR "hda_codec: cannot build controls" |
2423 | "for #%d (error %d)\n", codec->addr, err); | ||
2424 | err = snd_hda_codec_reset(codec); | ||
2425 | if (err < 0) { | ||
2426 | printk(KERN_ERR | ||
2427 | "hda_codec: cannot revert codec\n"); | ||
2428 | return err; | ||
2429 | } | ||
2430 | } | ||
2176 | } | 2431 | } |
2177 | return 0; | 2432 | return 0; |
2178 | } | 2433 | } |
@@ -2181,19 +2436,12 @@ EXPORT_SYMBOL_HDA(snd_hda_build_controls); | |||
2181 | int snd_hda_codec_build_controls(struct hda_codec *codec) | 2436 | int snd_hda_codec_build_controls(struct hda_codec *codec) |
2182 | { | 2437 | { |
2183 | int err = 0; | 2438 | int err = 0; |
2184 | /* fake as if already powered-on */ | ||
2185 | hda_keep_power_on(codec); | ||
2186 | /* then fire up */ | ||
2187 | hda_set_power_state(codec, | ||
2188 | codec->afg ? codec->afg : codec->mfg, | ||
2189 | AC_PWRST_D0); | ||
2190 | hda_exec_init_verbs(codec); | 2439 | hda_exec_init_verbs(codec); |
2191 | /* continue to initialize... */ | 2440 | /* continue to initialize... */ |
2192 | if (codec->patch_ops.init) | 2441 | if (codec->patch_ops.init) |
2193 | err = codec->patch_ops.init(codec); | 2442 | err = codec->patch_ops.init(codec); |
2194 | if (!err && codec->patch_ops.build_controls) | 2443 | if (!err && codec->patch_ops.build_controls) |
2195 | err = codec->patch_ops.build_controls(codec); | 2444 | err = codec->patch_ops.build_controls(codec); |
2196 | snd_hda_power_down(codec); | ||
2197 | if (err < 0) | 2445 | if (err < 0) |
2198 | return err; | 2446 | return err; |
2199 | return 0; | 2447 | return 0; |
@@ -2306,12 +2554,11 @@ EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format); | |||
2306 | static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, | 2554 | static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, |
2307 | u32 *ratesp, u64 *formatsp, unsigned int *bpsp) | 2555 | u32 *ratesp, u64 *formatsp, unsigned int *bpsp) |
2308 | { | 2556 | { |
2309 | int i; | 2557 | unsigned int i, val, wcaps; |
2310 | unsigned int val, streams; | ||
2311 | 2558 | ||
2312 | val = 0; | 2559 | val = 0; |
2313 | if (nid != codec->afg && | 2560 | wcaps = get_wcaps(codec, nid); |
2314 | (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD)) { | 2561 | if (nid != codec->afg && (wcaps & AC_WCAP_FORMAT_OVRD)) { |
2315 | val = snd_hda_param_read(codec, nid, AC_PAR_PCM); | 2562 | val = snd_hda_param_read(codec, nid, AC_PAR_PCM); |
2316 | if (val == -1) | 2563 | if (val == -1) |
2317 | return -EIO; | 2564 | return -EIO; |
@@ -2325,15 +2572,20 @@ static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, | |||
2325 | if (val & (1 << i)) | 2572 | if (val & (1 << i)) |
2326 | rates |= rate_bits[i].alsa_bits; | 2573 | rates |= rate_bits[i].alsa_bits; |
2327 | } | 2574 | } |
2575 | if (rates == 0) { | ||
2576 | snd_printk(KERN_ERR "hda_codec: rates == 0 " | ||
2577 | "(nid=0x%x, val=0x%x, ovrd=%i)\n", | ||
2578 | nid, val, | ||
2579 | (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0); | ||
2580 | return -EIO; | ||
2581 | } | ||
2328 | *ratesp = rates; | 2582 | *ratesp = rates; |
2329 | } | 2583 | } |
2330 | 2584 | ||
2331 | if (formatsp || bpsp) { | 2585 | if (formatsp || bpsp) { |
2332 | u64 formats = 0; | 2586 | u64 formats = 0; |
2333 | unsigned int bps; | 2587 | unsigned int streams, bps; |
2334 | unsigned int wcaps; | ||
2335 | 2588 | ||
2336 | wcaps = get_wcaps(codec, nid); | ||
2337 | streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM); | 2589 | streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM); |
2338 | if (streams == -1) | 2590 | if (streams == -1) |
2339 | return -EIO; | 2591 | return -EIO; |
@@ -2386,6 +2638,15 @@ static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, | |||
2386 | formats |= SNDRV_PCM_FMTBIT_U8; | 2638 | formats |= SNDRV_PCM_FMTBIT_U8; |
2387 | bps = 8; | 2639 | bps = 8; |
2388 | } | 2640 | } |
2641 | if (formats == 0) { | ||
2642 | snd_printk(KERN_ERR "hda_codec: formats == 0 " | ||
2643 | "(nid=0x%x, val=0x%x, ovrd=%i, " | ||
2644 | "streams=0x%x)\n", | ||
2645 | nid, val, | ||
2646 | (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0, | ||
2647 | streams); | ||
2648 | return -EIO; | ||
2649 | } | ||
2389 | if (formatsp) | 2650 | if (formatsp) |
2390 | *formatsp = formats; | 2651 | *formatsp = formats; |
2391 | if (bpsp) | 2652 | if (bpsp) |
@@ -2501,12 +2762,16 @@ static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo, | |||
2501 | static int set_pcm_default_values(struct hda_codec *codec, | 2762 | static int set_pcm_default_values(struct hda_codec *codec, |
2502 | struct hda_pcm_stream *info) | 2763 | struct hda_pcm_stream *info) |
2503 | { | 2764 | { |
2765 | int err; | ||
2766 | |||
2504 | /* query support PCM information from the given NID */ | 2767 | /* query support PCM information from the given NID */ |
2505 | if (info->nid && (!info->rates || !info->formats)) { | 2768 | if (info->nid && (!info->rates || !info->formats)) { |
2506 | snd_hda_query_supported_pcm(codec, info->nid, | 2769 | err = snd_hda_query_supported_pcm(codec, info->nid, |
2507 | info->rates ? NULL : &info->rates, | 2770 | info->rates ? NULL : &info->rates, |
2508 | info->formats ? NULL : &info->formats, | 2771 | info->formats ? NULL : &info->formats, |
2509 | info->maxbps ? NULL : &info->maxbps); | 2772 | info->maxbps ? NULL : &info->maxbps); |
2773 | if (err < 0) | ||
2774 | return err; | ||
2510 | } | 2775 | } |
2511 | if (info->ops.open == NULL) | 2776 | if (info->ops.open == NULL) |
2512 | info->ops.open = hda_pcm_default_open_close; | 2777 | info->ops.open = hda_pcm_default_open_close; |
@@ -2549,13 +2814,10 @@ static int get_empty_pcm_device(struct hda_bus *bus, int type) | |||
2549 | for (i = 0; i < ARRAY_SIZE(audio_idx); i++) { | 2814 | for (i = 0; i < ARRAY_SIZE(audio_idx); i++) { |
2550 | dev = audio_idx[i]; | 2815 | dev = audio_idx[i]; |
2551 | if (!test_bit(dev, bus->pcm_dev_bits)) | 2816 | if (!test_bit(dev, bus->pcm_dev_bits)) |
2552 | break; | 2817 | goto ok; |
2553 | } | ||
2554 | if (i >= ARRAY_SIZE(audio_idx)) { | ||
2555 | snd_printk(KERN_WARNING "Too many audio devices\n"); | ||
2556 | return -EAGAIN; | ||
2557 | } | 2818 | } |
2558 | break; | 2819 | snd_printk(KERN_WARNING "Too many audio devices\n"); |
2820 | return -EAGAIN; | ||
2559 | case HDA_PCM_TYPE_SPDIF: | 2821 | case HDA_PCM_TYPE_SPDIF: |
2560 | case HDA_PCM_TYPE_HDMI: | 2822 | case HDA_PCM_TYPE_HDMI: |
2561 | case HDA_PCM_TYPE_MODEM: | 2823 | case HDA_PCM_TYPE_MODEM: |
@@ -2570,6 +2832,7 @@ static int get_empty_pcm_device(struct hda_bus *bus, int type) | |||
2570 | snd_printk(KERN_WARNING "Invalid PCM type %d\n", type); | 2832 | snd_printk(KERN_WARNING "Invalid PCM type %d\n", type); |
2571 | return -EINVAL; | 2833 | return -EINVAL; |
2572 | } | 2834 | } |
2835 | ok: | ||
2573 | set_bit(dev, bus->pcm_dev_bits); | 2836 | set_bit(dev, bus->pcm_dev_bits); |
2574 | return dev; | 2837 | return dev; |
2575 | } | 2838 | } |
@@ -2606,24 +2869,36 @@ int snd_hda_codec_build_pcms(struct hda_codec *codec) | |||
2606 | if (!codec->patch_ops.build_pcms) | 2869 | if (!codec->patch_ops.build_pcms) |
2607 | return 0; | 2870 | return 0; |
2608 | err = codec->patch_ops.build_pcms(codec); | 2871 | err = codec->patch_ops.build_pcms(codec); |
2609 | if (err < 0) | 2872 | if (err < 0) { |
2610 | return err; | 2873 | printk(KERN_ERR "hda_codec: cannot build PCMs" |
2874 | "for #%d (error %d)\n", codec->addr, err); | ||
2875 | err = snd_hda_codec_reset(codec); | ||
2876 | if (err < 0) { | ||
2877 | printk(KERN_ERR | ||
2878 | "hda_codec: cannot revert codec\n"); | ||
2879 | return err; | ||
2880 | } | ||
2881 | } | ||
2611 | } | 2882 | } |
2612 | for (pcm = 0; pcm < codec->num_pcms; pcm++) { | 2883 | for (pcm = 0; pcm < codec->num_pcms; pcm++) { |
2613 | struct hda_pcm *cpcm = &codec->pcm_info[pcm]; | 2884 | struct hda_pcm *cpcm = &codec->pcm_info[pcm]; |
2614 | int dev; | 2885 | int dev; |
2615 | 2886 | ||
2616 | if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams) | 2887 | if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams) |
2617 | return 0; /* no substreams assigned */ | 2888 | continue; /* no substreams assigned */ |
2618 | 2889 | ||
2619 | if (!cpcm->pcm) { | 2890 | if (!cpcm->pcm) { |
2620 | dev = get_empty_pcm_device(codec->bus, cpcm->pcm_type); | 2891 | dev = get_empty_pcm_device(codec->bus, cpcm->pcm_type); |
2621 | if (dev < 0) | 2892 | if (dev < 0) |
2622 | return 0; | 2893 | continue; /* no fatal error */ |
2623 | cpcm->device = dev; | 2894 | cpcm->device = dev; |
2624 | err = snd_hda_attach_pcm(codec, cpcm); | 2895 | err = snd_hda_attach_pcm(codec, cpcm); |
2625 | if (err < 0) | 2896 | if (err < 0) { |
2626 | return err; | 2897 | printk(KERN_ERR "hda_codec: cannot attach " |
2898 | "PCM stream %d for codec #%d\n", | ||
2899 | dev, codec->addr); | ||
2900 | continue; /* no fatal error */ | ||
2901 | } | ||
2627 | } | 2902 | } |
2628 | } | 2903 | } |
2629 | return 0; | 2904 | return 0; |
@@ -3324,8 +3599,7 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
3324 | if (ignore_nids && is_in_nid_list(nid, ignore_nids)) | 3599 | if (ignore_nids && is_in_nid_list(nid, ignore_nids)) |
3325 | continue; | 3600 | continue; |
3326 | 3601 | ||
3327 | def_conf = snd_hda_codec_read(codec, nid, 0, | 3602 | def_conf = snd_hda_codec_get_pincfg(codec, nid); |
3328 | AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
3329 | if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE) | 3603 | if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE) |
3330 | continue; | 3604 | continue; |
3331 | loc = get_defcfg_location(def_conf); | 3605 | loc = get_defcfg_location(def_conf); |
@@ -3401,10 +3675,22 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
3401 | cfg->input_pins[AUTO_PIN_AUX] = nid; | 3675 | cfg->input_pins[AUTO_PIN_AUX] = nid; |
3402 | break; | 3676 | break; |
3403 | case AC_JACK_SPDIF_OUT: | 3677 | case AC_JACK_SPDIF_OUT: |
3404 | cfg->dig_out_pin = nid; | 3678 | case AC_JACK_DIG_OTHER_OUT: |
3679 | if (cfg->dig_outs >= ARRAY_SIZE(cfg->dig_out_pins)) | ||
3680 | continue; | ||
3681 | cfg->dig_out_pins[cfg->dig_outs] = nid; | ||
3682 | cfg->dig_out_type[cfg->dig_outs] = | ||
3683 | (loc == AC_JACK_LOC_HDMI) ? | ||
3684 | HDA_PCM_TYPE_HDMI : HDA_PCM_TYPE_SPDIF; | ||
3685 | cfg->dig_outs++; | ||
3405 | break; | 3686 | break; |
3406 | case AC_JACK_SPDIF_IN: | 3687 | case AC_JACK_SPDIF_IN: |
3688 | case AC_JACK_DIG_OTHER_IN: | ||
3407 | cfg->dig_in_pin = nid; | 3689 | cfg->dig_in_pin = nid; |
3690 | if (loc == AC_JACK_LOC_HDMI) | ||
3691 | cfg->dig_in_type = HDA_PCM_TYPE_HDMI; | ||
3692 | else | ||
3693 | cfg->dig_in_type = HDA_PCM_TYPE_SPDIF; | ||
3408 | break; | 3694 | break; |
3409 | } | 3695 | } |
3410 | } | 3696 | } |
@@ -3510,6 +3796,9 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
3510 | cfg->hp_pins[1], cfg->hp_pins[2], | 3796 | cfg->hp_pins[1], cfg->hp_pins[2], |
3511 | cfg->hp_pins[3], cfg->hp_pins[4]); | 3797 | cfg->hp_pins[3], cfg->hp_pins[4]); |
3512 | snd_printd(" mono: mono_out=0x%x\n", cfg->mono_out_pin); | 3798 | snd_printd(" mono: mono_out=0x%x\n", cfg->mono_out_pin); |
3799 | if (cfg->dig_outs) | ||
3800 | snd_printd(" dig-out=0x%x/0x%x\n", | ||
3801 | cfg->dig_out_pins[0], cfg->dig_out_pins[1]); | ||
3513 | snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x," | 3802 | snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x," |
3514 | " cd=0x%x, aux=0x%x\n", | 3803 | " cd=0x%x, aux=0x%x\n", |
3515 | cfg->input_pins[AUTO_PIN_MIC], | 3804 | cfg->input_pins[AUTO_PIN_MIC], |
@@ -3518,6 +3807,8 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
3518 | cfg->input_pins[AUTO_PIN_FRONT_LINE], | 3807 | cfg->input_pins[AUTO_PIN_FRONT_LINE], |
3519 | cfg->input_pins[AUTO_PIN_CD], | 3808 | cfg->input_pins[AUTO_PIN_CD], |
3520 | cfg->input_pins[AUTO_PIN_AUX]); | 3809 | cfg->input_pins[AUTO_PIN_AUX]); |
3810 | if (cfg->dig_in_pin) | ||
3811 | snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin); | ||
3521 | 3812 | ||
3522 | return 0; | 3813 | return 0; |
3523 | } | 3814 | } |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 09a332ada0c6..2fdecf4b0eb6 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -739,6 +739,7 @@ struct hda_codec { | |||
739 | hda_nid_t mfg; /* MFG node id */ | 739 | hda_nid_t mfg; /* MFG node id */ |
740 | 740 | ||
741 | /* ids */ | 741 | /* ids */ |
742 | u32 function_id; | ||
742 | u32 vendor_id; | 743 | u32 vendor_id; |
743 | u32 subsystem_id; | 744 | u32 subsystem_id; |
744 | u32 revision_id; | 745 | u32 revision_id; |
@@ -778,11 +779,14 @@ struct hda_codec { | |||
778 | unsigned short spdif_ctls; /* SPDIF control bits */ | 779 | unsigned short spdif_ctls; /* SPDIF control bits */ |
779 | unsigned int spdif_in_enable; /* SPDIF input enable? */ | 780 | unsigned int spdif_in_enable; /* SPDIF input enable? */ |
780 | hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */ | 781 | hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */ |
782 | struct snd_array init_pins; /* initial (BIOS) pin configurations */ | ||
783 | struct snd_array driver_pins; /* pin configs set by codec parser */ | ||
781 | 784 | ||
782 | #ifdef CONFIG_SND_HDA_HWDEP | 785 | #ifdef CONFIG_SND_HDA_HWDEP |
783 | struct snd_hwdep *hwdep; /* assigned hwdep device */ | 786 | struct snd_hwdep *hwdep; /* assigned hwdep device */ |
784 | struct snd_array init_verbs; /* additional init verbs */ | 787 | struct snd_array init_verbs; /* additional init verbs */ |
785 | struct snd_array hints; /* additional hints */ | 788 | struct snd_array hints; /* additional hints */ |
789 | struct snd_array user_pins; /* default pin configs to override */ | ||
786 | #endif | 790 | #endif |
787 | 791 | ||
788 | /* misc flags */ | 792 | /* misc flags */ |
@@ -790,6 +794,9 @@ struct hda_codec { | |||
790 | * status change | 794 | * status change |
791 | * (e.g. Realtek codecs) | 795 | * (e.g. Realtek codecs) |
792 | */ | 796 | */ |
797 | unsigned int pin_amp_workaround:1; /* pin out-amp takes index | ||
798 | * (e.g. Conexant codecs) | ||
799 | */ | ||
793 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 800 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
794 | unsigned int power_on :1; /* current (global) power-state */ | 801 | unsigned int power_on :1; /* current (global) power-state */ |
795 | unsigned int power_transition :1; /* power-state in transition */ | 802 | unsigned int power_transition :1; /* power-state in transition */ |
@@ -855,6 +862,18 @@ void snd_hda_codec_resume_cache(struct hda_codec *codec); | |||
855 | #define snd_hda_sequence_write_cache snd_hda_sequence_write | 862 | #define snd_hda_sequence_write_cache snd_hda_sequence_write |
856 | #endif | 863 | #endif |
857 | 864 | ||
865 | /* the struct for codec->pin_configs */ | ||
866 | struct hda_pincfg { | ||
867 | hda_nid_t nid; | ||
868 | unsigned int cfg; | ||
869 | }; | ||
870 | |||
871 | unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid); | ||
872 | int snd_hda_codec_set_pincfg(struct hda_codec *codec, hda_nid_t nid, | ||
873 | unsigned int cfg); | ||
874 | int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list, | ||
875 | hda_nid_t nid, unsigned int cfg); /* for hwdep */ | ||
876 | |||
858 | /* | 877 | /* |
859 | * Mixer | 878 | * Mixer |
860 | */ | 879 | */ |
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 65745e96dc70..1d5797a96682 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c | |||
@@ -144,9 +144,9 @@ static int add_new_node(struct hda_codec *codec, struct hda_gspec *spec, hda_nid | |||
144 | node->type = (node->wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; | 144 | node->type = (node->wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; |
145 | 145 | ||
146 | if (node->type == AC_WID_PIN) { | 146 | if (node->type == AC_WID_PIN) { |
147 | node->pin_caps = snd_hda_param_read(codec, node->nid, AC_PAR_PIN_CAP); | 147 | node->pin_caps = snd_hda_query_pin_caps(codec, node->nid); |
148 | node->pin_ctl = snd_hda_codec_read(codec, node->nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | 148 | node->pin_ctl = snd_hda_codec_read(codec, node->nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0); |
149 | node->def_cfg = snd_hda_codec_read(codec, node->nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); | 149 | node->def_cfg = snd_hda_codec_get_pincfg(codec, node->nid); |
150 | } | 150 | } |
151 | 151 | ||
152 | if (node->wid_caps & AC_WCAP_OUT_AMP) { | 152 | if (node->wid_caps & AC_WCAP_OUT_AMP) { |
diff --git a/sound/pci/hda/hda_hwdep.c b/sound/pci/hda/hda_hwdep.c index 4ae51dcb81af..1c57505c2874 100644 --- a/sound/pci/hda/hda_hwdep.c +++ b/sound/pci/hda/hda_hwdep.c | |||
@@ -30,6 +30,12 @@ | |||
30 | #include <sound/hda_hwdep.h> | 30 | #include <sound/hda_hwdep.h> |
31 | #include <sound/minors.h> | 31 | #include <sound/minors.h> |
32 | 32 | ||
33 | /* hint string pair */ | ||
34 | struct hda_hint { | ||
35 | const char *key; | ||
36 | const char *val; /* contained in the same alloc as key */ | ||
37 | }; | ||
38 | |||
33 | /* | 39 | /* |
34 | * write/read an out-of-bound verb | 40 | * write/read an out-of-bound verb |
35 | */ | 41 | */ |
@@ -99,16 +105,17 @@ static int hda_hwdep_open(struct snd_hwdep *hw, struct file *file) | |||
99 | 105 | ||
100 | static void clear_hwdep_elements(struct hda_codec *codec) | 106 | static void clear_hwdep_elements(struct hda_codec *codec) |
101 | { | 107 | { |
102 | char **head; | ||
103 | int i; | 108 | int i; |
104 | 109 | ||
105 | /* clear init verbs */ | 110 | /* clear init verbs */ |
106 | snd_array_free(&codec->init_verbs); | 111 | snd_array_free(&codec->init_verbs); |
107 | /* clear hints */ | 112 | /* clear hints */ |
108 | head = codec->hints.list; | 113 | for (i = 0; i < codec->hints.used; i++) { |
109 | for (i = 0; i < codec->hints.used; i++, head++) | 114 | struct hda_hint *hint = snd_array_elem(&codec->hints, i); |
110 | kfree(*head); | 115 | kfree(hint->key); /* we don't need to free hint->val */ |
116 | } | ||
111 | snd_array_free(&codec->hints); | 117 | snd_array_free(&codec->hints); |
118 | snd_array_free(&codec->user_pins); | ||
112 | } | 119 | } |
113 | 120 | ||
114 | static void hwdep_free(struct snd_hwdep *hwdep) | 121 | static void hwdep_free(struct snd_hwdep *hwdep) |
@@ -140,7 +147,8 @@ int /*__devinit*/ snd_hda_create_hwdep(struct hda_codec *codec) | |||
140 | #endif | 147 | #endif |
141 | 148 | ||
142 | snd_array_init(&codec->init_verbs, sizeof(struct hda_verb), 32); | 149 | snd_array_init(&codec->init_verbs, sizeof(struct hda_verb), 32); |
143 | snd_array_init(&codec->hints, sizeof(char *), 32); | 150 | snd_array_init(&codec->hints, sizeof(struct hda_hint), 32); |
151 | snd_array_init(&codec->user_pins, sizeof(struct hda_pincfg), 16); | ||
144 | 152 | ||
145 | return 0; | 153 | return 0; |
146 | } | 154 | } |
@@ -153,7 +161,13 @@ int /*__devinit*/ snd_hda_create_hwdep(struct hda_codec *codec) | |||
153 | 161 | ||
154 | static int clear_codec(struct hda_codec *codec) | 162 | static int clear_codec(struct hda_codec *codec) |
155 | { | 163 | { |
156 | snd_hda_codec_reset(codec); | 164 | int err; |
165 | |||
166 | err = snd_hda_codec_reset(codec); | ||
167 | if (err < 0) { | ||
168 | snd_printk(KERN_ERR "The codec is being used, can't free.\n"); | ||
169 | return err; | ||
170 | } | ||
157 | clear_hwdep_elements(codec); | 171 | clear_hwdep_elements(codec); |
158 | return 0; | 172 | return 0; |
159 | } | 173 | } |
@@ -162,20 +176,29 @@ static int reconfig_codec(struct hda_codec *codec) | |||
162 | { | 176 | { |
163 | int err; | 177 | int err; |
164 | 178 | ||
179 | snd_hda_power_up(codec); | ||
165 | snd_printk(KERN_INFO "hda-codec: reconfiguring\n"); | 180 | snd_printk(KERN_INFO "hda-codec: reconfiguring\n"); |
166 | snd_hda_codec_reset(codec); | 181 | err = snd_hda_codec_reset(codec); |
182 | if (err < 0) { | ||
183 | snd_printk(KERN_ERR | ||
184 | "The codec is being used, can't reconfigure.\n"); | ||
185 | goto error; | ||
186 | } | ||
167 | err = snd_hda_codec_configure(codec); | 187 | err = snd_hda_codec_configure(codec); |
168 | if (err < 0) | 188 | if (err < 0) |
169 | return err; | 189 | goto error; |
170 | /* rebuild PCMs */ | 190 | /* rebuild PCMs */ |
171 | err = snd_hda_codec_build_pcms(codec); | 191 | err = snd_hda_codec_build_pcms(codec); |
172 | if (err < 0) | 192 | if (err < 0) |
173 | return err; | 193 | goto error; |
174 | /* rebuild mixers */ | 194 | /* rebuild mixers */ |
175 | err = snd_hda_codec_build_controls(codec); | 195 | err = snd_hda_codec_build_controls(codec); |
176 | if (err < 0) | 196 | if (err < 0) |
177 | return err; | 197 | goto error; |
178 | return snd_card_register(codec->bus->card); | 198 | err = snd_card_register(codec->bus->card); |
199 | error: | ||
200 | snd_hda_power_down(codec); | ||
201 | return err; | ||
179 | } | 202 | } |
180 | 203 | ||
181 | /* | 204 | /* |
@@ -271,6 +294,22 @@ static ssize_t type##_store(struct device *dev, \ | |||
271 | CODEC_ACTION_STORE(reconfig); | 294 | CODEC_ACTION_STORE(reconfig); |
272 | CODEC_ACTION_STORE(clear); | 295 | CODEC_ACTION_STORE(clear); |
273 | 296 | ||
297 | static ssize_t init_verbs_show(struct device *dev, | ||
298 | struct device_attribute *attr, | ||
299 | char *buf) | ||
300 | { | ||
301 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); | ||
302 | struct hda_codec *codec = hwdep->private_data; | ||
303 | int i, len = 0; | ||
304 | for (i = 0; i < codec->init_verbs.used; i++) { | ||
305 | struct hda_verb *v = snd_array_elem(&codec->init_verbs, i); | ||
306 | len += snprintf(buf + len, PAGE_SIZE - len, | ||
307 | "0x%02x 0x%03x 0x%04x\n", | ||
308 | v->nid, v->verb, v->param); | ||
309 | } | ||
310 | return len; | ||
311 | } | ||
312 | |||
274 | static ssize_t init_verbs_store(struct device *dev, | 313 | static ssize_t init_verbs_store(struct device *dev, |
275 | struct device_attribute *attr, | 314 | struct device_attribute *attr, |
276 | const char *buf, size_t count) | 315 | const char *buf, size_t count) |
@@ -293,26 +332,157 @@ static ssize_t init_verbs_store(struct device *dev, | |||
293 | return count; | 332 | return count; |
294 | } | 333 | } |
295 | 334 | ||
335 | static ssize_t hints_show(struct device *dev, | ||
336 | struct device_attribute *attr, | ||
337 | char *buf) | ||
338 | { | ||
339 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); | ||
340 | struct hda_codec *codec = hwdep->private_data; | ||
341 | int i, len = 0; | ||
342 | for (i = 0; i < codec->hints.used; i++) { | ||
343 | struct hda_hint *hint = snd_array_elem(&codec->hints, i); | ||
344 | len += snprintf(buf + len, PAGE_SIZE - len, | ||
345 | "%s = %s\n", hint->key, hint->val); | ||
346 | } | ||
347 | return len; | ||
348 | } | ||
349 | |||
350 | static struct hda_hint *get_hint(struct hda_codec *codec, const char *key) | ||
351 | { | ||
352 | int i; | ||
353 | |||
354 | for (i = 0; i < codec->hints.used; i++) { | ||
355 | struct hda_hint *hint = snd_array_elem(&codec->hints, i); | ||
356 | if (!strcmp(hint->key, key)) | ||
357 | return hint; | ||
358 | } | ||
359 | return NULL; | ||
360 | } | ||
361 | |||
362 | static void remove_trail_spaces(char *str) | ||
363 | { | ||
364 | char *p; | ||
365 | if (!*str) | ||
366 | return; | ||
367 | p = str + strlen(str) - 1; | ||
368 | for (; isspace(*p); p--) { | ||
369 | *p = 0; | ||
370 | if (p == str) | ||
371 | return; | ||
372 | } | ||
373 | } | ||
374 | |||
375 | #define MAX_HINTS 1024 | ||
376 | |||
296 | static ssize_t hints_store(struct device *dev, | 377 | static ssize_t hints_store(struct device *dev, |
297 | struct device_attribute *attr, | 378 | struct device_attribute *attr, |
298 | const char *buf, size_t count) | 379 | const char *buf, size_t count) |
299 | { | 380 | { |
300 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); | 381 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); |
301 | struct hda_codec *codec = hwdep->private_data; | 382 | struct hda_codec *codec = hwdep->private_data; |
302 | char *p; | 383 | char *key, *val; |
303 | char **hint; | 384 | struct hda_hint *hint; |
304 | 385 | ||
305 | if (!*buf || isspace(*buf) || *buf == '#' || *buf == '\n') | 386 | while (isspace(*buf)) |
387 | buf++; | ||
388 | if (!*buf || *buf == '#' || *buf == '\n') | ||
306 | return count; | 389 | return count; |
307 | p = kstrndup_noeol(buf, 1024); | 390 | if (*buf == '=') |
308 | if (!p) | 391 | return -EINVAL; |
392 | key = kstrndup_noeol(buf, 1024); | ||
393 | if (!key) | ||
309 | return -ENOMEM; | 394 | return -ENOMEM; |
310 | hint = snd_array_new(&codec->hints); | 395 | /* extract key and val */ |
396 | val = strchr(key, '='); | ||
397 | if (!val) { | ||
398 | kfree(key); | ||
399 | return -EINVAL; | ||
400 | } | ||
401 | *val++ = 0; | ||
402 | while (isspace(*val)) | ||
403 | val++; | ||
404 | remove_trail_spaces(key); | ||
405 | remove_trail_spaces(val); | ||
406 | hint = get_hint(codec, key); | ||
407 | if (hint) { | ||
408 | /* replace */ | ||
409 | kfree(hint->key); | ||
410 | hint->key = key; | ||
411 | hint->val = val; | ||
412 | return count; | ||
413 | } | ||
414 | /* allocate a new hint entry */ | ||
415 | if (codec->hints.used >= MAX_HINTS) | ||
416 | hint = NULL; | ||
417 | else | ||
418 | hint = snd_array_new(&codec->hints); | ||
311 | if (!hint) { | 419 | if (!hint) { |
312 | kfree(p); | 420 | kfree(key); |
313 | return -ENOMEM; | 421 | return -ENOMEM; |
314 | } | 422 | } |
315 | *hint = p; | 423 | hint->key = key; |
424 | hint->val = val; | ||
425 | return count; | ||
426 | } | ||
427 | |||
428 | static ssize_t pin_configs_show(struct hda_codec *codec, | ||
429 | struct snd_array *list, | ||
430 | char *buf) | ||
431 | { | ||
432 | int i, len = 0; | ||
433 | for (i = 0; i < list->used; i++) { | ||
434 | struct hda_pincfg *pin = snd_array_elem(list, i); | ||
435 | len += sprintf(buf + len, "0x%02x 0x%08x\n", | ||
436 | pin->nid, pin->cfg); | ||
437 | } | ||
438 | return len; | ||
439 | } | ||
440 | |||
441 | static ssize_t init_pin_configs_show(struct device *dev, | ||
442 | struct device_attribute *attr, | ||
443 | char *buf) | ||
444 | { | ||
445 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); | ||
446 | struct hda_codec *codec = hwdep->private_data; | ||
447 | return pin_configs_show(codec, &codec->init_pins, buf); | ||
448 | } | ||
449 | |||
450 | static ssize_t user_pin_configs_show(struct device *dev, | ||
451 | struct device_attribute *attr, | ||
452 | char *buf) | ||
453 | { | ||
454 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); | ||
455 | struct hda_codec *codec = hwdep->private_data; | ||
456 | return pin_configs_show(codec, &codec->user_pins, buf); | ||
457 | } | ||
458 | |||
459 | static ssize_t driver_pin_configs_show(struct device *dev, | ||
460 | struct device_attribute *attr, | ||
461 | char *buf) | ||
462 | { | ||
463 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); | ||
464 | struct hda_codec *codec = hwdep->private_data; | ||
465 | return pin_configs_show(codec, &codec->driver_pins, buf); | ||
466 | } | ||
467 | |||
468 | #define MAX_PIN_CONFIGS 32 | ||
469 | |||
470 | static ssize_t user_pin_configs_store(struct device *dev, | ||
471 | struct device_attribute *attr, | ||
472 | const char *buf, size_t count) | ||
473 | { | ||
474 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); | ||
475 | struct hda_codec *codec = hwdep->private_data; | ||
476 | int nid, cfg; | ||
477 | int err; | ||
478 | |||
479 | if (sscanf(buf, "%i %i", &nid, &cfg) != 2) | ||
480 | return -EINVAL; | ||
481 | if (!nid) | ||
482 | return -EINVAL; | ||
483 | err = snd_hda_add_pincfg(codec, &codec->user_pins, nid, cfg); | ||
484 | if (err < 0) | ||
485 | return err; | ||
316 | return count; | 486 | return count; |
317 | } | 487 | } |
318 | 488 | ||
@@ -331,8 +501,11 @@ static struct device_attribute codec_attrs[] = { | |||
331 | CODEC_ATTR_RO(mfg), | 501 | CODEC_ATTR_RO(mfg), |
332 | CODEC_ATTR_RW(name), | 502 | CODEC_ATTR_RW(name), |
333 | CODEC_ATTR_RW(modelname), | 503 | CODEC_ATTR_RW(modelname), |
334 | CODEC_ATTR_WO(init_verbs), | 504 | CODEC_ATTR_RW(init_verbs), |
335 | CODEC_ATTR_WO(hints), | 505 | CODEC_ATTR_RW(hints), |
506 | CODEC_ATTR_RO(init_pin_configs), | ||
507 | CODEC_ATTR_RW(user_pin_configs), | ||
508 | CODEC_ATTR_RO(driver_pin_configs), | ||
336 | CODEC_ATTR_WO(reconfig), | 509 | CODEC_ATTR_WO(reconfig), |
337 | CODEC_ATTR_WO(clear), | 510 | CODEC_ATTR_WO(clear), |
338 | }; | 511 | }; |
@@ -351,4 +524,29 @@ int snd_hda_hwdep_add_sysfs(struct hda_codec *codec) | |||
351 | return 0; | 524 | return 0; |
352 | } | 525 | } |
353 | 526 | ||
527 | /* | ||
528 | * Look for hint string | ||
529 | */ | ||
530 | const char *snd_hda_get_hint(struct hda_codec *codec, const char *key) | ||
531 | { | ||
532 | struct hda_hint *hint = get_hint(codec, key); | ||
533 | return hint ? hint->val : NULL; | ||
534 | } | ||
535 | EXPORT_SYMBOL_HDA(snd_hda_get_hint); | ||
536 | |||
537 | int snd_hda_get_bool_hint(struct hda_codec *codec, const char *key) | ||
538 | { | ||
539 | const char *p = snd_hda_get_hint(codec, key); | ||
540 | if (!p || !*p) | ||
541 | return -ENOENT; | ||
542 | switch (toupper(*p)) { | ||
543 | case 'T': /* true */ | ||
544 | case 'Y': /* yes */ | ||
545 | case '1': | ||
546 | return 1; | ||
547 | } | ||
548 | return 0; | ||
549 | } | ||
550 | EXPORT_SYMBOL_HDA(snd_hda_get_bool_hint); | ||
551 | |||
354 | #endif /* CONFIG_SND_HDA_RECONFIG */ | 552 | #endif /* CONFIG_SND_HDA_RECONFIG */ |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index f3b5723c2859..30829ee920c3 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -381,6 +381,7 @@ struct azx { | |||
381 | 381 | ||
382 | /* HD codec */ | 382 | /* HD codec */ |
383 | unsigned short codec_mask; | 383 | unsigned short codec_mask; |
384 | int codec_probe_mask; /* copied from probe_mask option */ | ||
384 | struct hda_bus *bus; | 385 | struct hda_bus *bus; |
385 | 386 | ||
386 | /* CORB/RIRB */ | 387 | /* CORB/RIRB */ |
@@ -858,13 +859,18 @@ static void azx_stream_start(struct azx *chip, struct azx_dev *azx_dev) | |||
858 | SD_CTL_DMA_START | SD_INT_MASK); | 859 | SD_CTL_DMA_START | SD_INT_MASK); |
859 | } | 860 | } |
860 | 861 | ||
861 | /* stop a stream */ | 862 | /* stop DMA */ |
862 | static void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev) | 863 | static void azx_stream_clear(struct azx *chip, struct azx_dev *azx_dev) |
863 | { | 864 | { |
864 | /* stop DMA */ | ||
865 | azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) & | 865 | azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) & |
866 | ~(SD_CTL_DMA_START | SD_INT_MASK)); | 866 | ~(SD_CTL_DMA_START | SD_INT_MASK)); |
867 | azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK); /* to be sure */ | 867 | azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK); /* to be sure */ |
868 | } | ||
869 | |||
870 | /* stop a stream */ | ||
871 | static void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev) | ||
872 | { | ||
873 | azx_stream_clear(chip, azx_dev); | ||
868 | /* disable SIE */ | 874 | /* disable SIE */ |
869 | azx_writeb(chip, INTCTL, | 875 | azx_writeb(chip, INTCTL, |
870 | azx_readb(chip, INTCTL) & ~(1 << azx_dev->index)); | 876 | azx_readb(chip, INTCTL) & ~(1 << azx_dev->index)); |
@@ -1075,8 +1081,7 @@ static int azx_setup_periods(struct azx *chip, | |||
1075 | azx_sd_writel(azx_dev, SD_BDLPL, 0); | 1081 | azx_sd_writel(azx_dev, SD_BDLPL, 0); |
1076 | azx_sd_writel(azx_dev, SD_BDLPU, 0); | 1082 | azx_sd_writel(azx_dev, SD_BDLPU, 0); |
1077 | 1083 | ||
1078 | period_bytes = snd_pcm_lib_period_bytes(substream); | 1084 | period_bytes = azx_dev->period_bytes; |
1079 | azx_dev->period_bytes = period_bytes; | ||
1080 | periods = azx_dev->bufsize / period_bytes; | 1085 | periods = azx_dev->bufsize / period_bytes; |
1081 | 1086 | ||
1082 | /* program the initial BDL entries */ | 1087 | /* program the initial BDL entries */ |
@@ -1123,24 +1128,17 @@ static int azx_setup_periods(struct azx *chip, | |||
1123 | error: | 1128 | error: |
1124 | snd_printk(KERN_ERR "Too many BDL entries: buffer=%d, period=%d\n", | 1129 | snd_printk(KERN_ERR "Too many BDL entries: buffer=%d, period=%d\n", |
1125 | azx_dev->bufsize, period_bytes); | 1130 | azx_dev->bufsize, period_bytes); |
1126 | /* reset */ | ||
1127 | azx_sd_writel(azx_dev, SD_BDLPL, 0); | ||
1128 | azx_sd_writel(azx_dev, SD_BDLPU, 0); | ||
1129 | return -EINVAL; | 1131 | return -EINVAL; |
1130 | } | 1132 | } |
1131 | 1133 | ||
1132 | /* | 1134 | /* reset stream */ |
1133 | * set up the SD for streaming | 1135 | static void azx_stream_reset(struct azx *chip, struct azx_dev *azx_dev) |
1134 | */ | ||
1135 | static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) | ||
1136 | { | 1136 | { |
1137 | unsigned char val; | 1137 | unsigned char val; |
1138 | int timeout; | 1138 | int timeout; |
1139 | 1139 | ||
1140 | /* make sure the run bit is zero for SD */ | 1140 | azx_stream_clear(chip, azx_dev); |
1141 | azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) & | 1141 | |
1142 | ~SD_CTL_DMA_START); | ||
1143 | /* reset stream */ | ||
1144 | azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) | | 1142 | azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) | |
1145 | SD_CTL_STREAM_RESET); | 1143 | SD_CTL_STREAM_RESET); |
1146 | udelay(3); | 1144 | udelay(3); |
@@ -1157,7 +1155,15 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) | |||
1157 | while (((val = azx_sd_readb(azx_dev, SD_CTL)) & SD_CTL_STREAM_RESET) && | 1155 | while (((val = azx_sd_readb(azx_dev, SD_CTL)) & SD_CTL_STREAM_RESET) && |
1158 | --timeout) | 1156 | --timeout) |
1159 | ; | 1157 | ; |
1158 | } | ||
1160 | 1159 | ||
1160 | /* | ||
1161 | * set up the SD for streaming | ||
1162 | */ | ||
1163 | static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) | ||
1164 | { | ||
1165 | /* make sure the run bit is zero for SD */ | ||
1166 | azx_stream_clear(chip, azx_dev); | ||
1161 | /* program the stream_tag */ | 1167 | /* program the stream_tag */ |
1162 | azx_sd_writel(azx_dev, SD_CTL, | 1168 | azx_sd_writel(azx_dev, SD_CTL, |
1163 | (azx_sd_readl(azx_dev, SD_CTL) & ~SD_CTL_STREAM_TAG_MASK)| | 1169 | (azx_sd_readl(azx_dev, SD_CTL) & ~SD_CTL_STREAM_TAG_MASK)| |
@@ -1228,7 +1234,6 @@ static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] __devinitdata = { | |||
1228 | }; | 1234 | }; |
1229 | 1235 | ||
1230 | static int __devinit azx_codec_create(struct azx *chip, const char *model, | 1236 | static int __devinit azx_codec_create(struct azx *chip, const char *model, |
1231 | unsigned int codec_probe_mask, | ||
1232 | int no_init) | 1237 | int no_init) |
1233 | { | 1238 | { |
1234 | struct hda_bus_template bus_temp; | 1239 | struct hda_bus_template bus_temp; |
@@ -1261,7 +1266,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model, | |||
1261 | 1266 | ||
1262 | /* First try to probe all given codec slots */ | 1267 | /* First try to probe all given codec slots */ |
1263 | for (c = 0; c < max_slots; c++) { | 1268 | for (c = 0; c < max_slots; c++) { |
1264 | if ((chip->codec_mask & (1 << c)) & codec_probe_mask) { | 1269 | if ((chip->codec_mask & (1 << c)) & chip->codec_probe_mask) { |
1265 | if (probe_codec(chip, c) < 0) { | 1270 | if (probe_codec(chip, c) < 0) { |
1266 | /* Some BIOSen give you wrong codec addresses | 1271 | /* Some BIOSen give you wrong codec addresses |
1267 | * that don't exist | 1272 | * that don't exist |
@@ -1285,7 +1290,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model, | |||
1285 | 1290 | ||
1286 | /* Then create codec instances */ | 1291 | /* Then create codec instances */ |
1287 | for (c = 0; c < max_slots; c++) { | 1292 | for (c = 0; c < max_slots; c++) { |
1288 | if ((chip->codec_mask & (1 << c)) & codec_probe_mask) { | 1293 | if ((chip->codec_mask & (1 << c)) & chip->codec_probe_mask) { |
1289 | struct hda_codec *codec; | 1294 | struct hda_codec *codec; |
1290 | err = snd_hda_codec_new(chip->bus, c, !no_init, &codec); | 1295 | err = snd_hda_codec_new(chip->bus, c, !no_init, &codec); |
1291 | if (err < 0) | 1296 | if (err < 0) |
@@ -1403,6 +1408,8 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) | |||
1403 | runtime->private_data = azx_dev; | 1408 | runtime->private_data = azx_dev; |
1404 | snd_pcm_set_sync(substream); | 1409 | snd_pcm_set_sync(substream); |
1405 | mutex_unlock(&chip->open_mutex); | 1410 | mutex_unlock(&chip->open_mutex); |
1411 | |||
1412 | azx_stream_reset(chip, azx_dev); | ||
1406 | return 0; | 1413 | return 0; |
1407 | } | 1414 | } |
1408 | 1415 | ||
@@ -1429,6 +1436,11 @@ static int azx_pcm_close(struct snd_pcm_substream *substream) | |||
1429 | static int azx_pcm_hw_params(struct snd_pcm_substream *substream, | 1436 | static int azx_pcm_hw_params(struct snd_pcm_substream *substream, |
1430 | struct snd_pcm_hw_params *hw_params) | 1437 | struct snd_pcm_hw_params *hw_params) |
1431 | { | 1438 | { |
1439 | struct azx_dev *azx_dev = get_azx_dev(substream); | ||
1440 | |||
1441 | azx_dev->bufsize = 0; | ||
1442 | azx_dev->period_bytes = 0; | ||
1443 | azx_dev->format_val = 0; | ||
1432 | return snd_pcm_lib_malloc_pages(substream, | 1444 | return snd_pcm_lib_malloc_pages(substream, |
1433 | params_buffer_bytes(hw_params)); | 1445 | params_buffer_bytes(hw_params)); |
1434 | } | 1446 | } |
@@ -1443,6 +1455,9 @@ static int azx_pcm_hw_free(struct snd_pcm_substream *substream) | |||
1443 | azx_sd_writel(azx_dev, SD_BDLPL, 0); | 1455 | azx_sd_writel(azx_dev, SD_BDLPL, 0); |
1444 | azx_sd_writel(azx_dev, SD_BDLPU, 0); | 1456 | azx_sd_writel(azx_dev, SD_BDLPU, 0); |
1445 | azx_sd_writel(azx_dev, SD_CTL, 0); | 1457 | azx_sd_writel(azx_dev, SD_CTL, 0); |
1458 | azx_dev->bufsize = 0; | ||
1459 | azx_dev->period_bytes = 0; | ||
1460 | azx_dev->format_val = 0; | ||
1446 | 1461 | ||
1447 | hinfo->ops.cleanup(hinfo, apcm->codec, substream); | 1462 | hinfo->ops.cleanup(hinfo, apcm->codec, substream); |
1448 | 1463 | ||
@@ -1456,23 +1471,37 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) | |||
1456 | struct azx_dev *azx_dev = get_azx_dev(substream); | 1471 | struct azx_dev *azx_dev = get_azx_dev(substream); |
1457 | struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; | 1472 | struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; |
1458 | struct snd_pcm_runtime *runtime = substream->runtime; | 1473 | struct snd_pcm_runtime *runtime = substream->runtime; |
1474 | unsigned int bufsize, period_bytes, format_val; | ||
1475 | int err; | ||
1459 | 1476 | ||
1460 | azx_dev->bufsize = snd_pcm_lib_buffer_bytes(substream); | 1477 | format_val = snd_hda_calc_stream_format(runtime->rate, |
1461 | azx_dev->format_val = snd_hda_calc_stream_format(runtime->rate, | 1478 | runtime->channels, |
1462 | runtime->channels, | 1479 | runtime->format, |
1463 | runtime->format, | 1480 | hinfo->maxbps); |
1464 | hinfo->maxbps); | 1481 | if (!format_val) { |
1465 | if (!azx_dev->format_val) { | ||
1466 | snd_printk(KERN_ERR SFX | 1482 | snd_printk(KERN_ERR SFX |
1467 | "invalid format_val, rate=%d, ch=%d, format=%d\n", | 1483 | "invalid format_val, rate=%d, ch=%d, format=%d\n", |
1468 | runtime->rate, runtime->channels, runtime->format); | 1484 | runtime->rate, runtime->channels, runtime->format); |
1469 | return -EINVAL; | 1485 | return -EINVAL; |
1470 | } | 1486 | } |
1471 | 1487 | ||
1488 | bufsize = snd_pcm_lib_buffer_bytes(substream); | ||
1489 | period_bytes = snd_pcm_lib_period_bytes(substream); | ||
1490 | |||
1472 | snd_printdd("azx_pcm_prepare: bufsize=0x%x, format=0x%x\n", | 1491 | snd_printdd("azx_pcm_prepare: bufsize=0x%x, format=0x%x\n", |
1473 | azx_dev->bufsize, azx_dev->format_val); | 1492 | bufsize, format_val); |
1474 | if (azx_setup_periods(chip, substream, azx_dev) < 0) | 1493 | |
1475 | return -EINVAL; | 1494 | if (bufsize != azx_dev->bufsize || |
1495 | period_bytes != azx_dev->period_bytes || | ||
1496 | format_val != azx_dev->format_val) { | ||
1497 | azx_dev->bufsize = bufsize; | ||
1498 | azx_dev->period_bytes = period_bytes; | ||
1499 | azx_dev->format_val = format_val; | ||
1500 | err = azx_setup_periods(chip, substream, azx_dev); | ||
1501 | if (err < 0) | ||
1502 | return err; | ||
1503 | } | ||
1504 | |||
1476 | azx_setup_controller(chip, azx_dev); | 1505 | azx_setup_controller(chip, azx_dev); |
1477 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 1506 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
1478 | azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1; | 1507 | azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1; |
@@ -2100,25 +2129,36 @@ static struct snd_pci_quirk probe_mask_list[] __devinitdata = { | |||
2100 | SND_PCI_QUIRK(0x1028, 0x20ac, "Dell Studio Desktop", 0x01), | 2129 | SND_PCI_QUIRK(0x1028, 0x20ac, "Dell Studio Desktop", 0x01), |
2101 | /* including bogus ALC268 in slot#2 that conflicts with ALC888 */ | 2130 | /* including bogus ALC268 in slot#2 that conflicts with ALC888 */ |
2102 | SND_PCI_QUIRK(0x17c0, 0x4085, "Medion MD96630", 0x01), | 2131 | SND_PCI_QUIRK(0x17c0, 0x4085, "Medion MD96630", 0x01), |
2103 | /* conflict of ALC268 in slot#3 (digital I/O); a temporary fix */ | 2132 | /* forced codec slots */ |
2104 | SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba laptop", 0x03), | 2133 | SND_PCI_QUIRK(0x1046, 0x1262, "ASUS W5F", 0x103), |
2105 | {} | 2134 | {} |
2106 | }; | 2135 | }; |
2107 | 2136 | ||
2137 | #define AZX_FORCE_CODEC_MASK 0x100 | ||
2138 | |||
2108 | static void __devinit check_probe_mask(struct azx *chip, int dev) | 2139 | static void __devinit check_probe_mask(struct azx *chip, int dev) |
2109 | { | 2140 | { |
2110 | const struct snd_pci_quirk *q; | 2141 | const struct snd_pci_quirk *q; |
2111 | 2142 | ||
2112 | if (probe_mask[dev] == -1) { | 2143 | chip->codec_probe_mask = probe_mask[dev]; |
2144 | if (chip->codec_probe_mask == -1) { | ||
2113 | q = snd_pci_quirk_lookup(chip->pci, probe_mask_list); | 2145 | q = snd_pci_quirk_lookup(chip->pci, probe_mask_list); |
2114 | if (q) { | 2146 | if (q) { |
2115 | printk(KERN_INFO | 2147 | printk(KERN_INFO |
2116 | "hda_intel: probe_mask set to 0x%x " | 2148 | "hda_intel: probe_mask set to 0x%x " |
2117 | "for device %04x:%04x\n", | 2149 | "for device %04x:%04x\n", |
2118 | q->value, q->subvendor, q->subdevice); | 2150 | q->value, q->subvendor, q->subdevice); |
2119 | probe_mask[dev] = q->value; | 2151 | chip->codec_probe_mask = q->value; |
2120 | } | 2152 | } |
2121 | } | 2153 | } |
2154 | |||
2155 | /* check forced option */ | ||
2156 | if (chip->codec_probe_mask != -1 && | ||
2157 | (chip->codec_probe_mask & AZX_FORCE_CODEC_MASK)) { | ||
2158 | chip->codec_mask = chip->codec_probe_mask & 0xff; | ||
2159 | printk(KERN_INFO "hda_intel: codec_mask forced to 0x%x\n", | ||
2160 | chip->codec_mask); | ||
2161 | } | ||
2122 | } | 2162 | } |
2123 | 2163 | ||
2124 | 2164 | ||
@@ -2347,10 +2387,10 @@ static int __devinit azx_probe(struct pci_dev *pci, | |||
2347 | return -ENOENT; | 2387 | return -ENOENT; |
2348 | } | 2388 | } |
2349 | 2389 | ||
2350 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 2390 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); |
2351 | if (!card) { | 2391 | if (err < 0) { |
2352 | snd_printk(KERN_ERR SFX "Error creating card!\n"); | 2392 | snd_printk(KERN_ERR SFX "Error creating card!\n"); |
2353 | return -ENOMEM; | 2393 | return err; |
2354 | } | 2394 | } |
2355 | 2395 | ||
2356 | err = azx_create(card, pci, dev, pci_id->driver_data, &chip); | 2396 | err = azx_create(card, pci, dev, pci_id->driver_data, &chip); |
@@ -2359,8 +2399,7 @@ static int __devinit azx_probe(struct pci_dev *pci, | |||
2359 | card->private_data = chip; | 2399 | card->private_data = chip; |
2360 | 2400 | ||
2361 | /* create codec instances */ | 2401 | /* create codec instances */ |
2362 | err = azx_codec_create(chip, model[dev], probe_mask[dev], | 2402 | err = azx_codec_create(chip, model[dev], probe_only[dev]); |
2363 | probe_only[dev]); | ||
2364 | if (err < 0) | 2403 | if (err < 0) |
2365 | goto out_free; | 2404 | goto out_free; |
2366 | 2405 | ||
@@ -2457,10 +2496,10 @@ static struct pci_device_id azx_ids[] = { | |||
2457 | { PCI_DEVICE(0x10de, 0x0ac1), .driver_data = AZX_DRIVER_NVIDIA }, | 2496 | { PCI_DEVICE(0x10de, 0x0ac1), .driver_data = AZX_DRIVER_NVIDIA }, |
2458 | { PCI_DEVICE(0x10de, 0x0ac2), .driver_data = AZX_DRIVER_NVIDIA }, | 2497 | { PCI_DEVICE(0x10de, 0x0ac2), .driver_data = AZX_DRIVER_NVIDIA }, |
2459 | { PCI_DEVICE(0x10de, 0x0ac3), .driver_data = AZX_DRIVER_NVIDIA }, | 2498 | { PCI_DEVICE(0x10de, 0x0ac3), .driver_data = AZX_DRIVER_NVIDIA }, |
2460 | { PCI_DEVICE(0x10de, 0x0bd4), .driver_data = AZX_DRIVER_NVIDIA }, | 2499 | { PCI_DEVICE(0x10de, 0x0d94), .driver_data = AZX_DRIVER_NVIDIA }, |
2461 | { PCI_DEVICE(0x10de, 0x0bd5), .driver_data = AZX_DRIVER_NVIDIA }, | 2500 | { PCI_DEVICE(0x10de, 0x0d95), .driver_data = AZX_DRIVER_NVIDIA }, |
2462 | { PCI_DEVICE(0x10de, 0x0bd6), .driver_data = AZX_DRIVER_NVIDIA }, | 2501 | { PCI_DEVICE(0x10de, 0x0d96), .driver_data = AZX_DRIVER_NVIDIA }, |
2463 | { PCI_DEVICE(0x10de, 0x0bd7), .driver_data = AZX_DRIVER_NVIDIA }, | 2502 | { PCI_DEVICE(0x10de, 0x0d97), .driver_data = AZX_DRIVER_NVIDIA }, |
2464 | /* Teradici */ | 2503 | /* Teradici */ |
2465 | { PCI_DEVICE(0x6549, 0x1200), .driver_data = AZX_DRIVER_TERA }, | 2504 | { PCI_DEVICE(0x6549, 0x1200), .driver_data = AZX_DRIVER_TERA }, |
2466 | /* AMD Generic, PCI class code and Vendor ID for HD Audio */ | 2505 | /* AMD Generic, PCI class code and Vendor ID for HD Audio */ |
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 44f189cb97ae..83349013b4df 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -26,8 +26,10 @@ | |||
26 | /* | 26 | /* |
27 | * for mixer controls | 27 | * for mixer controls |
28 | */ | 28 | */ |
29 | #define HDA_COMPOSE_AMP_VAL_OFS(nid,chs,idx,dir,ofs) \ | ||
30 | ((nid) | ((chs)<<16) | ((dir)<<18) | ((idx)<<19) | ((ofs)<<23)) | ||
29 | #define HDA_COMPOSE_AMP_VAL(nid,chs,idx,dir) \ | 31 | #define HDA_COMPOSE_AMP_VAL(nid,chs,idx,dir) \ |
30 | ((nid) | ((chs)<<16) | ((dir)<<18) | ((idx)<<19)) | 32 | HDA_COMPOSE_AMP_VAL_OFS(nid, chs, idx, dir, 0) |
31 | /* mono volume with index (index=0,1,...) (channel=1,2) */ | 33 | /* mono volume with index (index=0,1,...) (channel=1,2) */ |
32 | #define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ | 34 | #define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ |
33 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ | 35 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ |
@@ -96,7 +98,7 @@ struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, | |||
96 | const char *name); | 98 | const char *name); |
97 | int snd_hda_add_vmaster(struct hda_codec *codec, char *name, | 99 | int snd_hda_add_vmaster(struct hda_codec *codec, char *name, |
98 | unsigned int *tlv, const char **slaves); | 100 | unsigned int *tlv, const char **slaves); |
99 | void snd_hda_codec_reset(struct hda_codec *codec); | 101 | int snd_hda_codec_reset(struct hda_codec *codec); |
100 | int snd_hda_codec_configure(struct hda_codec *codec); | 102 | int snd_hda_codec_configure(struct hda_codec *codec); |
101 | 103 | ||
102 | /* amp value bits */ | 104 | /* amp value bits */ |
@@ -134,7 +136,7 @@ extern struct hda_ctl_ops snd_hda_bind_sw; /* for bind-switch */ | |||
134 | 136 | ||
135 | struct hda_bind_ctls { | 137 | struct hda_bind_ctls { |
136 | struct hda_ctl_ops *ops; | 138 | struct hda_ctl_ops *ops; |
137 | long values[]; | 139 | unsigned long values[]; |
138 | }; | 140 | }; |
139 | 141 | ||
140 | int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol, | 142 | int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol, |
@@ -227,6 +229,7 @@ struct hda_multi_out { | |||
227 | hda_nid_t hp_nid; /* optional DAC for HP, 0 when not exists */ | 229 | hda_nid_t hp_nid; /* optional DAC for HP, 0 when not exists */ |
228 | hda_nid_t extra_out_nid[3]; /* optional DACs, 0 when not exists */ | 230 | hda_nid_t extra_out_nid[3]; /* optional DACs, 0 when not exists */ |
229 | hda_nid_t dig_out_nid; /* digital out audio widget */ | 231 | hda_nid_t dig_out_nid; /* digital out audio widget */ |
232 | hda_nid_t *slave_dig_outs; | ||
230 | int max_channels; /* currently supported analog channels */ | 233 | int max_channels; /* currently supported analog channels */ |
231 | int dig_out_used; /* current usage of digital out (HDA_DIG_XXX) */ | 234 | int dig_out_used; /* current usage of digital out (HDA_DIG_XXX) */ |
232 | int no_share_stream; /* don't share a stream with multiple pins */ | 235 | int no_share_stream; /* don't share a stream with multiple pins */ |
@@ -354,9 +357,12 @@ struct auto_pin_cfg { | |||
354 | int line_out_type; /* AUTO_PIN_XXX_OUT */ | 357 | int line_out_type; /* AUTO_PIN_XXX_OUT */ |
355 | hda_nid_t hp_pins[AUTO_CFG_MAX_OUTS]; | 358 | hda_nid_t hp_pins[AUTO_CFG_MAX_OUTS]; |
356 | hda_nid_t input_pins[AUTO_PIN_LAST]; | 359 | hda_nid_t input_pins[AUTO_PIN_LAST]; |
357 | hda_nid_t dig_out_pin; | 360 | int dig_outs; |
361 | hda_nid_t dig_out_pins[2]; | ||
358 | hda_nid_t dig_in_pin; | 362 | hda_nid_t dig_in_pin; |
359 | hda_nid_t mono_out_pin; | 363 | hda_nid_t mono_out_pin; |
364 | int dig_out_type[2]; /* HDA_PCM_TYPE_XXX */ | ||
365 | int dig_in_type; /* HDA_PCM_TYPE_XXX */ | ||
360 | }; | 366 | }; |
361 | 367 | ||
362 | #define get_defcfg_connect(cfg) \ | 368 | #define get_defcfg_connect(cfg) \ |
@@ -405,6 +411,7 @@ static inline u32 get_wcaps(struct hda_codec *codec, hda_nid_t nid) | |||
405 | u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction); | 411 | u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction); |
406 | int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, | 412 | int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, |
407 | unsigned int caps); | 413 | unsigned int caps); |
414 | u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid); | ||
408 | 415 | ||
409 | int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl); | 416 | int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl); |
410 | void snd_hda_ctls_clear(struct hda_codec *codec); | 417 | void snd_hda_ctls_clear(struct hda_codec *codec); |
@@ -427,6 +434,23 @@ static inline int snd_hda_hwdep_add_sysfs(struct hda_codec *codec) | |||
427 | } | 434 | } |
428 | #endif | 435 | #endif |
429 | 436 | ||
437 | #ifdef CONFIG_SND_HDA_RECONFIG | ||
438 | const char *snd_hda_get_hint(struct hda_codec *codec, const char *key); | ||
439 | int snd_hda_get_bool_hint(struct hda_codec *codec, const char *key); | ||
440 | #else | ||
441 | static inline | ||
442 | const char *snd_hda_get_hint(struct hda_codec *codec, const char *key) | ||
443 | { | ||
444 | return NULL; | ||
445 | } | ||
446 | |||
447 | static inline | ||
448 | int snd_hda_get_bool_hint(struct hda_codec *codec, const char *key) | ||
449 | { | ||
450 | return -ENOENT; | ||
451 | } | ||
452 | #endif | ||
453 | |||
430 | /* | 454 | /* |
431 | * power-management | 455 | * power-management |
432 | */ | 456 | */ |
@@ -458,6 +482,7 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec, | |||
458 | #define get_amp_channels(kc) (((kc)->private_value >> 16) & 0x3) | 482 | #define get_amp_channels(kc) (((kc)->private_value >> 16) & 0x3) |
459 | #define get_amp_direction(kc) (((kc)->private_value >> 18) & 0x1) | 483 | #define get_amp_direction(kc) (((kc)->private_value >> 18) & 0x1) |
460 | #define get_amp_index(kc) (((kc)->private_value >> 19) & 0xf) | 484 | #define get_amp_index(kc) (((kc)->private_value >> 19) & 0xf) |
485 | #define get_amp_offset(kc) (((kc)->private_value >> 23) & 0x3f) | ||
461 | 486 | ||
462 | /* | 487 | /* |
463 | * CEA Short Audio Descriptor data | 488 | * CEA Short Audio Descriptor data |
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index 144b85276d5a..93d7499350c6 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c | |||
@@ -399,8 +399,10 @@ static void print_conn_list(struct snd_info_buffer *buffer, | |||
399 | { | 399 | { |
400 | int c, curr = -1; | 400 | int c, curr = -1; |
401 | 401 | ||
402 | if (conn_len > 1 && wid_type != AC_WID_AUD_MIX && | 402 | if (conn_len > 1 && |
403 | wid_type != AC_WID_VOL_KNB) | 403 | wid_type != AC_WID_AUD_MIX && |
404 | wid_type != AC_WID_VOL_KNB && | ||
405 | wid_type != AC_WID_POWER) | ||
404 | curr = snd_hda_codec_read(codec, nid, 0, | 406 | curr = snd_hda_codec_read(codec, nid, 0, |
405 | AC_VERB_GET_CONNECT_SEL, 0); | 407 | AC_VERB_GET_CONNECT_SEL, 0); |
406 | snd_iprintf(buffer, " Connection: %d\n", conn_len); | 408 | snd_iprintf(buffer, " Connection: %d\n", conn_len); |
@@ -467,8 +469,9 @@ static void print_codec_info(struct snd_info_entry *entry, | |||
467 | snd_iprintf(buffer, "Codec: %s\n", | 469 | snd_iprintf(buffer, "Codec: %s\n", |
468 | codec->name ? codec->name : "Not Set"); | 470 | codec->name ? codec->name : "Not Set"); |
469 | snd_iprintf(buffer, "Address: %d\n", codec->addr); | 471 | snd_iprintf(buffer, "Address: %d\n", codec->addr); |
470 | snd_iprintf(buffer, "Vendor Id: 0x%x\n", codec->vendor_id); | 472 | snd_iprintf(buffer, "Function Id: 0x%x\n", codec->function_id); |
471 | snd_iprintf(buffer, "Subsystem Id: 0x%x\n", codec->subsystem_id); | 473 | snd_iprintf(buffer, "Vendor Id: 0x%08x\n", codec->vendor_id); |
474 | snd_iprintf(buffer, "Subsystem Id: 0x%08x\n", codec->subsystem_id); | ||
472 | snd_iprintf(buffer, "Revision Id: 0x%x\n", codec->revision_id); | 475 | snd_iprintf(buffer, "Revision Id: 0x%x\n", codec->revision_id); |
473 | 476 | ||
474 | if (codec->mfg) | 477 | if (codec->mfg) |
@@ -554,8 +557,14 @@ static void print_codec_info(struct snd_info_entry *entry, | |||
554 | snd_iprintf(buffer, " Amp-Out caps: "); | 557 | snd_iprintf(buffer, " Amp-Out caps: "); |
555 | print_amp_caps(buffer, codec, nid, HDA_OUTPUT); | 558 | print_amp_caps(buffer, codec, nid, HDA_OUTPUT); |
556 | snd_iprintf(buffer, " Amp-Out vals: "); | 559 | snd_iprintf(buffer, " Amp-Out vals: "); |
557 | print_amp_vals(buffer, codec, nid, HDA_OUTPUT, | 560 | if (wid_type == AC_WID_PIN && |
558 | wid_caps & AC_WCAP_STEREO, 1); | 561 | codec->pin_amp_workaround) |
562 | print_amp_vals(buffer, codec, nid, HDA_OUTPUT, | ||
563 | wid_caps & AC_WCAP_STEREO, | ||
564 | conn_len); | ||
565 | else | ||
566 | print_amp_vals(buffer, codec, nid, HDA_OUTPUT, | ||
567 | wid_caps & AC_WCAP_STEREO, 1); | ||
559 | } | 568 | } |
560 | 569 | ||
561 | switch (wid_type) { | 570 | switch (wid_type) { |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index e48612323aa0..5bb48ee8b6c6 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -27,11 +27,12 @@ | |||
27 | #include <sound/core.h> | 27 | #include <sound/core.h> |
28 | #include "hda_codec.h" | 28 | #include "hda_codec.h" |
29 | #include "hda_local.h" | 29 | #include "hda_local.h" |
30 | #include "hda_beep.h" | ||
30 | 31 | ||
31 | struct ad198x_spec { | 32 | struct ad198x_spec { |
32 | struct snd_kcontrol_new *mixers[5]; | 33 | struct snd_kcontrol_new *mixers[5]; |
33 | int num_mixers; | 34 | int num_mixers; |
34 | 35 | unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */ | |
35 | const struct hda_verb *init_verbs[5]; /* initialization verbs | 36 | const struct hda_verb *init_verbs[5]; /* initialization verbs |
36 | * don't forget NULL termination! | 37 | * don't forget NULL termination! |
37 | */ | 38 | */ |
@@ -154,6 +155,16 @@ static const char *ad_slave_sws[] = { | |||
154 | 155 | ||
155 | static void ad198x_free_kctls(struct hda_codec *codec); | 156 | static void ad198x_free_kctls(struct hda_codec *codec); |
156 | 157 | ||
158 | /* additional beep mixers; the actual parameters are overwritten at build */ | ||
159 | static struct snd_kcontrol_new ad_beep_mixer[] = { | ||
160 | HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_OUTPUT), | ||
161 | HDA_CODEC_MUTE("Beep Playback Switch", 0, 0, HDA_OUTPUT), | ||
162 | { } /* end */ | ||
163 | }; | ||
164 | |||
165 | #define set_beep_amp(spec, nid, idx, dir) \ | ||
166 | ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir)) /* mono */ | ||
167 | |||
157 | static int ad198x_build_controls(struct hda_codec *codec) | 168 | static int ad198x_build_controls(struct hda_codec *codec) |
158 | { | 169 | { |
159 | struct ad198x_spec *spec = codec->spec; | 170 | struct ad198x_spec *spec = codec->spec; |
@@ -181,6 +192,21 @@ static int ad198x_build_controls(struct hda_codec *codec) | |||
181 | return err; | 192 | return err; |
182 | } | 193 | } |
183 | 194 | ||
195 | /* create beep controls if needed */ | ||
196 | if (spec->beep_amp) { | ||
197 | struct snd_kcontrol_new *knew; | ||
198 | for (knew = ad_beep_mixer; knew->name; knew++) { | ||
199 | struct snd_kcontrol *kctl; | ||
200 | kctl = snd_ctl_new1(knew, codec); | ||
201 | if (!kctl) | ||
202 | return -ENOMEM; | ||
203 | kctl->private_value = spec->beep_amp; | ||
204 | err = snd_hda_ctl_add(codec, kctl); | ||
205 | if (err < 0) | ||
206 | return err; | ||
207 | } | ||
208 | } | ||
209 | |||
184 | /* if we have no master control, let's create it */ | 210 | /* if we have no master control, let's create it */ |
185 | if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { | 211 | if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { |
186 | unsigned int vmaster_tlv[4]; | 212 | unsigned int vmaster_tlv[4]; |
@@ -406,7 +432,8 @@ static void ad198x_free(struct hda_codec *codec) | |||
406 | return; | 432 | return; |
407 | 433 | ||
408 | ad198x_free_kctls(codec); | 434 | ad198x_free_kctls(codec); |
409 | kfree(codec->spec); | 435 | kfree(spec); |
436 | snd_hda_detach_beep_device(codec); | ||
410 | } | 437 | } |
411 | 438 | ||
412 | static struct hda_codec_ops ad198x_patch_ops = { | 439 | static struct hda_codec_ops ad198x_patch_ops = { |
@@ -545,8 +572,6 @@ static struct snd_kcontrol_new ad1986a_mixers[] = { | |||
545 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), | 572 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), |
546 | HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), | 573 | HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), |
547 | HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT), | 574 | HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT), |
548 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x18, 0x0, HDA_OUTPUT), | ||
549 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x18, 0x0, HDA_OUTPUT), | ||
550 | HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT), | 575 | HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT), |
551 | HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), | 576 | HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), |
552 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), | 577 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), |
@@ -610,8 +635,7 @@ static struct snd_kcontrol_new ad1986a_laptop_mixers[] = { | |||
610 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), | 635 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), |
611 | HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), | 636 | HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), |
612 | HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT), | 637 | HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT), |
613 | /* HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x18, 0x0, HDA_OUTPUT), | 638 | /* |
614 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x18, 0x0, HDA_OUTPUT), | ||
615 | HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT), | 639 | HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT), |
616 | HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), */ | 640 | HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), */ |
617 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), | 641 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), |
@@ -809,8 +833,6 @@ static struct snd_kcontrol_new ad1986a_laptop_automute_mixers[] = { | |||
809 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), | 833 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), |
810 | HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), | 834 | HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), |
811 | HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT), | 835 | HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT), |
812 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x18, 0x0, HDA_OUTPUT), | ||
813 | HDA_CODEC_MUTE("Beep Playback Switch", 0x18, 0x0, HDA_OUTPUT), | ||
814 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), | 836 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), |
815 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT), | 837 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT), |
816 | { | 838 | { |
@@ -1002,10 +1024,8 @@ static struct snd_pci_quirk ad1986a_cfg_tbl[] = { | |||
1002 | SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba", AD1986A_LAPTOP_EAPD), | 1024 | SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba", AD1986A_LAPTOP_EAPD), |
1003 | SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK), | 1025 | SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK), |
1004 | SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP), | 1026 | SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP), |
1005 | SND_PCI_QUIRK(0x144d, 0xc023, "Samsung X60", AD1986A_SAMSUNG), | ||
1006 | SND_PCI_QUIRK(0x144d, 0xc024, "Samsung R65", AD1986A_SAMSUNG), | ||
1007 | SND_PCI_QUIRK(0x144d, 0xc026, "Samsung X11", AD1986A_SAMSUNG), | ||
1008 | SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA), | 1027 | SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA), |
1028 | SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc000, "Samsung", AD1986A_SAMSUNG), | ||
1009 | SND_PCI_QUIRK(0x144d, 0xc504, "Samsung Q35", AD1986A_3STACK), | 1029 | SND_PCI_QUIRK(0x144d, 0xc504, "Samsung Q35", AD1986A_3STACK), |
1010 | SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_LAPTOP), | 1030 | SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_LAPTOP), |
1011 | SND_PCI_QUIRK(0x17aa, 0x1017, "Lenovo A60", AD1986A_3STACK), | 1031 | SND_PCI_QUIRK(0x17aa, 0x1017, "Lenovo A60", AD1986A_3STACK), |
@@ -1027,15 +1047,14 @@ static struct hda_amp_list ad1986a_loopbacks[] = { | |||
1027 | 1047 | ||
1028 | static int is_jack_available(struct hda_codec *codec, hda_nid_t nid) | 1048 | static int is_jack_available(struct hda_codec *codec, hda_nid_t nid) |
1029 | { | 1049 | { |
1030 | unsigned int conf = snd_hda_codec_read(codec, nid, 0, | 1050 | unsigned int conf = snd_hda_codec_get_pincfg(codec, nid); |
1031 | AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
1032 | return get_defcfg_connect(conf) != AC_JACK_PORT_NONE; | 1051 | return get_defcfg_connect(conf) != AC_JACK_PORT_NONE; |
1033 | } | 1052 | } |
1034 | 1053 | ||
1035 | static int patch_ad1986a(struct hda_codec *codec) | 1054 | static int patch_ad1986a(struct hda_codec *codec) |
1036 | { | 1055 | { |
1037 | struct ad198x_spec *spec; | 1056 | struct ad198x_spec *spec; |
1038 | int board_config; | 1057 | int err, board_config; |
1039 | 1058 | ||
1040 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 1059 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
1041 | if (spec == NULL) | 1060 | if (spec == NULL) |
@@ -1043,6 +1062,13 @@ static int patch_ad1986a(struct hda_codec *codec) | |||
1043 | 1062 | ||
1044 | codec->spec = spec; | 1063 | codec->spec = spec; |
1045 | 1064 | ||
1065 | err = snd_hda_attach_beep_device(codec, 0x19); | ||
1066 | if (err < 0) { | ||
1067 | ad198x_free(codec); | ||
1068 | return err; | ||
1069 | } | ||
1070 | set_beep_amp(spec, 0x18, 0, HDA_OUTPUT); | ||
1071 | |||
1046 | spec->multiout.max_channels = 6; | 1072 | spec->multiout.max_channels = 6; |
1047 | spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids); | 1073 | spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids); |
1048 | spec->multiout.dac_nids = ad1986a_dac_nids; | 1074 | spec->multiout.dac_nids = ad1986a_dac_nids; |
@@ -1222,8 +1248,6 @@ static struct snd_kcontrol_new ad1983_mixers[] = { | |||
1222 | HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT), | 1248 | HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT), |
1223 | HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT), | 1249 | HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT), |
1224 | HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT), | 1250 | HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT), |
1225 | HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x10, 1, 0x0, HDA_OUTPUT), | ||
1226 | HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x10, 1, 0x0, HDA_OUTPUT), | ||
1227 | HDA_CODEC_VOLUME("Mic Boost", 0x0c, 0x0, HDA_OUTPUT), | 1251 | HDA_CODEC_VOLUME("Mic Boost", 0x0c, 0x0, HDA_OUTPUT), |
1228 | HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), | 1252 | HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), |
1229 | HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT), | 1253 | HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT), |
@@ -1294,6 +1318,7 @@ static struct hda_amp_list ad1983_loopbacks[] = { | |||
1294 | static int patch_ad1983(struct hda_codec *codec) | 1318 | static int patch_ad1983(struct hda_codec *codec) |
1295 | { | 1319 | { |
1296 | struct ad198x_spec *spec; | 1320 | struct ad198x_spec *spec; |
1321 | int err; | ||
1297 | 1322 | ||
1298 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 1323 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
1299 | if (spec == NULL) | 1324 | if (spec == NULL) |
@@ -1301,6 +1326,13 @@ static int patch_ad1983(struct hda_codec *codec) | |||
1301 | 1326 | ||
1302 | codec->spec = spec; | 1327 | codec->spec = spec; |
1303 | 1328 | ||
1329 | err = snd_hda_attach_beep_device(codec, 0x10); | ||
1330 | if (err < 0) { | ||
1331 | ad198x_free(codec); | ||
1332 | return err; | ||
1333 | } | ||
1334 | set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); | ||
1335 | |||
1304 | spec->multiout.max_channels = 2; | 1336 | spec->multiout.max_channels = 2; |
1305 | spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids); | 1337 | spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids); |
1306 | spec->multiout.dac_nids = ad1983_dac_nids; | 1338 | spec->multiout.dac_nids = ad1983_dac_nids; |
@@ -1370,8 +1402,6 @@ static struct snd_kcontrol_new ad1981_mixers[] = { | |||
1370 | HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT), | 1402 | HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT), |
1371 | HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT), | 1403 | HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT), |
1372 | HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT), | 1404 | HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT), |
1373 | HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT), | ||
1374 | HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x0d, 1, 0x0, HDA_OUTPUT), | ||
1375 | HDA_CODEC_VOLUME("Front Mic Boost", 0x08, 0x0, HDA_INPUT), | 1405 | HDA_CODEC_VOLUME("Front Mic Boost", 0x08, 0x0, HDA_INPUT), |
1376 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x0, HDA_INPUT), | 1406 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x0, HDA_INPUT), |
1377 | HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), | 1407 | HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), |
@@ -1416,8 +1446,8 @@ static struct hda_verb ad1981_init_verbs[] = { | |||
1416 | {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 1446 | {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, |
1417 | {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | 1447 | {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, |
1418 | /* Mic boost: 0dB */ | 1448 | /* Mic boost: 0dB */ |
1419 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 1449 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
1420 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 1450 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
1421 | /* Record selector: Front mic */ | 1451 | /* Record selector: Front mic */ |
1422 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x0}, | 1452 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x0}, |
1423 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | 1453 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, |
@@ -1682,10 +1712,10 @@ static struct snd_pci_quirk ad1981_cfg_tbl[] = { | |||
1682 | SND_PCI_QUIRK(0x1014, 0x0597, "Lenovo Z60", AD1981_THINKPAD), | 1712 | SND_PCI_QUIRK(0x1014, 0x0597, "Lenovo Z60", AD1981_THINKPAD), |
1683 | SND_PCI_QUIRK(0x1014, 0x05b7, "Lenovo Z60m", AD1981_THINKPAD), | 1713 | SND_PCI_QUIRK(0x1014, 0x05b7, "Lenovo Z60m", AD1981_THINKPAD), |
1684 | /* All HP models */ | 1714 | /* All HP models */ |
1685 | SND_PCI_QUIRK(0x103c, 0, "HP nx", AD1981_HP), | 1715 | SND_PCI_QUIRK_VENDOR(0x103c, "HP nx", AD1981_HP), |
1686 | SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba U205", AD1981_TOSHIBA), | 1716 | SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba U205", AD1981_TOSHIBA), |
1687 | /* Lenovo Thinkpad T60/X60/Z6xx */ | 1717 | /* Lenovo Thinkpad T60/X60/Z6xx */ |
1688 | SND_PCI_QUIRK(0x17aa, 0, "Lenovo Thinkpad", AD1981_THINKPAD), | 1718 | SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1981_THINKPAD), |
1689 | /* HP nx6320 (reversed SSID, H/W bug) */ | 1719 | /* HP nx6320 (reversed SSID, H/W bug) */ |
1690 | SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_HP), | 1720 | SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_HP), |
1691 | {} | 1721 | {} |
@@ -1694,7 +1724,7 @@ static struct snd_pci_quirk ad1981_cfg_tbl[] = { | |||
1694 | static int patch_ad1981(struct hda_codec *codec) | 1724 | static int patch_ad1981(struct hda_codec *codec) |
1695 | { | 1725 | { |
1696 | struct ad198x_spec *spec; | 1726 | struct ad198x_spec *spec; |
1697 | int board_config; | 1727 | int err, board_config; |
1698 | 1728 | ||
1699 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 1729 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
1700 | if (spec == NULL) | 1730 | if (spec == NULL) |
@@ -1702,6 +1732,13 @@ static int patch_ad1981(struct hda_codec *codec) | |||
1702 | 1732 | ||
1703 | codec->spec = spec; | 1733 | codec->spec = spec; |
1704 | 1734 | ||
1735 | err = snd_hda_attach_beep_device(codec, 0x10); | ||
1736 | if (err < 0) { | ||
1737 | ad198x_free(codec); | ||
1738 | return err; | ||
1739 | } | ||
1740 | set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT); | ||
1741 | |||
1705 | spec->multiout.max_channels = 2; | 1742 | spec->multiout.max_channels = 2; |
1706 | spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids); | 1743 | spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids); |
1707 | spec->multiout.dac_nids = ad1981_dac_nids; | 1744 | spec->multiout.dac_nids = ad1981_dac_nids; |
@@ -1988,9 +2025,6 @@ static struct snd_kcontrol_new ad1988_6stack_mixers2[] = { | |||
1988 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT), | 2025 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT), |
1989 | HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT), | 2026 | HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT), |
1990 | 2027 | ||
1991 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT), | ||
1992 | HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT), | ||
1993 | |||
1994 | HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT), | 2028 | HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT), |
1995 | HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT), | 2029 | HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT), |
1996 | 2030 | ||
@@ -2034,9 +2068,6 @@ static struct snd_kcontrol_new ad1988_3stack_mixers2[] = { | |||
2034 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT), | 2068 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT), |
2035 | HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT), | 2069 | HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT), |
2036 | 2070 | ||
2037 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT), | ||
2038 | HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT), | ||
2039 | |||
2040 | HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT), | 2071 | HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT), |
2041 | HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT), | 2072 | HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT), |
2042 | 2073 | ||
@@ -2066,9 +2097,6 @@ static struct snd_kcontrol_new ad1988_laptop_mixers[] = { | |||
2066 | HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT), | 2097 | HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT), |
2067 | HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT), | 2098 | HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT), |
2068 | 2099 | ||
2069 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT), | ||
2070 | HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT), | ||
2071 | |||
2072 | HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT), | 2100 | HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT), |
2073 | HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT), | 2101 | HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT), |
2074 | 2102 | ||
@@ -2297,10 +2325,6 @@ static struct hda_verb ad1988_capture_init_verbs[] = { | |||
2297 | {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1}, | 2325 | {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1}, |
2298 | {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1}, | 2326 | {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1}, |
2299 | {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, | 2327 | {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, |
2300 | /* ADCs; muted */ | ||
2301 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
2302 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
2303 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
2304 | 2328 | ||
2305 | { } | 2329 | { } |
2306 | }; | 2330 | }; |
@@ -2408,10 +2432,6 @@ static struct hda_verb ad1988_3stack_init_verbs[] = { | |||
2408 | {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1}, | 2432 | {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1}, |
2409 | {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1}, | 2433 | {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1}, |
2410 | {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, | 2434 | {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, |
2411 | /* ADCs; muted */ | ||
2412 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
2413 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
2414 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
2415 | /* Analog Mix output amp */ | 2435 | /* Analog Mix output amp */ |
2416 | {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ | 2436 | {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ |
2417 | { } | 2437 | { } |
@@ -2483,10 +2503,6 @@ static struct hda_verb ad1988_laptop_init_verbs[] = { | |||
2483 | {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1}, | 2503 | {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1}, |
2484 | {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1}, | 2504 | {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1}, |
2485 | {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, | 2505 | {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, |
2486 | /* ADCs; muted */ | ||
2487 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
2488 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
2489 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
2490 | /* Analog Mix output amp */ | 2506 | /* Analog Mix output amp */ |
2491 | {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ | 2507 | {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ |
2492 | { } | 2508 | { } |
@@ -2890,7 +2906,7 @@ static int ad1988_parse_auto_config(struct hda_codec *codec) | |||
2890 | 2906 | ||
2891 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 2907 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
2892 | 2908 | ||
2893 | if (spec->autocfg.dig_out_pin) | 2909 | if (spec->autocfg.dig_outs) |
2894 | spec->multiout.dig_out_nid = AD1988_SPDIF_OUT; | 2910 | spec->multiout.dig_out_nid = AD1988_SPDIF_OUT; |
2895 | if (spec->autocfg.dig_in_pin) | 2911 | if (spec->autocfg.dig_in_pin) |
2896 | spec->dig_in_nid = AD1988_SPDIF_IN; | 2912 | spec->dig_in_nid = AD1988_SPDIF_IN; |
@@ -2940,7 +2956,7 @@ static struct snd_pci_quirk ad1988_cfg_tbl[] = { | |||
2940 | static int patch_ad1988(struct hda_codec *codec) | 2956 | static int patch_ad1988(struct hda_codec *codec) |
2941 | { | 2957 | { |
2942 | struct ad198x_spec *spec; | 2958 | struct ad198x_spec *spec; |
2943 | int board_config; | 2959 | int err, board_config; |
2944 | 2960 | ||
2945 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 2961 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
2946 | if (spec == NULL) | 2962 | if (spec == NULL) |
@@ -2960,7 +2976,7 @@ static int patch_ad1988(struct hda_codec *codec) | |||
2960 | 2976 | ||
2961 | if (board_config == AD1988_AUTO) { | 2977 | if (board_config == AD1988_AUTO) { |
2962 | /* automatic parse from the BIOS config */ | 2978 | /* automatic parse from the BIOS config */ |
2963 | int err = ad1988_parse_auto_config(codec); | 2979 | err = ad1988_parse_auto_config(codec); |
2964 | if (err < 0) { | 2980 | if (err < 0) { |
2965 | ad198x_free(codec); | 2981 | ad198x_free(codec); |
2966 | return err; | 2982 | return err; |
@@ -2970,6 +2986,13 @@ static int patch_ad1988(struct hda_codec *codec) | |||
2970 | } | 2986 | } |
2971 | } | 2987 | } |
2972 | 2988 | ||
2989 | err = snd_hda_attach_beep_device(codec, 0x10); | ||
2990 | if (err < 0) { | ||
2991 | ad198x_free(codec); | ||
2992 | return err; | ||
2993 | } | ||
2994 | set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); | ||
2995 | |||
2973 | switch (board_config) { | 2996 | switch (board_config) { |
2974 | case AD1988_6STACK: | 2997 | case AD1988_6STACK: |
2975 | case AD1988_6STACK_DIG: | 2998 | case AD1988_6STACK_DIG: |
@@ -3126,12 +3149,6 @@ static struct snd_kcontrol_new ad1884_base_mixers[] = { | |||
3126 | HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT), | 3149 | HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT), |
3127 | HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT), | 3150 | HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT), |
3128 | HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT), | 3151 | HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT), |
3129 | /* | ||
3130 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x20, 0x03, HDA_INPUT), | ||
3131 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x20, 0x03, HDA_INPUT), | ||
3132 | HDA_CODEC_VOLUME("Digital Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT), | ||
3133 | HDA_CODEC_MUTE("Digital Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT), | ||
3134 | */ | ||
3135 | HDA_CODEC_VOLUME("Mic Boost", 0x15, 0x0, HDA_INPUT), | 3152 | HDA_CODEC_VOLUME("Mic Boost", 0x15, 0x0, HDA_INPUT), |
3136 | HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT), | 3153 | HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT), |
3137 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), | 3154 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), |
@@ -3204,10 +3221,10 @@ static struct hda_verb ad1884_init_verbs[] = { | |||
3204 | {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, | 3221 | {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, |
3205 | /* Port-B (front mic) pin */ | 3222 | /* Port-B (front mic) pin */ |
3206 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | 3223 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, |
3207 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | 3224 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
3208 | /* Port-C (rear mic) pin */ | 3225 | /* Port-C (rear mic) pin */ |
3209 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | 3226 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, |
3210 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | 3227 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
3211 | /* Analog mixer; mute as default */ | 3228 | /* Analog mixer; mute as default */ |
3212 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | 3229 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
3213 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | 3230 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
@@ -3240,7 +3257,7 @@ static const char *ad1884_slave_vols[] = { | |||
3240 | "CD Playback Volume", | 3257 | "CD Playback Volume", |
3241 | "Internal Mic Playback Volume", | 3258 | "Internal Mic Playback Volume", |
3242 | "Docking Mic Playback Volume" | 3259 | "Docking Mic Playback Volume" |
3243 | "Beep Playback Volume", | 3260 | /* "Beep Playback Volume", */ |
3244 | "IEC958 Playback Volume", | 3261 | "IEC958 Playback Volume", |
3245 | NULL | 3262 | NULL |
3246 | }; | 3263 | }; |
@@ -3248,6 +3265,7 @@ static const char *ad1884_slave_vols[] = { | |||
3248 | static int patch_ad1884(struct hda_codec *codec) | 3265 | static int patch_ad1884(struct hda_codec *codec) |
3249 | { | 3266 | { |
3250 | struct ad198x_spec *spec; | 3267 | struct ad198x_spec *spec; |
3268 | int err; | ||
3251 | 3269 | ||
3252 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 3270 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
3253 | if (spec == NULL) | 3271 | if (spec == NULL) |
@@ -3255,6 +3273,13 @@ static int patch_ad1884(struct hda_codec *codec) | |||
3255 | 3273 | ||
3256 | codec->spec = spec; | 3274 | codec->spec = spec; |
3257 | 3275 | ||
3276 | err = snd_hda_attach_beep_device(codec, 0x10); | ||
3277 | if (err < 0) { | ||
3278 | ad198x_free(codec); | ||
3279 | return err; | ||
3280 | } | ||
3281 | set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); | ||
3282 | |||
3258 | spec->multiout.max_channels = 2; | 3283 | spec->multiout.max_channels = 2; |
3259 | spec->multiout.num_dacs = ARRAY_SIZE(ad1884_dac_nids); | 3284 | spec->multiout.num_dacs = ARRAY_SIZE(ad1884_dac_nids); |
3260 | spec->multiout.dac_nids = ad1884_dac_nids; | 3285 | spec->multiout.dac_nids = ad1884_dac_nids; |
@@ -3321,8 +3346,6 @@ static struct snd_kcontrol_new ad1984_thinkpad_mixers[] = { | |||
3321 | HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT), | 3346 | HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT), |
3322 | HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT), | 3347 | HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT), |
3323 | HDA_CODEC_VOLUME("Docking Mic Boost", 0x25, 0x0, HDA_OUTPUT), | 3348 | HDA_CODEC_VOLUME("Docking Mic Boost", 0x25, 0x0, HDA_OUTPUT), |
3324 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT), | ||
3325 | HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT), | ||
3326 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), | 3349 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), |
3327 | HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), | 3350 | HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), |
3328 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), | 3351 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), |
@@ -3358,7 +3381,7 @@ static struct hda_verb ad1984_thinkpad_init_verbs[] = { | |||
3358 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | 3381 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, |
3359 | {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | 3382 | {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, |
3360 | /* docking mic boost */ | 3383 | /* docking mic boost */ |
3361 | {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | 3384 | {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, |
3362 | /* Analog mixer - docking mic; mute as default */ | 3385 | /* Analog mixer - docking mic; mute as default */ |
3363 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | 3386 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
3364 | /* enable EAPD bit */ | 3387 | /* enable EAPD bit */ |
@@ -3379,10 +3402,6 @@ static struct snd_kcontrol_new ad1984_dell_desktop_mixers[] = { | |||
3379 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT), | 3402 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT), |
3380 | HDA_CODEC_VOLUME("Line-In Playback Volume", 0x20, 0x01, HDA_INPUT), | 3403 | HDA_CODEC_VOLUME("Line-In Playback Volume", 0x20, 0x01, HDA_INPUT), |
3381 | HDA_CODEC_MUTE("Line-In Playback Switch", 0x20, 0x01, HDA_INPUT), | 3404 | HDA_CODEC_MUTE("Line-In Playback Switch", 0x20, 0x01, HDA_INPUT), |
3382 | /* | ||
3383 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x20, 0x03, HDA_INPUT), | ||
3384 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x20, 0x03, HDA_INPUT), | ||
3385 | */ | ||
3386 | HDA_CODEC_VOLUME("Line-In Boost", 0x15, 0x0, HDA_INPUT), | 3405 | HDA_CODEC_VOLUME("Line-In Boost", 0x15, 0x0, HDA_INPUT), |
3387 | HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT), | 3406 | HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT), |
3388 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), | 3407 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), |
@@ -3468,7 +3487,7 @@ static const char *ad1984_models[AD1984_MODELS] = { | |||
3468 | 3487 | ||
3469 | static struct snd_pci_quirk ad1984_cfg_tbl[] = { | 3488 | static struct snd_pci_quirk ad1984_cfg_tbl[] = { |
3470 | /* Lenovo Thinkpad T61/X61 */ | 3489 | /* Lenovo Thinkpad T61/X61 */ |
3471 | SND_PCI_QUIRK(0x17aa, 0, "Lenovo Thinkpad", AD1984_THINKPAD), | 3490 | SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1984_THINKPAD), |
3472 | SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP), | 3491 | SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP), |
3473 | {} | 3492 | {} |
3474 | }; | 3493 | }; |
@@ -3561,8 +3580,6 @@ static struct snd_kcontrol_new ad1884a_base_mixers[] = { | |||
3561 | HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT), | 3580 | HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT), |
3562 | HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT), | 3581 | HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT), |
3563 | HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT), | 3582 | HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT), |
3564 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT), | ||
3565 | HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT), | ||
3566 | HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT), | 3583 | HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT), |
3567 | HDA_CODEC_VOLUME("Line Boost", 0x15, 0x0, HDA_INPUT), | 3584 | HDA_CODEC_VOLUME("Line Boost", 0x15, 0x0, HDA_INPUT), |
3568 | HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT), | 3585 | HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT), |
@@ -3622,10 +3639,10 @@ static struct hda_verb ad1884a_init_verbs[] = { | |||
3622 | {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | 3639 | {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, |
3623 | /* Port-B (front mic) pin */ | 3640 | /* Port-B (front mic) pin */ |
3624 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | 3641 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, |
3625 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | 3642 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
3626 | /* Port-C (rear line-in) pin */ | 3643 | /* Port-C (rear line-in) pin */ |
3627 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | 3644 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, |
3628 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | 3645 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
3629 | /* Port-E (rear mic) pin */ | 3646 | /* Port-E (rear mic) pin */ |
3630 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | 3647 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, |
3631 | {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | 3648 | {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, |
@@ -3695,8 +3712,6 @@ static struct snd_kcontrol_new ad1884a_laptop_mixers[] = { | |||
3695 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT), | 3712 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT), |
3696 | HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT), | 3713 | HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT), |
3697 | HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT), | 3714 | HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT), |
3698 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT), | ||
3699 | HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT), | ||
3700 | HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT), | 3715 | HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT), |
3701 | HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT), | 3716 | HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT), |
3702 | HDA_CODEC_VOLUME("Dock Mic Boost", 0x25, 0x0, HDA_OUTPUT), | 3717 | HDA_CODEC_VOLUME("Dock Mic Boost", 0x25, 0x0, HDA_OUTPUT), |
@@ -3724,8 +3739,6 @@ static struct snd_kcontrol_new ad1884a_mobile_mixers[] = { | |||
3724 | HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT), | 3739 | HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT), |
3725 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), | 3740 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), |
3726 | HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), | 3741 | HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), |
3727 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT), | ||
3728 | HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT), | ||
3729 | HDA_CODEC_VOLUME("Mic Capture Volume", 0x14, 0x0, HDA_INPUT), | 3742 | HDA_CODEC_VOLUME("Mic Capture Volume", 0x14, 0x0, HDA_INPUT), |
3730 | HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x15, 0x0, HDA_INPUT), | 3743 | HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x15, 0x0, HDA_INPUT), |
3731 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), | 3744 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), |
@@ -3836,8 +3849,6 @@ static struct snd_kcontrol_new ad1984a_thinkpad_mixers[] = { | |||
3836 | HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), | 3849 | HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), |
3837 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT), | 3850 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT), |
3838 | HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT), | 3851 | HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT), |
3839 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT), | ||
3840 | HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT), | ||
3841 | HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT), | 3852 | HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT), |
3842 | HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT), | 3853 | HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT), |
3843 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), | 3854 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), |
@@ -3911,9 +3922,9 @@ static struct snd_pci_quirk ad1884a_cfg_tbl[] = { | |||
3911 | SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE), | 3922 | SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE), |
3912 | SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP), | 3923 | SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP), |
3913 | SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE), | 3924 | SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE), |
3914 | SND_PCI_QUIRK(0x103c, 0x30e6, "HP 6730b", AD1884A_LAPTOP), | 3925 | SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x3070, "HP", AD1884A_MOBILE), |
3915 | SND_PCI_QUIRK(0x103c, 0x30e7, "HP EliteBook 8530p", AD1884A_LAPTOP), | 3926 | SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30e0, "HP laptop", AD1884A_LAPTOP), |
3916 | SND_PCI_QUIRK(0x103c, 0x3614, "HP 6730s", AD1884A_LAPTOP), | 3927 | SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3600, "HP laptop", AD1884A_LAPTOP), |
3917 | SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD), | 3928 | SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD), |
3918 | {} | 3929 | {} |
3919 | }; | 3930 | }; |
@@ -3921,7 +3932,7 @@ static struct snd_pci_quirk ad1884a_cfg_tbl[] = { | |||
3921 | static int patch_ad1884a(struct hda_codec *codec) | 3932 | static int patch_ad1884a(struct hda_codec *codec) |
3922 | { | 3933 | { |
3923 | struct ad198x_spec *spec; | 3934 | struct ad198x_spec *spec; |
3924 | int board_config; | 3935 | int err, board_config; |
3925 | 3936 | ||
3926 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 3937 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
3927 | if (spec == NULL) | 3938 | if (spec == NULL) |
@@ -3929,6 +3940,13 @@ static int patch_ad1884a(struct hda_codec *codec) | |||
3929 | 3940 | ||
3930 | codec->spec = spec; | 3941 | codec->spec = spec; |
3931 | 3942 | ||
3943 | err = snd_hda_attach_beep_device(codec, 0x10); | ||
3944 | if (err < 0) { | ||
3945 | ad198x_free(codec); | ||
3946 | return err; | ||
3947 | } | ||
3948 | set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); | ||
3949 | |||
3932 | spec->multiout.max_channels = 2; | 3950 | spec->multiout.max_channels = 2; |
3933 | spec->multiout.num_dacs = ARRAY_SIZE(ad1884a_dac_nids); | 3951 | spec->multiout.num_dacs = ARRAY_SIZE(ad1884a_dac_nids); |
3934 | spec->multiout.dac_nids = ad1884a_dac_nids; | 3952 | spec->multiout.dac_nids = ad1884a_dac_nids; |
@@ -3966,6 +3984,14 @@ static int patch_ad1884a(struct hda_codec *codec) | |||
3966 | spec->multiout.dig_out_nid = 0; | 3984 | spec->multiout.dig_out_nid = 0; |
3967 | codec->patch_ops.unsol_event = ad1884a_hp_unsol_event; | 3985 | codec->patch_ops.unsol_event = ad1884a_hp_unsol_event; |
3968 | codec->patch_ops.init = ad1884a_hp_init; | 3986 | codec->patch_ops.init = ad1884a_hp_init; |
3987 | /* set the upper-limit for mixer amp to 0dB for avoiding the | ||
3988 | * possible damage by overloading | ||
3989 | */ | ||
3990 | snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT, | ||
3991 | (0x17 << AC_AMPCAP_OFFSET_SHIFT) | | ||
3992 | (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | | ||
3993 | (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | | ||
3994 | (1 << AC_AMPCAP_MUTE_SHIFT)); | ||
3969 | break; | 3995 | break; |
3970 | case AD1884A_THINKPAD: | 3996 | case AD1884A_THINKPAD: |
3971 | spec->mixers[0] = ad1984a_thinkpad_mixers; | 3997 | spec->mixers[0] = ad1984a_thinkpad_mixers; |
@@ -4083,8 +4109,6 @@ static struct snd_kcontrol_new ad1882_loopback_mixers[] = { | |||
4083 | HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x04, HDA_INPUT), | 4109 | HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x04, HDA_INPUT), |
4084 | HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT), | 4110 | HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT), |
4085 | HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT), | 4111 | HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT), |
4086 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x07, HDA_INPUT), | ||
4087 | HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x07, HDA_INPUT), | ||
4088 | { } /* end */ | 4112 | { } /* end */ |
4089 | }; | 4113 | }; |
4090 | 4114 | ||
@@ -4097,8 +4121,6 @@ static struct snd_kcontrol_new ad1882a_loopback_mixers[] = { | |||
4097 | HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT), | 4121 | HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT), |
4098 | HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT), | 4122 | HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT), |
4099 | HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT), | 4123 | HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT), |
4100 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x07, HDA_INPUT), | ||
4101 | HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x07, HDA_INPUT), | ||
4102 | HDA_CODEC_VOLUME("Digital Mic Boost", 0x1f, 0x0, HDA_INPUT), | 4124 | HDA_CODEC_VOLUME("Digital Mic Boost", 0x1f, 0x0, HDA_INPUT), |
4103 | { } /* end */ | 4125 | { } /* end */ |
4104 | }; | 4126 | }; |
@@ -4257,7 +4279,7 @@ static const char *ad1882_models[AD1986A_MODELS] = { | |||
4257 | static int patch_ad1882(struct hda_codec *codec) | 4279 | static int patch_ad1882(struct hda_codec *codec) |
4258 | { | 4280 | { |
4259 | struct ad198x_spec *spec; | 4281 | struct ad198x_spec *spec; |
4260 | int board_config; | 4282 | int err, board_config; |
4261 | 4283 | ||
4262 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 4284 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
4263 | if (spec == NULL) | 4285 | if (spec == NULL) |
@@ -4265,6 +4287,13 @@ static int patch_ad1882(struct hda_codec *codec) | |||
4265 | 4287 | ||
4266 | codec->spec = spec; | 4288 | codec->spec = spec; |
4267 | 4289 | ||
4290 | err = snd_hda_attach_beep_device(codec, 0x10); | ||
4291 | if (err < 0) { | ||
4292 | ad198x_free(codec); | ||
4293 | return err; | ||
4294 | } | ||
4295 | set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); | ||
4296 | |||
4268 | spec->multiout.max_channels = 6; | 4297 | spec->multiout.max_channels = 6; |
4269 | spec->multiout.num_dacs = 3; | 4298 | spec->multiout.num_dacs = 3; |
4270 | spec->multiout.dac_nids = ad1882_dac_nids; | 4299 | spec->multiout.dac_nids = ad1882_dac_nids; |
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c index f3ebe837f2d5..c921264bbd71 100644 --- a/sound/pci/hda/patch_cmedia.c +++ b/sound/pci/hda/patch_cmedia.c | |||
@@ -680,13 +680,13 @@ static int patch_cmi9880(struct hda_codec *codec) | |||
680 | struct auto_pin_cfg cfg; | 680 | struct auto_pin_cfg cfg; |
681 | 681 | ||
682 | /* collect pin default configuration */ | 682 | /* collect pin default configuration */ |
683 | port_e = snd_hda_codec_read(codec, 0x0f, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); | 683 | port_e = snd_hda_codec_get_pincfg(codec, 0x0f); |
684 | port_f = snd_hda_codec_read(codec, 0x10, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); | 684 | port_f = snd_hda_codec_get_pincfg(codec, 0x10); |
685 | spec->front_panel = 1; | 685 | spec->front_panel = 1; |
686 | if (get_defcfg_connect(port_e) == AC_JACK_PORT_NONE || | 686 | if (get_defcfg_connect(port_e) == AC_JACK_PORT_NONE || |
687 | get_defcfg_connect(port_f) == AC_JACK_PORT_NONE) { | 687 | get_defcfg_connect(port_f) == AC_JACK_PORT_NONE) { |
688 | port_g = snd_hda_codec_read(codec, 0x1f, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); | 688 | port_g = snd_hda_codec_get_pincfg(codec, 0x1f); |
689 | port_h = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); | 689 | port_h = snd_hda_codec_get_pincfg(codec, 0x20); |
690 | spec->channel_modes = cmi9880_channel_modes; | 690 | spec->channel_modes = cmi9880_channel_modes; |
691 | /* no front panel */ | 691 | /* no front panel */ |
692 | if (get_defcfg_connect(port_g) == AC_JACK_PORT_NONE || | 692 | if (get_defcfg_connect(port_g) == AC_JACK_PORT_NONE || |
@@ -703,8 +703,8 @@ static int patch_cmi9880(struct hda_codec *codec) | |||
703 | spec->multiout.max_channels = cmi9880_channel_modes[0].channels; | 703 | spec->multiout.max_channels = cmi9880_channel_modes[0].channels; |
704 | } else { | 704 | } else { |
705 | spec->input_mux = &cmi9880_basic_mux; | 705 | spec->input_mux = &cmi9880_basic_mux; |
706 | port_spdifi = snd_hda_codec_read(codec, 0x13, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); | 706 | port_spdifi = snd_hda_codec_get_pincfg(codec, 0x13); |
707 | port_spdifo = snd_hda_codec_read(codec, 0x12, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); | 707 | port_spdifo = snd_hda_codec_get_pincfg(codec, 0x12); |
708 | if (get_defcfg_connect(port_spdifo) != AC_JACK_PORT_NONE) | 708 | if (get_defcfg_connect(port_spdifo) != AC_JACK_PORT_NONE) |
709 | spec->multiout.dig_out_nid = CMI_DIG_OUT_NID; | 709 | spec->multiout.dig_out_nid = CMI_DIG_OUT_NID; |
710 | if (get_defcfg_connect(port_spdifi) != AC_JACK_PORT_NONE) | 710 | if (get_defcfg_connect(port_spdifi) != AC_JACK_PORT_NONE) |
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 0177ef8f4c9e..1f2ad76ca94b 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -58,6 +58,7 @@ struct conexant_spec { | |||
58 | 58 | ||
59 | struct snd_kcontrol_new *mixers[5]; | 59 | struct snd_kcontrol_new *mixers[5]; |
60 | int num_mixers; | 60 | int num_mixers; |
61 | hda_nid_t vmaster_nid; | ||
61 | 62 | ||
62 | const struct hda_verb *init_verbs[5]; /* initialization verbs | 63 | const struct hda_verb *init_verbs[5]; /* initialization verbs |
63 | * don't forget NULL | 64 | * don't forget NULL |
@@ -72,6 +73,7 @@ struct conexant_spec { | |||
72 | */ | 73 | */ |
73 | unsigned int cur_eapd; | 74 | unsigned int cur_eapd; |
74 | unsigned int hp_present; | 75 | unsigned int hp_present; |
76 | unsigned int no_auto_mic; | ||
75 | unsigned int need_dac_fix; | 77 | unsigned int need_dac_fix; |
76 | 78 | ||
77 | /* capture */ | 79 | /* capture */ |
@@ -461,6 +463,29 @@ static void conexant_free(struct hda_codec *codec) | |||
461 | kfree(codec->spec); | 463 | kfree(codec->spec); |
462 | } | 464 | } |
463 | 465 | ||
466 | static struct snd_kcontrol_new cxt_capture_mixers[] = { | ||
467 | { | ||
468 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
469 | .name = "Capture Source", | ||
470 | .info = conexant_mux_enum_info, | ||
471 | .get = conexant_mux_enum_get, | ||
472 | .put = conexant_mux_enum_put | ||
473 | }, | ||
474 | {} | ||
475 | }; | ||
476 | |||
477 | static const char *slave_vols[] = { | ||
478 | "Headphone Playback Volume", | ||
479 | "Speaker Playback Volume", | ||
480 | NULL | ||
481 | }; | ||
482 | |||
483 | static const char *slave_sws[] = { | ||
484 | "Headphone Playback Switch", | ||
485 | "Speaker Playback Switch", | ||
486 | NULL | ||
487 | }; | ||
488 | |||
464 | static int conexant_build_controls(struct hda_codec *codec) | 489 | static int conexant_build_controls(struct hda_codec *codec) |
465 | { | 490 | { |
466 | struct conexant_spec *spec = codec->spec; | 491 | struct conexant_spec *spec = codec->spec; |
@@ -488,6 +513,32 @@ static int conexant_build_controls(struct hda_codec *codec) | |||
488 | if (err < 0) | 513 | if (err < 0) |
489 | return err; | 514 | return err; |
490 | } | 515 | } |
516 | |||
517 | /* if we have no master control, let's create it */ | ||
518 | if (spec->vmaster_nid && | ||
519 | !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { | ||
520 | unsigned int vmaster_tlv[4]; | ||
521 | snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid, | ||
522 | HDA_OUTPUT, vmaster_tlv); | ||
523 | err = snd_hda_add_vmaster(codec, "Master Playback Volume", | ||
524 | vmaster_tlv, slave_vols); | ||
525 | if (err < 0) | ||
526 | return err; | ||
527 | } | ||
528 | if (spec->vmaster_nid && | ||
529 | !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { | ||
530 | err = snd_hda_add_vmaster(codec, "Master Playback Switch", | ||
531 | NULL, slave_sws); | ||
532 | if (err < 0) | ||
533 | return err; | ||
534 | } | ||
535 | |||
536 | if (spec->input_mux) { | ||
537 | err = snd_hda_add_new_ctls(codec, cxt_capture_mixers); | ||
538 | if (err < 0) | ||
539 | return err; | ||
540 | } | ||
541 | |||
491 | return 0; | 542 | return 0; |
492 | } | 543 | } |
493 | 544 | ||
@@ -719,13 +770,6 @@ static void cxt5045_hp_unsol_event(struct hda_codec *codec, | |||
719 | } | 770 | } |
720 | 771 | ||
721 | static struct snd_kcontrol_new cxt5045_mixers[] = { | 772 | static struct snd_kcontrol_new cxt5045_mixers[] = { |
722 | { | ||
723 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
724 | .name = "Capture Source", | ||
725 | .info = conexant_mux_enum_info, | ||
726 | .get = conexant_mux_enum_get, | ||
727 | .put = conexant_mux_enum_put | ||
728 | }, | ||
729 | HDA_CODEC_VOLUME("Int Mic Capture Volume", 0x1a, 0x01, HDA_INPUT), | 773 | HDA_CODEC_VOLUME("Int Mic Capture Volume", 0x1a, 0x01, HDA_INPUT), |
730 | HDA_CODEC_MUTE("Int Mic Capture Switch", 0x1a, 0x01, HDA_INPUT), | 774 | HDA_CODEC_MUTE("Int Mic Capture Switch", 0x1a, 0x01, HDA_INPUT), |
731 | HDA_CODEC_VOLUME("Ext Mic Capture Volume", 0x1a, 0x02, HDA_INPUT), | 775 | HDA_CODEC_VOLUME("Ext Mic Capture Volume", 0x1a, 0x02, HDA_INPUT), |
@@ -759,13 +803,6 @@ static struct snd_kcontrol_new cxt5045_benq_mixers[] = { | |||
759 | }; | 803 | }; |
760 | 804 | ||
761 | static struct snd_kcontrol_new cxt5045_mixers_hp530[] = { | 805 | static struct snd_kcontrol_new cxt5045_mixers_hp530[] = { |
762 | { | ||
763 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
764 | .name = "Capture Source", | ||
765 | .info = conexant_mux_enum_info, | ||
766 | .get = conexant_mux_enum_get, | ||
767 | .put = conexant_mux_enum_put | ||
768 | }, | ||
769 | HDA_CODEC_VOLUME("Int Mic Capture Volume", 0x1a, 0x02, HDA_INPUT), | 806 | HDA_CODEC_VOLUME("Int Mic Capture Volume", 0x1a, 0x02, HDA_INPUT), |
770 | HDA_CODEC_MUTE("Int Mic Capture Switch", 0x1a, 0x02, HDA_INPUT), | 807 | HDA_CODEC_MUTE("Int Mic Capture Switch", 0x1a, 0x02, HDA_INPUT), |
771 | HDA_CODEC_VOLUME("Ext Mic Capture Volume", 0x1a, 0x01, HDA_INPUT), | 808 | HDA_CODEC_VOLUME("Ext Mic Capture Volume", 0x1a, 0x01, HDA_INPUT), |
@@ -1002,15 +1039,9 @@ static const char *cxt5045_models[CXT5045_MODELS] = { | |||
1002 | }; | 1039 | }; |
1003 | 1040 | ||
1004 | static struct snd_pci_quirk cxt5045_cfg_tbl[] = { | 1041 | static struct snd_pci_quirk cxt5045_cfg_tbl[] = { |
1005 | SND_PCI_QUIRK(0x103c, 0x30a5, "HP", CXT5045_LAPTOP_HPSENSE), | ||
1006 | SND_PCI_QUIRK(0x103c, 0x30b2, "HP DV Series", CXT5045_LAPTOP_HPSENSE), | ||
1007 | SND_PCI_QUIRK(0x103c, 0x30b5, "HP DV2120", CXT5045_LAPTOP_HPSENSE), | ||
1008 | SND_PCI_QUIRK(0x103c, 0x30b7, "HP DV6000Z", CXT5045_LAPTOP_HPSENSE), | ||
1009 | SND_PCI_QUIRK(0x103c, 0x30bb, "HP DV8000", CXT5045_LAPTOP_HPSENSE), | ||
1010 | SND_PCI_QUIRK(0x103c, 0x30cd, "HP DV Series", CXT5045_LAPTOP_HPSENSE), | ||
1011 | SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV9533EG", CXT5045_LAPTOP_HPSENSE), | ||
1012 | SND_PCI_QUIRK(0x103c, 0x30d5, "HP 530", CXT5045_LAPTOP_HP530), | 1042 | SND_PCI_QUIRK(0x103c, 0x30d5, "HP 530", CXT5045_LAPTOP_HP530), |
1013 | SND_PCI_QUIRK(0x103c, 0x30d9, "HP Spartan", CXT5045_LAPTOP_HPSENSE), | 1043 | SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3000, "HP DV Series", |
1044 | CXT5045_LAPTOP_HPSENSE), | ||
1014 | SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P105", CXT5045_LAPTOP_MICSENSE), | 1045 | SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P105", CXT5045_LAPTOP_MICSENSE), |
1015 | SND_PCI_QUIRK(0x152d, 0x0753, "Benq R55E", CXT5045_BENQ), | 1046 | SND_PCI_QUIRK(0x152d, 0x0753, "Benq R55E", CXT5045_BENQ), |
1016 | SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_LAPTOP_MICSENSE), | 1047 | SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_LAPTOP_MICSENSE), |
@@ -1020,8 +1051,8 @@ static struct snd_pci_quirk cxt5045_cfg_tbl[] = { | |||
1020 | SND_PCI_QUIRK(0x1509, 0x1e40, "FIC", CXT5045_LAPTOP_HPMICSENSE), | 1051 | SND_PCI_QUIRK(0x1509, 0x1e40, "FIC", CXT5045_LAPTOP_HPMICSENSE), |
1021 | SND_PCI_QUIRK(0x1509, 0x2f05, "FIC", CXT5045_LAPTOP_HPMICSENSE), | 1052 | SND_PCI_QUIRK(0x1509, 0x2f05, "FIC", CXT5045_LAPTOP_HPMICSENSE), |
1022 | SND_PCI_QUIRK(0x1509, 0x2f06, "FIC", CXT5045_LAPTOP_HPMICSENSE), | 1053 | SND_PCI_QUIRK(0x1509, 0x2f06, "FIC", CXT5045_LAPTOP_HPMICSENSE), |
1023 | SND_PCI_QUIRK(0x1631, 0xc106, "Packard Bell", CXT5045_LAPTOP_HPMICSENSE), | 1054 | SND_PCI_QUIRK_MASK(0x1631, 0xff00, 0xc100, "Packard Bell", |
1024 | SND_PCI_QUIRK(0x1631, 0xc107, "Packard Bell", CXT5045_LAPTOP_HPMICSENSE), | 1055 | CXT5045_LAPTOP_HPMICSENSE), |
1025 | SND_PCI_QUIRK(0x8086, 0x2111, "Conexant Reference board", CXT5045_LAPTOP_HPSENSE), | 1056 | SND_PCI_QUIRK(0x8086, 0x2111, "Conexant Reference board", CXT5045_LAPTOP_HPSENSE), |
1026 | {} | 1057 | {} |
1027 | }; | 1058 | }; |
@@ -1035,6 +1066,7 @@ static int patch_cxt5045(struct hda_codec *codec) | |||
1035 | if (!spec) | 1066 | if (!spec) |
1036 | return -ENOMEM; | 1067 | return -ENOMEM; |
1037 | codec->spec = spec; | 1068 | codec->spec = spec; |
1069 | codec->pin_amp_workaround = 1; | ||
1038 | 1070 | ||
1039 | spec->multiout.max_channels = 2; | 1071 | spec->multiout.max_channels = 2; |
1040 | spec->multiout.num_dacs = ARRAY_SIZE(cxt5045_dac_nids); | 1072 | spec->multiout.num_dacs = ARRAY_SIZE(cxt5045_dac_nids); |
@@ -1134,7 +1166,7 @@ static int patch_cxt5045(struct hda_codec *codec) | |||
1134 | /* Conexant 5047 specific */ | 1166 | /* Conexant 5047 specific */ |
1135 | #define CXT5047_SPDIF_OUT 0x11 | 1167 | #define CXT5047_SPDIF_OUT 0x11 |
1136 | 1168 | ||
1137 | static hda_nid_t cxt5047_dac_nids[2] = { 0x10, 0x1c }; | 1169 | static hda_nid_t cxt5047_dac_nids[1] = { 0x10 }; /* 0x1c */ |
1138 | static hda_nid_t cxt5047_adc_nids[1] = { 0x12 }; | 1170 | static hda_nid_t cxt5047_adc_nids[1] = { 0x12 }; |
1139 | static hda_nid_t cxt5047_capsrc_nids[1] = { 0x1a }; | 1171 | static hda_nid_t cxt5047_capsrc_nids[1] = { 0x1a }; |
1140 | 1172 | ||
@@ -1142,20 +1174,6 @@ static struct hda_channel_mode cxt5047_modes[1] = { | |||
1142 | { 2, NULL }, | 1174 | { 2, NULL }, |
1143 | }; | 1175 | }; |
1144 | 1176 | ||
1145 | static struct hda_input_mux cxt5047_capture_source = { | ||
1146 | .num_items = 1, | ||
1147 | .items = { | ||
1148 | { "Mic", 0x2 }, | ||
1149 | } | ||
1150 | }; | ||
1151 | |||
1152 | static struct hda_input_mux cxt5047_hp_capture_source = { | ||
1153 | .num_items = 1, | ||
1154 | .items = { | ||
1155 | { "ExtMic", 0x2 }, | ||
1156 | } | ||
1157 | }; | ||
1158 | |||
1159 | static struct hda_input_mux cxt5047_toshiba_capture_source = { | 1177 | static struct hda_input_mux cxt5047_toshiba_capture_source = { |
1160 | .num_items = 2, | 1178 | .num_items = 2, |
1161 | .items = { | 1179 | .items = { |
@@ -1179,7 +1197,11 @@ static int cxt5047_hp_master_sw_put(struct snd_kcontrol *kcontrol, | |||
1179 | * the headphone jack | 1197 | * the headphone jack |
1180 | */ | 1198 | */ |
1181 | bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE; | 1199 | bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE; |
1182 | snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0, | 1200 | /* NOTE: Conexat codec needs the index for *OUTPUT* amp of |
1201 | * pin widgets unlike other codecs. In this case, we need to | ||
1202 | * set index 0x01 for the volume from the mixer amp 0x19. | ||
1203 | */ | ||
1204 | snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0x01, | ||
1183 | HDA_AMP_MUTE, bits); | 1205 | HDA_AMP_MUTE, bits); |
1184 | bits = spec->cur_eapd ? 0 : HDA_AMP_MUTE; | 1206 | bits = spec->cur_eapd ? 0 : HDA_AMP_MUTE; |
1185 | snd_hda_codec_amp_stereo(codec, 0x13, HDA_OUTPUT, 0, | 1207 | snd_hda_codec_amp_stereo(codec, 0x13, HDA_OUTPUT, 0, |
@@ -1187,16 +1209,6 @@ static int cxt5047_hp_master_sw_put(struct snd_kcontrol *kcontrol, | |||
1187 | return 1; | 1209 | return 1; |
1188 | } | 1210 | } |
1189 | 1211 | ||
1190 | /* bind volumes of both NID 0x13 (Headphones) and 0x1d (Speakers) */ | ||
1191 | static struct hda_bind_ctls cxt5047_bind_master_vol = { | ||
1192 | .ops = &snd_hda_bind_vol, | ||
1193 | .values = { | ||
1194 | HDA_COMPOSE_AMP_VAL(0x13, 3, 0, HDA_OUTPUT), | ||
1195 | HDA_COMPOSE_AMP_VAL(0x1d, 3, 0, HDA_OUTPUT), | ||
1196 | 0 | ||
1197 | }, | ||
1198 | }; | ||
1199 | |||
1200 | /* mute internal speaker if HP is plugged */ | 1212 | /* mute internal speaker if HP is plugged */ |
1201 | static void cxt5047_hp_automute(struct hda_codec *codec) | 1213 | static void cxt5047_hp_automute(struct hda_codec *codec) |
1202 | { | 1214 | { |
@@ -1207,27 +1219,8 @@ static void cxt5047_hp_automute(struct hda_codec *codec) | |||
1207 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 1219 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
1208 | 1220 | ||
1209 | bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0; | 1221 | bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0; |
1210 | snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0, | 1222 | /* See the note in cxt5047_hp_master_sw_put */ |
1211 | HDA_AMP_MUTE, bits); | 1223 | snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0x01, |
1212 | /* Mute/Unmute PCM 2 for good measure - some systems need this */ | ||
1213 | snd_hda_codec_amp_stereo(codec, 0x1c, HDA_OUTPUT, 0, | ||
1214 | HDA_AMP_MUTE, bits); | ||
1215 | } | ||
1216 | |||
1217 | /* mute internal speaker if HP is plugged */ | ||
1218 | static void cxt5047_hp2_automute(struct hda_codec *codec) | ||
1219 | { | ||
1220 | struct conexant_spec *spec = codec->spec; | ||
1221 | unsigned int bits; | ||
1222 | |||
1223 | spec->hp_present = snd_hda_codec_read(codec, 0x13, 0, | ||
1224 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
1225 | |||
1226 | bits = spec->hp_present ? HDA_AMP_MUTE : 0; | ||
1227 | snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0, | ||
1228 | HDA_AMP_MUTE, bits); | ||
1229 | /* Mute/Unmute PCM 2 for good measure - some systems need this */ | ||
1230 | snd_hda_codec_amp_stereo(codec, 0x1c, HDA_OUTPUT, 0, | ||
1231 | HDA_AMP_MUTE, bits); | 1224 | HDA_AMP_MUTE, bits); |
1232 | } | 1225 | } |
1233 | 1226 | ||
@@ -1268,55 +1261,14 @@ static void cxt5047_hp_unsol_event(struct hda_codec *codec, | |||
1268 | } | 1261 | } |
1269 | } | 1262 | } |
1270 | 1263 | ||
1271 | /* unsolicited event for HP jack sensing - non-EAPD systems */ | 1264 | static struct snd_kcontrol_new cxt5047_base_mixers[] = { |
1272 | static void cxt5047_hp2_unsol_event(struct hda_codec *codec, | 1265 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x19, 0x02, HDA_INPUT), |
1273 | unsigned int res) | 1266 | HDA_CODEC_MUTE("Mic Playback Switch", 0x19, 0x02, HDA_INPUT), |
1274 | { | 1267 | HDA_CODEC_VOLUME("Mic Boost", 0x1a, 0x0, HDA_OUTPUT), |
1275 | res >>= 26; | ||
1276 | switch (res) { | ||
1277 | case CONEXANT_HP_EVENT: | ||
1278 | cxt5047_hp2_automute(codec); | ||
1279 | break; | ||
1280 | case CONEXANT_MIC_EVENT: | ||
1281 | cxt5047_hp_automic(codec); | ||
1282 | break; | ||
1283 | } | ||
1284 | } | ||
1285 | |||
1286 | static struct snd_kcontrol_new cxt5047_mixers[] = { | ||
1287 | HDA_CODEC_VOLUME("Mic Bypass Capture Volume", 0x19, 0x02, HDA_INPUT), | ||
1288 | HDA_CODEC_MUTE("Mic Bypass Capture Switch", 0x19, 0x02, HDA_INPUT), | ||
1289 | HDA_CODEC_VOLUME("Mic Gain Volume", 0x1a, 0x0, HDA_OUTPUT), | ||
1290 | HDA_CODEC_MUTE("Mic Gain Switch", 0x1a, 0x0, HDA_OUTPUT), | ||
1291 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT), | 1268 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT), |
1292 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT), | 1269 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT), |
1293 | HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT), | 1270 | HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT), |
1294 | HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT), | 1271 | HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT), |
1295 | HDA_CODEC_VOLUME("PCM-2 Volume", 0x1c, 0x00, HDA_OUTPUT), | ||
1296 | HDA_CODEC_MUTE("PCM-2 Switch", 0x1c, 0x00, HDA_OUTPUT), | ||
1297 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x00, HDA_OUTPUT), | ||
1298 | HDA_CODEC_MUTE("Speaker Playback Switch", 0x1d, 0x00, HDA_OUTPUT), | ||
1299 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x13, 0x00, HDA_OUTPUT), | ||
1300 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x13, 0x00, HDA_OUTPUT), | ||
1301 | |||
1302 | {} | ||
1303 | }; | ||
1304 | |||
1305 | static struct snd_kcontrol_new cxt5047_toshiba_mixers[] = { | ||
1306 | { | ||
1307 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1308 | .name = "Capture Source", | ||
1309 | .info = conexant_mux_enum_info, | ||
1310 | .get = conexant_mux_enum_get, | ||
1311 | .put = conexant_mux_enum_put | ||
1312 | }, | ||
1313 | HDA_CODEC_VOLUME("Mic Bypass Capture Volume", 0x19, 0x02, HDA_INPUT), | ||
1314 | HDA_CODEC_MUTE("Mic Bypass Capture Switch", 0x19, 0x02, HDA_INPUT), | ||
1315 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT), | ||
1316 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT), | ||
1317 | HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT), | ||
1318 | HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT), | ||
1319 | HDA_BIND_VOL("Master Playback Volume", &cxt5047_bind_master_vol), | ||
1320 | { | 1272 | { |
1321 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1273 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1322 | .name = "Master Playback Switch", | 1274 | .name = "Master Playback Switch", |
@@ -1329,29 +1281,15 @@ static struct snd_kcontrol_new cxt5047_toshiba_mixers[] = { | |||
1329 | {} | 1281 | {} |
1330 | }; | 1282 | }; |
1331 | 1283 | ||
1332 | static struct snd_kcontrol_new cxt5047_hp_mixers[] = { | 1284 | static struct snd_kcontrol_new cxt5047_hp_spk_mixers[] = { |
1333 | { | 1285 | /* See the note in cxt5047_hp_master_sw_put */ |
1334 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1286 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x01, HDA_OUTPUT), |
1335 | .name = "Capture Source", | 1287 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x13, 0x00, HDA_OUTPUT), |
1336 | .info = conexant_mux_enum_info, | 1288 | {} |
1337 | .get = conexant_mux_enum_get, | 1289 | }; |
1338 | .put = conexant_mux_enum_put | 1290 | |
1339 | }, | 1291 | static struct snd_kcontrol_new cxt5047_hp_only_mixers[] = { |
1340 | HDA_CODEC_VOLUME("Mic Bypass Capture Volume", 0x19, 0x02, HDA_INPUT), | ||
1341 | HDA_CODEC_MUTE("Mic Bypass Capture Switch", 0x19,0x02,HDA_INPUT), | ||
1342 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT), | ||
1343 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT), | ||
1344 | HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT), | ||
1345 | HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT), | ||
1346 | HDA_CODEC_VOLUME("Master Playback Volume", 0x13, 0x00, HDA_OUTPUT), | 1292 | HDA_CODEC_VOLUME("Master Playback Volume", 0x13, 0x00, HDA_OUTPUT), |
1347 | { | ||
1348 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1349 | .name = "Master Playback Switch", | ||
1350 | .info = cxt_eapd_info, | ||
1351 | .get = cxt_eapd_get, | ||
1352 | .put = cxt5047_hp_master_sw_put, | ||
1353 | .private_value = 0x13, | ||
1354 | }, | ||
1355 | { } /* end */ | 1293 | { } /* end */ |
1356 | }; | 1294 | }; |
1357 | 1295 | ||
@@ -1362,8 +1300,8 @@ static struct hda_verb cxt5047_init_verbs[] = { | |||
1362 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 }, | 1300 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 }, |
1363 | /* HP, Speaker */ | 1301 | /* HP, Speaker */ |
1364 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | 1302 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, |
1365 | {0x13, AC_VERB_SET_CONNECT_SEL,0x1}, | 1303 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x0}, /* mixer(0x19) */ |
1366 | {0x1d, AC_VERB_SET_CONNECT_SEL,0x0}, | 1304 | {0x1d, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mixer(0x19) */ |
1367 | /* Record selector: Mic */ | 1305 | /* Record selector: Mic */ |
1368 | {0x12, AC_VERB_SET_CONNECT_SEL,0x03}, | 1306 | {0x12, AC_VERB_SET_CONNECT_SEL,0x03}, |
1369 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, | 1307 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, |
@@ -1383,30 +1321,7 @@ static struct hda_verb cxt5047_init_verbs[] = { | |||
1383 | 1321 | ||
1384 | /* configuration for Toshiba Laptops */ | 1322 | /* configuration for Toshiba Laptops */ |
1385 | static struct hda_verb cxt5047_toshiba_init_verbs[] = { | 1323 | static struct hda_verb cxt5047_toshiba_init_verbs[] = { |
1386 | {0x13, AC_VERB_SET_EAPD_BTLENABLE, 0x0 }, /* default on */ | 1324 | {0x13, AC_VERB_SET_EAPD_BTLENABLE, 0x0}, /* default off */ |
1387 | /* pin sensing on HP and Mic jacks */ | ||
1388 | {0x13, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, | ||
1389 | {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, | ||
1390 | /* Speaker routing */ | ||
1391 | {0x1d, AC_VERB_SET_CONNECT_SEL,0x1}, | ||
1392 | {} | ||
1393 | }; | ||
1394 | |||
1395 | /* configuration for HP Laptops */ | ||
1396 | static struct hda_verb cxt5047_hp_init_verbs[] = { | ||
1397 | /* pin sensing on HP jack */ | ||
1398 | {0x13, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, | ||
1399 | /* 0x13 is actually shared by both HP and speaker; | ||
1400 | * setting the connection to 0 (=0x19) makes the master volume control | ||
1401 | * working mysteriouslly... | ||
1402 | */ | ||
1403 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
1404 | /* Record selector: Ext Mic */ | ||
1405 | {0x12, AC_VERB_SET_CONNECT_SEL,0x03}, | ||
1406 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, | ||
1407 | AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, | ||
1408 | /* Speaker routing */ | ||
1409 | {0x1d, AC_VERB_SET_CONNECT_SEL,0x1}, | ||
1410 | {} | 1325 | {} |
1411 | }; | 1326 | }; |
1412 | 1327 | ||
@@ -1571,11 +1486,9 @@ static const char *cxt5047_models[CXT5047_MODELS] = { | |||
1571 | }; | 1486 | }; |
1572 | 1487 | ||
1573 | static struct snd_pci_quirk cxt5047_cfg_tbl[] = { | 1488 | static struct snd_pci_quirk cxt5047_cfg_tbl[] = { |
1574 | SND_PCI_QUIRK(0x103c, 0x30a0, "HP DV1000", CXT5047_LAPTOP), | ||
1575 | SND_PCI_QUIRK(0x103c, 0x30a5, "HP DV5200T/DV8000T", CXT5047_LAPTOP_HP), | 1489 | SND_PCI_QUIRK(0x103c, 0x30a5, "HP DV5200T/DV8000T", CXT5047_LAPTOP_HP), |
1576 | SND_PCI_QUIRK(0x103c, 0x30b2, "HP DV2000T/DV3000T", CXT5047_LAPTOP), | 1490 | SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3000, "HP DV Series", |
1577 | SND_PCI_QUIRK(0x103c, 0x30b5, "HP DV2000Z", CXT5047_LAPTOP), | 1491 | CXT5047_LAPTOP), |
1578 | SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV6700", CXT5047_LAPTOP), | ||
1579 | SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P100", CXT5047_LAPTOP_EAPD), | 1492 | SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P100", CXT5047_LAPTOP_EAPD), |
1580 | {} | 1493 | {} |
1581 | }; | 1494 | }; |
@@ -1589,6 +1502,7 @@ static int patch_cxt5047(struct hda_codec *codec) | |||
1589 | if (!spec) | 1502 | if (!spec) |
1590 | return -ENOMEM; | 1503 | return -ENOMEM; |
1591 | codec->spec = spec; | 1504 | codec->spec = spec; |
1505 | codec->pin_amp_workaround = 1; | ||
1592 | 1506 | ||
1593 | spec->multiout.max_channels = 2; | 1507 | spec->multiout.max_channels = 2; |
1594 | spec->multiout.num_dacs = ARRAY_SIZE(cxt5047_dac_nids); | 1508 | spec->multiout.num_dacs = ARRAY_SIZE(cxt5047_dac_nids); |
@@ -1597,9 +1511,8 @@ static int patch_cxt5047(struct hda_codec *codec) | |||
1597 | spec->num_adc_nids = 1; | 1511 | spec->num_adc_nids = 1; |
1598 | spec->adc_nids = cxt5047_adc_nids; | 1512 | spec->adc_nids = cxt5047_adc_nids; |
1599 | spec->capsrc_nids = cxt5047_capsrc_nids; | 1513 | spec->capsrc_nids = cxt5047_capsrc_nids; |
1600 | spec->input_mux = &cxt5047_capture_source; | ||
1601 | spec->num_mixers = 1; | 1514 | spec->num_mixers = 1; |
1602 | spec->mixers[0] = cxt5047_mixers; | 1515 | spec->mixers[0] = cxt5047_base_mixers; |
1603 | spec->num_init_verbs = 1; | 1516 | spec->num_init_verbs = 1; |
1604 | spec->init_verbs[0] = cxt5047_init_verbs; | 1517 | spec->init_verbs[0] = cxt5047_init_verbs; |
1605 | spec->spdif_route = 0; | 1518 | spec->spdif_route = 0; |
@@ -1613,21 +1526,22 @@ static int patch_cxt5047(struct hda_codec *codec) | |||
1613 | cxt5047_cfg_tbl); | 1526 | cxt5047_cfg_tbl); |
1614 | switch (board_config) { | 1527 | switch (board_config) { |
1615 | case CXT5047_LAPTOP: | 1528 | case CXT5047_LAPTOP: |
1616 | codec->patch_ops.unsol_event = cxt5047_hp2_unsol_event; | 1529 | spec->num_mixers = 2; |
1530 | spec->mixers[1] = cxt5047_hp_spk_mixers; | ||
1531 | codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; | ||
1617 | break; | 1532 | break; |
1618 | case CXT5047_LAPTOP_HP: | 1533 | case CXT5047_LAPTOP_HP: |
1619 | spec->input_mux = &cxt5047_hp_capture_source; | 1534 | spec->num_mixers = 2; |
1620 | spec->num_init_verbs = 2; | 1535 | spec->mixers[1] = cxt5047_hp_only_mixers; |
1621 | spec->init_verbs[1] = cxt5047_hp_init_verbs; | ||
1622 | spec->mixers[0] = cxt5047_hp_mixers; | ||
1623 | codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; | 1536 | codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; |
1624 | codec->patch_ops.init = cxt5047_hp_init; | 1537 | codec->patch_ops.init = cxt5047_hp_init; |
1625 | break; | 1538 | break; |
1626 | case CXT5047_LAPTOP_EAPD: | 1539 | case CXT5047_LAPTOP_EAPD: |
1627 | spec->input_mux = &cxt5047_toshiba_capture_source; | 1540 | spec->input_mux = &cxt5047_toshiba_capture_source; |
1541 | spec->num_mixers = 2; | ||
1542 | spec->mixers[1] = cxt5047_hp_spk_mixers; | ||
1628 | spec->num_init_verbs = 2; | 1543 | spec->num_init_verbs = 2; |
1629 | spec->init_verbs[1] = cxt5047_toshiba_init_verbs; | 1544 | spec->init_verbs[1] = cxt5047_toshiba_init_verbs; |
1630 | spec->mixers[0] = cxt5047_toshiba_mixers; | ||
1631 | codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; | 1545 | codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; |
1632 | break; | 1546 | break; |
1633 | #ifdef CONFIG_SND_DEBUG | 1547 | #ifdef CONFIG_SND_DEBUG |
@@ -1638,6 +1552,7 @@ static int patch_cxt5047(struct hda_codec *codec) | |||
1638 | codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; | 1552 | codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; |
1639 | #endif | 1553 | #endif |
1640 | } | 1554 | } |
1555 | spec->vmaster_nid = 0x13; | ||
1641 | return 0; | 1556 | return 0; |
1642 | } | 1557 | } |
1643 | 1558 | ||
@@ -1673,8 +1588,11 @@ static int cxt5051_hp_master_sw_put(struct snd_kcontrol *kcontrol, | |||
1673 | /* toggle input of built-in and mic jack appropriately */ | 1588 | /* toggle input of built-in and mic jack appropriately */ |
1674 | static void cxt5051_portb_automic(struct hda_codec *codec) | 1589 | static void cxt5051_portb_automic(struct hda_codec *codec) |
1675 | { | 1590 | { |
1591 | struct conexant_spec *spec = codec->spec; | ||
1676 | unsigned int present; | 1592 | unsigned int present; |
1677 | 1593 | ||
1594 | if (spec->no_auto_mic) | ||
1595 | return; | ||
1678 | present = snd_hda_codec_read(codec, 0x17, 0, | 1596 | present = snd_hda_codec_read(codec, 0x17, 0, |
1679 | AC_VERB_GET_PIN_SENSE, 0) & | 1597 | AC_VERB_GET_PIN_SENSE, 0) & |
1680 | AC_PINSENSE_PRESENCE; | 1598 | AC_PINSENSE_PRESENCE; |
@@ -1690,6 +1608,8 @@ static void cxt5051_portc_automic(struct hda_codec *codec) | |||
1690 | unsigned int present; | 1608 | unsigned int present; |
1691 | hda_nid_t new_adc; | 1609 | hda_nid_t new_adc; |
1692 | 1610 | ||
1611 | if (spec->no_auto_mic) | ||
1612 | return; | ||
1693 | present = snd_hda_codec_read(codec, 0x18, 0, | 1613 | present = snd_hda_codec_read(codec, 0x18, 0, |
1694 | AC_VERB_GET_PIN_SENSE, 0) & | 1614 | AC_VERB_GET_PIN_SENSE, 0) & |
1695 | AC_PINSENSE_PRESENCE; | 1615 | AC_PINSENSE_PRESENCE; |
@@ -1776,6 +1696,22 @@ static struct snd_kcontrol_new cxt5051_hp_mixers[] = { | |||
1776 | {} | 1696 | {} |
1777 | }; | 1697 | }; |
1778 | 1698 | ||
1699 | static struct snd_kcontrol_new cxt5051_hp_dv6736_mixers[] = { | ||
1700 | HDA_CODEC_VOLUME("Mic Volume", 0x14, 0x00, HDA_INPUT), | ||
1701 | HDA_CODEC_MUTE("Mic Switch", 0x14, 0x00, HDA_INPUT), | ||
1702 | HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT), | ||
1703 | { | ||
1704 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1705 | .name = "Master Playback Switch", | ||
1706 | .info = cxt_eapd_info, | ||
1707 | .get = cxt_eapd_get, | ||
1708 | .put = cxt5051_hp_master_sw_put, | ||
1709 | .private_value = 0x1a, | ||
1710 | }, | ||
1711 | |||
1712 | {} | ||
1713 | }; | ||
1714 | |||
1779 | static struct hda_verb cxt5051_init_verbs[] = { | 1715 | static struct hda_verb cxt5051_init_verbs[] = { |
1780 | /* Line in, Mic */ | 1716 | /* Line in, Mic */ |
1781 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, | 1717 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, |
@@ -1806,6 +1742,66 @@ static struct hda_verb cxt5051_init_verbs[] = { | |||
1806 | { } /* end */ | 1742 | { } /* end */ |
1807 | }; | 1743 | }; |
1808 | 1744 | ||
1745 | static struct hda_verb cxt5051_hp_dv6736_init_verbs[] = { | ||
1746 | /* Line in, Mic */ | ||
1747 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, | ||
1748 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1749 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0}, | ||
1750 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0}, | ||
1751 | /* SPK */ | ||
1752 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1753 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1754 | /* HP, Amp */ | ||
1755 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
1756 | {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1757 | /* DAC1 */ | ||
1758 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1759 | /* Record selector: Int mic */ | ||
1760 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, | ||
1761 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x1}, | ||
1762 | /* SPDIF route: PCM */ | ||
1763 | {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
1764 | /* EAPD */ | ||
1765 | {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | ||
1766 | {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT}, | ||
1767 | {0x17, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTB_EVENT}, | ||
1768 | { } /* end */ | ||
1769 | }; | ||
1770 | |||
1771 | static struct hda_verb cxt5051_lenovo_x200_init_verbs[] = { | ||
1772 | /* Line in, Mic */ | ||
1773 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, | ||
1774 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1775 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, | ||
1776 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1777 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
1778 | {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, | ||
1779 | /* SPK */ | ||
1780 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1781 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1782 | /* HP, Amp */ | ||
1783 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
1784 | {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1785 | /* Docking HP */ | ||
1786 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
1787 | {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1788 | /* DAC1 */ | ||
1789 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1790 | /* Record selector: Int mic */ | ||
1791 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44}, | ||
1792 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, | ||
1793 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44}, | ||
1794 | /* SPDIF route: PCM */ | ||
1795 | {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
1796 | /* EAPD */ | ||
1797 | {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | ||
1798 | {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT}, | ||
1799 | {0x17, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTB_EVENT}, | ||
1800 | {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTC_EVENT}, | ||
1801 | {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT}, | ||
1802 | { } /* end */ | ||
1803 | }; | ||
1804 | |||
1809 | /* initialize jack-sensing, too */ | 1805 | /* initialize jack-sensing, too */ |
1810 | static int cxt5051_init(struct hda_codec *codec) | 1806 | static int cxt5051_init(struct hda_codec *codec) |
1811 | { | 1807 | { |
@@ -1823,18 +1819,24 @@ static int cxt5051_init(struct hda_codec *codec) | |||
1823 | enum { | 1819 | enum { |
1824 | CXT5051_LAPTOP, /* Laptops w/ EAPD support */ | 1820 | CXT5051_LAPTOP, /* Laptops w/ EAPD support */ |
1825 | CXT5051_HP, /* no docking */ | 1821 | CXT5051_HP, /* no docking */ |
1822 | CXT5051_HP_DV6736, /* HP without mic switch */ | ||
1823 | CXT5051_LENOVO_X200, /* Lenovo X200 laptop */ | ||
1826 | CXT5051_MODELS | 1824 | CXT5051_MODELS |
1827 | }; | 1825 | }; |
1828 | 1826 | ||
1829 | static const char *cxt5051_models[CXT5051_MODELS] = { | 1827 | static const char *cxt5051_models[CXT5051_MODELS] = { |
1830 | [CXT5051_LAPTOP] = "laptop", | 1828 | [CXT5051_LAPTOP] = "laptop", |
1831 | [CXT5051_HP] = "hp", | 1829 | [CXT5051_HP] = "hp", |
1830 | [CXT5051_HP_DV6736] = "hp-dv6736", | ||
1831 | [CXT5051_LENOVO_X200] = "lenovo-x200", | ||
1832 | }; | 1832 | }; |
1833 | 1833 | ||
1834 | static struct snd_pci_quirk cxt5051_cfg_tbl[] = { | 1834 | static struct snd_pci_quirk cxt5051_cfg_tbl[] = { |
1835 | SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV6736", CXT5051_HP_DV6736), | ||
1835 | SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board", | 1836 | SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board", |
1836 | CXT5051_LAPTOP), | 1837 | CXT5051_LAPTOP), |
1837 | SND_PCI_QUIRK(0x14f1, 0x5051, "HP Spartan 1.1", CXT5051_HP), | 1838 | SND_PCI_QUIRK(0x14f1, 0x5051, "HP Spartan 1.1", CXT5051_HP), |
1839 | SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo X200", CXT5051_LENOVO_X200), | ||
1838 | {} | 1840 | {} |
1839 | }; | 1841 | }; |
1840 | 1842 | ||
@@ -1847,6 +1849,7 @@ static int patch_cxt5051(struct hda_codec *codec) | |||
1847 | if (!spec) | 1849 | if (!spec) |
1848 | return -ENOMEM; | 1850 | return -ENOMEM; |
1849 | codec->spec = spec; | 1851 | codec->spec = spec; |
1852 | codec->pin_amp_workaround = 1; | ||
1850 | 1853 | ||
1851 | codec->patch_ops = conexant_patch_ops; | 1854 | codec->patch_ops = conexant_patch_ops; |
1852 | codec->patch_ops.init = cxt5051_init; | 1855 | codec->patch_ops.init = cxt5051_init; |
@@ -1867,17 +1870,22 @@ static int patch_cxt5051(struct hda_codec *codec) | |||
1867 | spec->cur_adc = 0; | 1870 | spec->cur_adc = 0; |
1868 | spec->cur_adc_idx = 0; | 1871 | spec->cur_adc_idx = 0; |
1869 | 1872 | ||
1873 | codec->patch_ops.unsol_event = cxt5051_hp_unsol_event; | ||
1874 | |||
1870 | board_config = snd_hda_check_board_config(codec, CXT5051_MODELS, | 1875 | board_config = snd_hda_check_board_config(codec, CXT5051_MODELS, |
1871 | cxt5051_models, | 1876 | cxt5051_models, |
1872 | cxt5051_cfg_tbl); | 1877 | cxt5051_cfg_tbl); |
1873 | switch (board_config) { | 1878 | switch (board_config) { |
1874 | case CXT5051_HP: | 1879 | case CXT5051_HP: |
1875 | codec->patch_ops.unsol_event = cxt5051_hp_unsol_event; | ||
1876 | spec->mixers[0] = cxt5051_hp_mixers; | 1880 | spec->mixers[0] = cxt5051_hp_mixers; |
1877 | break; | 1881 | break; |
1878 | default: | 1882 | case CXT5051_HP_DV6736: |
1879 | case CXT5051_LAPTOP: | 1883 | spec->init_verbs[0] = cxt5051_hp_dv6736_init_verbs; |
1880 | codec->patch_ops.unsol_event = cxt5051_hp_unsol_event; | 1884 | spec->mixers[0] = cxt5051_hp_dv6736_mixers; |
1885 | spec->no_auto_mic = 1; | ||
1886 | break; | ||
1887 | case CXT5051_LENOVO_X200: | ||
1888 | spec->init_verbs[0] = cxt5051_lenovo_x200_init_verbs; | ||
1881 | break; | 1889 | break; |
1882 | } | 1890 | } |
1883 | 1891 | ||
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 6c26afcb8262..82097790f6f3 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <sound/core.h> | 30 | #include <sound/core.h> |
31 | #include "hda_codec.h" | 31 | #include "hda_codec.h" |
32 | #include "hda_local.h" | 32 | #include "hda_local.h" |
33 | #include "hda_beep.h" | ||
33 | 34 | ||
34 | #define ALC880_FRONT_EVENT 0x01 | 35 | #define ALC880_FRONT_EVENT 0x01 |
35 | #define ALC880_DCVOL_EVENT 0x02 | 36 | #define ALC880_DCVOL_EVENT 0x02 |
@@ -77,6 +78,7 @@ enum { | |||
77 | ALC260_ACER, | 78 | ALC260_ACER, |
78 | ALC260_WILL, | 79 | ALC260_WILL, |
79 | ALC260_REPLACER_672V, | 80 | ALC260_REPLACER_672V, |
81 | ALC260_FAVORIT100, | ||
80 | #ifdef CONFIG_SND_DEBUG | 82 | #ifdef CONFIG_SND_DEBUG |
81 | ALC260_TEST, | 83 | ALC260_TEST, |
82 | #endif | 84 | #endif |
@@ -103,6 +105,7 @@ enum { | |||
103 | ALC262_NEC, | 105 | ALC262_NEC, |
104 | ALC262_TOSHIBA_S06, | 106 | ALC262_TOSHIBA_S06, |
105 | ALC262_TOSHIBA_RX1, | 107 | ALC262_TOSHIBA_RX1, |
108 | ALC262_TYAN, | ||
106 | ALC262_AUTO, | 109 | ALC262_AUTO, |
107 | ALC262_MODEL_LAST /* last tag */ | 110 | ALC262_MODEL_LAST /* last tag */ |
108 | }; | 111 | }; |
@@ -238,6 +241,13 @@ enum { | |||
238 | ALC883_MODEL_LAST, | 241 | ALC883_MODEL_LAST, |
239 | }; | 242 | }; |
240 | 243 | ||
244 | /* styles of capture selection */ | ||
245 | enum { | ||
246 | CAPT_MUX = 0, /* only mux based */ | ||
247 | CAPT_MIX, /* only mixer based */ | ||
248 | CAPT_1MUX_MIX, /* first mux and other mixers */ | ||
249 | }; | ||
250 | |||
241 | /* for GPIO Poll */ | 251 | /* for GPIO Poll */ |
242 | #define GPIO_MASK 0x03 | 252 | #define GPIO_MASK 0x03 |
243 | 253 | ||
@@ -246,6 +256,7 @@ struct alc_spec { | |||
246 | struct snd_kcontrol_new *mixers[5]; /* mixer arrays */ | 256 | struct snd_kcontrol_new *mixers[5]; /* mixer arrays */ |
247 | unsigned int num_mixers; | 257 | unsigned int num_mixers; |
248 | struct snd_kcontrol_new *cap_mixer; /* capture mixer */ | 258 | struct snd_kcontrol_new *cap_mixer; /* capture mixer */ |
259 | unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */ | ||
249 | 260 | ||
250 | const struct hda_verb *init_verbs[5]; /* initialization verbs | 261 | const struct hda_verb *init_verbs[5]; /* initialization verbs |
251 | * don't forget NULL | 262 | * don't forget NULL |
@@ -269,13 +280,15 @@ struct alc_spec { | |||
269 | * dig_out_nid and hp_nid are optional | 280 | * dig_out_nid and hp_nid are optional |
270 | */ | 281 | */ |
271 | hda_nid_t alt_dac_nid; | 282 | hda_nid_t alt_dac_nid; |
283 | hda_nid_t slave_dig_outs[3]; /* optional - for auto-parsing */ | ||
284 | int dig_out_type; | ||
272 | 285 | ||
273 | /* capture */ | 286 | /* capture */ |
274 | unsigned int num_adc_nids; | 287 | unsigned int num_adc_nids; |
275 | hda_nid_t *adc_nids; | 288 | hda_nid_t *adc_nids; |
276 | hda_nid_t *capsrc_nids; | 289 | hda_nid_t *capsrc_nids; |
277 | hda_nid_t dig_in_nid; /* digital-in NID; optional */ | 290 | hda_nid_t dig_in_nid; /* digital-in NID; optional */ |
278 | unsigned char is_mix_capture; /* matrix-style capture (non-mux) */ | 291 | int capture_style; /* capture style (CAPT_*) */ |
279 | 292 | ||
280 | /* capture source */ | 293 | /* capture source */ |
281 | unsigned int num_mux_defs; | 294 | unsigned int num_mux_defs; |
@@ -293,7 +306,7 @@ struct alc_spec { | |||
293 | /* dynamic controls, init_verbs and input_mux */ | 306 | /* dynamic controls, init_verbs and input_mux */ |
294 | struct auto_pin_cfg autocfg; | 307 | struct auto_pin_cfg autocfg; |
295 | struct snd_array kctls; | 308 | struct snd_array kctls; |
296 | struct hda_input_mux private_imux; | 309 | struct hda_input_mux private_imux[3]; |
297 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; | 310 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; |
298 | 311 | ||
299 | /* hooks */ | 312 | /* hooks */ |
@@ -305,6 +318,9 @@ struct alc_spec { | |||
305 | unsigned int jack_present: 1; | 318 | unsigned int jack_present: 1; |
306 | unsigned int master_sw: 1; | 319 | unsigned int master_sw: 1; |
307 | 320 | ||
321 | /* other flags */ | ||
322 | unsigned int no_analog :1; /* digital I/O only */ | ||
323 | |||
308 | /* for virtual master */ | 324 | /* for virtual master */ |
309 | hda_nid_t vmaster_nid; | 325 | hda_nid_t vmaster_nid; |
310 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 326 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
@@ -314,13 +330,6 @@ struct alc_spec { | |||
314 | /* for PLL fix */ | 330 | /* for PLL fix */ |
315 | hda_nid_t pll_nid; | 331 | hda_nid_t pll_nid; |
316 | unsigned int pll_coef_idx, pll_coef_bit; | 332 | unsigned int pll_coef_idx, pll_coef_bit; |
317 | |||
318 | #ifdef SND_HDA_NEEDS_RESUME | ||
319 | #define ALC_MAX_PINS 16 | ||
320 | unsigned int num_pins; | ||
321 | hda_nid_t pin_nids[ALC_MAX_PINS]; | ||
322 | unsigned int pin_cfgs[ALC_MAX_PINS]; | ||
323 | #endif | ||
324 | }; | 333 | }; |
325 | 334 | ||
326 | /* | 335 | /* |
@@ -336,6 +345,7 @@ struct alc_config_preset { | |||
336 | hda_nid_t *dac_nids; | 345 | hda_nid_t *dac_nids; |
337 | hda_nid_t dig_out_nid; /* optional */ | 346 | hda_nid_t dig_out_nid; /* optional */ |
338 | hda_nid_t hp_nid; /* optional */ | 347 | hda_nid_t hp_nid; /* optional */ |
348 | hda_nid_t *slave_dig_outs; | ||
339 | unsigned int num_adc_nids; | 349 | unsigned int num_adc_nids; |
340 | hda_nid_t *adc_nids; | 350 | hda_nid_t *adc_nids; |
341 | hda_nid_t *capsrc_nids; | 351 | hda_nid_t *capsrc_nids; |
@@ -392,7 +402,8 @@ static int alc_mux_enum_put(struct snd_kcontrol *kcontrol, | |||
392 | mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx; | 402 | mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx; |
393 | imux = &spec->input_mux[mux_idx]; | 403 | imux = &spec->input_mux[mux_idx]; |
394 | 404 | ||
395 | if (spec->is_mix_capture) { | 405 | if (spec->capture_style && |
406 | !(spec->capture_style == CAPT_1MUX_MIX && !adc_idx)) { | ||
396 | /* Matrix-mixer style (e.g. ALC882) */ | 407 | /* Matrix-mixer style (e.g. ALC882) */ |
397 | unsigned int *cur_val = &spec->cur_mux[adc_idx]; | 408 | unsigned int *cur_val = &spec->cur_mux[adc_idx]; |
398 | unsigned int i, idx; | 409 | unsigned int i, idx; |
@@ -750,6 +761,24 @@ static int alc_eapd_ctrl_put(struct snd_kcontrol *kcontrol, | |||
750 | #endif /* CONFIG_SND_DEBUG */ | 761 | #endif /* CONFIG_SND_DEBUG */ |
751 | 762 | ||
752 | /* | 763 | /* |
764 | * set up the input pin config (depending on the given auto-pin type) | ||
765 | */ | ||
766 | static void alc_set_input_pin(struct hda_codec *codec, hda_nid_t nid, | ||
767 | int auto_pin_type) | ||
768 | { | ||
769 | unsigned int val = PIN_IN; | ||
770 | |||
771 | if (auto_pin_type <= AUTO_PIN_FRONT_MIC) { | ||
772 | unsigned int pincap; | ||
773 | pincap = snd_hda_query_pin_caps(codec, nid); | ||
774 | pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT; | ||
775 | if (pincap & AC_PINCAP_VREF_80) | ||
776 | val = PIN_VREF80; | ||
777 | } | ||
778 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, val); | ||
779 | } | ||
780 | |||
781 | /* | ||
753 | */ | 782 | */ |
754 | static void add_mixer(struct alc_spec *spec, struct snd_kcontrol_new *mix) | 783 | static void add_mixer(struct alc_spec *spec, struct snd_kcontrol_new *mix) |
755 | { | 784 | { |
@@ -810,6 +839,7 @@ static void setup_preset(struct alc_spec *spec, | |||
810 | spec->multiout.num_dacs = preset->num_dacs; | 839 | spec->multiout.num_dacs = preset->num_dacs; |
811 | spec->multiout.dac_nids = preset->dac_nids; | 840 | spec->multiout.dac_nids = preset->dac_nids; |
812 | spec->multiout.dig_out_nid = preset->dig_out_nid; | 841 | spec->multiout.dig_out_nid = preset->dig_out_nid; |
842 | spec->multiout.slave_dig_outs = preset->slave_dig_outs; | ||
813 | spec->multiout.hp_nid = preset->hp_nid; | 843 | spec->multiout.hp_nid = preset->hp_nid; |
814 | 844 | ||
815 | spec->num_mux_defs = preset->num_mux_defs; | 845 | spec->num_mux_defs = preset->num_mux_defs; |
@@ -921,7 +951,7 @@ static void alc_mic_automute(struct hda_codec *codec) | |||
921 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); | 951 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); |
922 | } | 952 | } |
923 | #else | 953 | #else |
924 | #define alc_mic_automute(codec) /* NOP */ | 954 | #define alc_mic_automute(codec) do {} while(0) /* NOP */ |
925 | #endif /* disabled */ | 955 | #endif /* disabled */ |
926 | 956 | ||
927 | /* unsolicited event for HP jack sensing */ | 957 | /* unsolicited event for HP jack sensing */ |
@@ -952,7 +982,7 @@ static void alc888_coef_init(struct hda_codec *codec) | |||
952 | snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 0); | 982 | snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 0); |
953 | tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0); | 983 | tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0); |
954 | snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7); | 984 | snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7); |
955 | if ((tmp & 0xf0) == 2) | 985 | if ((tmp & 0xf0) == 0x20) |
956 | /* alc888S-VC */ | 986 | /* alc888S-VC */ |
957 | snd_hda_codec_read(codec, 0x20, 0, | 987 | snd_hda_codec_read(codec, 0x20, 0, |
958 | AC_VERB_SET_PROC_COEF, 0x830); | 988 | AC_VERB_SET_PROC_COEF, 0x830); |
@@ -991,8 +1021,7 @@ static void alc_subsystem_id(struct hda_codec *codec, | |||
991 | nid = 0x1d; | 1021 | nid = 0x1d; |
992 | if (codec->vendor_id == 0x10ec0260) | 1022 | if (codec->vendor_id == 0x10ec0260) |
993 | nid = 0x17; | 1023 | nid = 0x17; |
994 | ass = snd_hda_codec_read(codec, nid, 0, | 1024 | ass = snd_hda_codec_get_pincfg(codec, nid); |
995 | AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
996 | if (!(ass & 1) && !(ass & 0x100000)) | 1025 | if (!(ass & 1) && !(ass & 0x100000)) |
997 | return; | 1026 | return; |
998 | if ((ass >> 30) != 1) /* no physical connection */ | 1027 | if ((ass >> 30) != 1) /* no physical connection */ |
@@ -1166,16 +1195,8 @@ static void alc_fix_pincfg(struct hda_codec *codec, | |||
1166 | return; | 1195 | return; |
1167 | 1196 | ||
1168 | cfg = pinfix[quirk->value]; | 1197 | cfg = pinfix[quirk->value]; |
1169 | for (; cfg->nid; cfg++) { | 1198 | for (; cfg->nid; cfg++) |
1170 | int i; | 1199 | snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val); |
1171 | u32 val = cfg->val; | ||
1172 | for (i = 0; i < 4; i++) { | ||
1173 | snd_hda_codec_write(codec, cfg->nid, 0, | ||
1174 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 + i, | ||
1175 | val & 0xff); | ||
1176 | val >>= 8; | ||
1177 | } | ||
1178 | } | ||
1179 | } | 1200 | } |
1180 | 1201 | ||
1181 | /* | 1202 | /* |
@@ -1375,8 +1396,6 @@ static struct snd_kcontrol_new alc888_base_mixer[] = { | |||
1375 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 1396 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
1376 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 1397 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), |
1377 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 1398 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
1378 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
1379 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
1380 | { } /* end */ | 1399 | { } /* end */ |
1381 | }; | 1400 | }; |
1382 | 1401 | ||
@@ -1483,8 +1502,6 @@ static struct snd_kcontrol_new alc880_three_stack_mixer[] = { | |||
1483 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 1502 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
1484 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT), | 1503 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT), |
1485 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT), | 1504 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT), |
1486 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
1487 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
1488 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT), | 1505 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT), |
1489 | { | 1506 | { |
1490 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1507 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -1578,8 +1595,7 @@ static int alc_cap_sw_put(struct snd_kcontrol *kcontrol, | |||
1578 | snd_hda_mixer_amp_switch_put); | 1595 | snd_hda_mixer_amp_switch_put); |
1579 | } | 1596 | } |
1580 | 1597 | ||
1581 | #define DEFINE_CAPMIX(num) \ | 1598 | #define _DEFINE_CAPMIX(num) \ |
1582 | static struct snd_kcontrol_new alc_capture_mixer ## num[] = { \ | ||
1583 | { \ | 1599 | { \ |
1584 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 1600 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
1585 | .name = "Capture Switch", \ | 1601 | .name = "Capture Switch", \ |
@@ -1600,7 +1616,9 @@ static struct snd_kcontrol_new alc_capture_mixer ## num[] = { \ | |||
1600 | .get = alc_cap_vol_get, \ | 1616 | .get = alc_cap_vol_get, \ |
1601 | .put = alc_cap_vol_put, \ | 1617 | .put = alc_cap_vol_put, \ |
1602 | .tlv = { .c = alc_cap_vol_tlv }, \ | 1618 | .tlv = { .c = alc_cap_vol_tlv }, \ |
1603 | }, \ | 1619 | } |
1620 | |||
1621 | #define _DEFINE_CAPSRC(num) \ | ||
1604 | { \ | 1622 | { \ |
1605 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 1623 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
1606 | /* .name = "Capture Source", */ \ | 1624 | /* .name = "Capture Source", */ \ |
@@ -1609,15 +1627,28 @@ static struct snd_kcontrol_new alc_capture_mixer ## num[] = { \ | |||
1609 | .info = alc_mux_enum_info, \ | 1627 | .info = alc_mux_enum_info, \ |
1610 | .get = alc_mux_enum_get, \ | 1628 | .get = alc_mux_enum_get, \ |
1611 | .put = alc_mux_enum_put, \ | 1629 | .put = alc_mux_enum_put, \ |
1612 | }, \ | 1630 | } |
1613 | { } /* end */ \ | 1631 | |
1632 | #define DEFINE_CAPMIX(num) \ | ||
1633 | static struct snd_kcontrol_new alc_capture_mixer ## num[] = { \ | ||
1634 | _DEFINE_CAPMIX(num), \ | ||
1635 | _DEFINE_CAPSRC(num), \ | ||
1636 | { } /* end */ \ | ||
1637 | } | ||
1638 | |||
1639 | #define DEFINE_CAPMIX_NOSRC(num) \ | ||
1640 | static struct snd_kcontrol_new alc_capture_mixer_nosrc ## num[] = { \ | ||
1641 | _DEFINE_CAPMIX(num), \ | ||
1642 | { } /* end */ \ | ||
1614 | } | 1643 | } |
1615 | 1644 | ||
1616 | /* up to three ADCs */ | 1645 | /* up to three ADCs */ |
1617 | DEFINE_CAPMIX(1); | 1646 | DEFINE_CAPMIX(1); |
1618 | DEFINE_CAPMIX(2); | 1647 | DEFINE_CAPMIX(2); |
1619 | DEFINE_CAPMIX(3); | 1648 | DEFINE_CAPMIX(3); |
1620 | 1649 | DEFINE_CAPMIX_NOSRC(1); | |
1650 | DEFINE_CAPMIX_NOSRC(2); | ||
1651 | DEFINE_CAPMIX_NOSRC(3); | ||
1621 | 1652 | ||
1622 | /* | 1653 | /* |
1623 | * ALC880 5-stack model | 1654 | * ALC880 5-stack model |
@@ -1706,8 +1737,6 @@ static struct snd_kcontrol_new alc880_six_stack_mixer[] = { | |||
1706 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 1737 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
1707 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 1738 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
1708 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 1739 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
1709 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
1710 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
1711 | { | 1740 | { |
1712 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1741 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1713 | .name = "Channel Mode", | 1742 | .name = "Channel Mode", |
@@ -1884,13 +1913,6 @@ static struct snd_kcontrol_new alc880_asus_w1v_mixer[] = { | |||
1884 | { } /* end */ | 1913 | { } /* end */ |
1885 | }; | 1914 | }; |
1886 | 1915 | ||
1887 | /* additional mixers to alc880_asus_mixer */ | ||
1888 | static struct snd_kcontrol_new alc880_pcbeep_mixer[] = { | ||
1889 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
1890 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
1891 | { } /* end */ | ||
1892 | }; | ||
1893 | |||
1894 | /* TCL S700 */ | 1916 | /* TCL S700 */ |
1895 | static struct snd_kcontrol_new alc880_tcl_s700_mixer[] = { | 1917 | static struct snd_kcontrol_new alc880_tcl_s700_mixer[] = { |
1896 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | 1918 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), |
@@ -1923,8 +1945,6 @@ static struct snd_kcontrol_new alc880_uniwill_mixer[] = { | |||
1923 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 1945 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
1924 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 1946 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
1925 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 1947 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
1926 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
1927 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
1928 | { | 1948 | { |
1929 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1949 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1930 | .name = "Channel Mode", | 1950 | .name = "Channel Mode", |
@@ -1999,6 +2019,13 @@ static const char *alc_slave_sws[] = { | |||
1999 | 2019 | ||
2000 | static void alc_free_kctls(struct hda_codec *codec); | 2020 | static void alc_free_kctls(struct hda_codec *codec); |
2001 | 2021 | ||
2022 | /* additional beep mixers; the actual parameters are overwritten at build */ | ||
2023 | static struct snd_kcontrol_new alc_beep_mixer[] = { | ||
2024 | HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_INPUT), | ||
2025 | HDA_CODEC_MUTE("Beep Playback Switch", 0, 0, HDA_INPUT), | ||
2026 | { } /* end */ | ||
2027 | }; | ||
2028 | |||
2002 | static int alc_build_controls(struct hda_codec *codec) | 2029 | static int alc_build_controls(struct hda_codec *codec) |
2003 | { | 2030 | { |
2004 | struct alc_spec *spec = codec->spec; | 2031 | struct alc_spec *spec = codec->spec; |
@@ -2020,11 +2047,13 @@ static int alc_build_controls(struct hda_codec *codec) | |||
2020 | spec->multiout.dig_out_nid); | 2047 | spec->multiout.dig_out_nid); |
2021 | if (err < 0) | 2048 | if (err < 0) |
2022 | return err; | 2049 | return err; |
2023 | err = snd_hda_create_spdif_share_sw(codec, | 2050 | if (!spec->no_analog) { |
2024 | &spec->multiout); | 2051 | err = snd_hda_create_spdif_share_sw(codec, |
2025 | if (err < 0) | 2052 | &spec->multiout); |
2026 | return err; | 2053 | if (err < 0) |
2027 | spec->multiout.share_spdif = 1; | 2054 | return err; |
2055 | spec->multiout.share_spdif = 1; | ||
2056 | } | ||
2028 | } | 2057 | } |
2029 | if (spec->dig_in_nid) { | 2058 | if (spec->dig_in_nid) { |
2030 | err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); | 2059 | err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); |
@@ -2032,8 +2061,24 @@ static int alc_build_controls(struct hda_codec *codec) | |||
2032 | return err; | 2061 | return err; |
2033 | } | 2062 | } |
2034 | 2063 | ||
2064 | /* create beep controls if needed */ | ||
2065 | if (spec->beep_amp) { | ||
2066 | struct snd_kcontrol_new *knew; | ||
2067 | for (knew = alc_beep_mixer; knew->name; knew++) { | ||
2068 | struct snd_kcontrol *kctl; | ||
2069 | kctl = snd_ctl_new1(knew, codec); | ||
2070 | if (!kctl) | ||
2071 | return -ENOMEM; | ||
2072 | kctl->private_value = spec->beep_amp; | ||
2073 | err = snd_hda_ctl_add(codec, kctl); | ||
2074 | if (err < 0) | ||
2075 | return err; | ||
2076 | } | ||
2077 | } | ||
2078 | |||
2035 | /* if we have no master control, let's create it */ | 2079 | /* if we have no master control, let's create it */ |
2036 | if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { | 2080 | if (!spec->no_analog && |
2081 | !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { | ||
2037 | unsigned int vmaster_tlv[4]; | 2082 | unsigned int vmaster_tlv[4]; |
2038 | snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid, | 2083 | snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid, |
2039 | HDA_OUTPUT, vmaster_tlv); | 2084 | HDA_OUTPUT, vmaster_tlv); |
@@ -2042,7 +2087,8 @@ static int alc_build_controls(struct hda_codec *codec) | |||
2042 | if (err < 0) | 2087 | if (err < 0) |
2043 | return err; | 2088 | return err; |
2044 | } | 2089 | } |
2045 | if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { | 2090 | if (!spec->no_analog && |
2091 | !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { | ||
2046 | err = snd_hda_add_vmaster(codec, "Master Playback Switch", | 2092 | err = snd_hda_add_vmaster(codec, "Master Playback Switch", |
2047 | NULL, alc_slave_sws); | 2093 | NULL, alc_slave_sws); |
2048 | if (err < 0) | 2094 | if (err < 0) |
@@ -2951,6 +2997,14 @@ static int alc880_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | |||
2951 | stream_tag, format, substream); | 2997 | stream_tag, format, substream); |
2952 | } | 2998 | } |
2953 | 2999 | ||
3000 | static int alc880_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
3001 | struct hda_codec *codec, | ||
3002 | struct snd_pcm_substream *substream) | ||
3003 | { | ||
3004 | struct alc_spec *spec = codec->spec; | ||
3005 | return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout); | ||
3006 | } | ||
3007 | |||
2954 | static int alc880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, | 3008 | static int alc880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, |
2955 | struct hda_codec *codec, | 3009 | struct hda_codec *codec, |
2956 | struct snd_pcm_substream *substream) | 3010 | struct snd_pcm_substream *substream) |
@@ -3034,7 +3088,8 @@ static struct hda_pcm_stream alc880_pcm_digital_playback = { | |||
3034 | .ops = { | 3088 | .ops = { |
3035 | .open = alc880_dig_playback_pcm_open, | 3089 | .open = alc880_dig_playback_pcm_open, |
3036 | .close = alc880_dig_playback_pcm_close, | 3090 | .close = alc880_dig_playback_pcm_close, |
3037 | .prepare = alc880_dig_playback_pcm_prepare | 3091 | .prepare = alc880_dig_playback_pcm_prepare, |
3092 | .cleanup = alc880_dig_playback_pcm_cleanup | ||
3038 | }, | 3093 | }, |
3039 | }; | 3094 | }; |
3040 | 3095 | ||
@@ -3061,6 +3116,9 @@ static int alc_build_pcms(struct hda_codec *codec) | |||
3061 | codec->num_pcms = 1; | 3116 | codec->num_pcms = 1; |
3062 | codec->pcm_info = info; | 3117 | codec->pcm_info = info; |
3063 | 3118 | ||
3119 | if (spec->no_analog) | ||
3120 | goto skip_analog; | ||
3121 | |||
3064 | info->name = spec->stream_name_analog; | 3122 | info->name = spec->stream_name_analog; |
3065 | if (spec->stream_analog_playback) { | 3123 | if (spec->stream_analog_playback) { |
3066 | if (snd_BUG_ON(!spec->multiout.dac_nids)) | 3124 | if (snd_BUG_ON(!spec->multiout.dac_nids)) |
@@ -3084,12 +3142,17 @@ static int alc_build_pcms(struct hda_codec *codec) | |||
3084 | } | 3142 | } |
3085 | } | 3143 | } |
3086 | 3144 | ||
3145 | skip_analog: | ||
3087 | /* SPDIF for stream index #1 */ | 3146 | /* SPDIF for stream index #1 */ |
3088 | if (spec->multiout.dig_out_nid || spec->dig_in_nid) { | 3147 | if (spec->multiout.dig_out_nid || spec->dig_in_nid) { |
3089 | codec->num_pcms = 2; | 3148 | codec->num_pcms = 2; |
3149 | codec->slave_dig_outs = spec->multiout.slave_dig_outs; | ||
3090 | info = spec->pcm_rec + 1; | 3150 | info = spec->pcm_rec + 1; |
3091 | info->name = spec->stream_name_digital; | 3151 | info->name = spec->stream_name_digital; |
3092 | info->pcm_type = HDA_PCM_TYPE_SPDIF; | 3152 | if (spec->dig_out_type) |
3153 | info->pcm_type = spec->dig_out_type; | ||
3154 | else | ||
3155 | info->pcm_type = HDA_PCM_TYPE_SPDIF; | ||
3093 | if (spec->multiout.dig_out_nid && | 3156 | if (spec->multiout.dig_out_nid && |
3094 | spec->stream_digital_playback) { | 3157 | spec->stream_digital_playback) { |
3095 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback); | 3158 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback); |
@@ -3104,6 +3167,9 @@ static int alc_build_pcms(struct hda_codec *codec) | |||
3104 | codec->spdif_status_reset = 1; | 3167 | codec->spdif_status_reset = 1; |
3105 | } | 3168 | } |
3106 | 3169 | ||
3170 | if (spec->no_analog) | ||
3171 | return 0; | ||
3172 | |||
3107 | /* If the use of more than one ADC is requested for the current | 3173 | /* If the use of more than one ADC is requested for the current |
3108 | * model, configure a second analog capture-only PCM. | 3174 | * model, configure a second analog capture-only PCM. |
3109 | */ | 3175 | */ |
@@ -3162,65 +3228,17 @@ static void alc_free(struct hda_codec *codec) | |||
3162 | 3228 | ||
3163 | alc_free_kctls(codec); | 3229 | alc_free_kctls(codec); |
3164 | kfree(spec); | 3230 | kfree(spec); |
3165 | codec->spec = NULL; /* to be sure */ | 3231 | snd_hda_detach_beep_device(codec); |
3166 | } | 3232 | } |
3167 | 3233 | ||
3168 | #ifdef SND_HDA_NEEDS_RESUME | 3234 | #ifdef SND_HDA_NEEDS_RESUME |
3169 | static void store_pin_configs(struct hda_codec *codec) | ||
3170 | { | ||
3171 | struct alc_spec *spec = codec->spec; | ||
3172 | hda_nid_t nid, end_nid; | ||
3173 | |||
3174 | end_nid = codec->start_nid + codec->num_nodes; | ||
3175 | for (nid = codec->start_nid; nid < end_nid; nid++) { | ||
3176 | unsigned int wid_caps = get_wcaps(codec, nid); | ||
3177 | unsigned int wid_type = | ||
3178 | (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; | ||
3179 | if (wid_type != AC_WID_PIN) | ||
3180 | continue; | ||
3181 | if (spec->num_pins >= ARRAY_SIZE(spec->pin_nids)) | ||
3182 | break; | ||
3183 | spec->pin_nids[spec->num_pins] = nid; | ||
3184 | spec->pin_cfgs[spec->num_pins] = | ||
3185 | snd_hda_codec_read(codec, nid, 0, | ||
3186 | AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
3187 | spec->num_pins++; | ||
3188 | } | ||
3189 | } | ||
3190 | |||
3191 | static void resume_pin_configs(struct hda_codec *codec) | ||
3192 | { | ||
3193 | struct alc_spec *spec = codec->spec; | ||
3194 | int i; | ||
3195 | |||
3196 | for (i = 0; i < spec->num_pins; i++) { | ||
3197 | hda_nid_t pin_nid = spec->pin_nids[i]; | ||
3198 | unsigned int pin_config = spec->pin_cfgs[i]; | ||
3199 | snd_hda_codec_write(codec, pin_nid, 0, | ||
3200 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_0, | ||
3201 | pin_config & 0x000000ff); | ||
3202 | snd_hda_codec_write(codec, pin_nid, 0, | ||
3203 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_1, | ||
3204 | (pin_config & 0x0000ff00) >> 8); | ||
3205 | snd_hda_codec_write(codec, pin_nid, 0, | ||
3206 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_2, | ||
3207 | (pin_config & 0x00ff0000) >> 16); | ||
3208 | snd_hda_codec_write(codec, pin_nid, 0, | ||
3209 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, | ||
3210 | pin_config >> 24); | ||
3211 | } | ||
3212 | } | ||
3213 | |||
3214 | static int alc_resume(struct hda_codec *codec) | 3235 | static int alc_resume(struct hda_codec *codec) |
3215 | { | 3236 | { |
3216 | resume_pin_configs(codec); | ||
3217 | codec->patch_ops.init(codec); | 3237 | codec->patch_ops.init(codec); |
3218 | snd_hda_codec_resume_amp(codec); | 3238 | snd_hda_codec_resume_amp(codec); |
3219 | snd_hda_codec_resume_cache(codec); | 3239 | snd_hda_codec_resume_cache(codec); |
3220 | return 0; | 3240 | return 0; |
3221 | } | 3241 | } |
3222 | #else | ||
3223 | #define store_pin_configs(codec) | ||
3224 | #endif | 3242 | #endif |
3225 | 3243 | ||
3226 | /* | 3244 | /* |
@@ -3559,7 +3577,7 @@ static struct snd_pci_quirk alc880_cfg_tbl[] = { | |||
3559 | SND_PCI_QUIRK(0x1043, 0x8181, "ASUS P4GPL", ALC880_ASUS_DIG), | 3577 | SND_PCI_QUIRK(0x1043, 0x8181, "ASUS P4GPL", ALC880_ASUS_DIG), |
3560 | SND_PCI_QUIRK(0x1043, 0x8196, "ASUS P5GD1", ALC880_6ST), | 3578 | SND_PCI_QUIRK(0x1043, 0x8196, "ASUS P5GD1", ALC880_6ST), |
3561 | SND_PCI_QUIRK(0x1043, 0x81b4, "ASUS", ALC880_6ST), | 3579 | SND_PCI_QUIRK(0x1043, 0x81b4, "ASUS", ALC880_6ST), |
3562 | SND_PCI_QUIRK(0x1043, 0, "ASUS", ALC880_ASUS), /* default ASUS */ | 3580 | SND_PCI_QUIRK_VENDOR(0x1043, "ASUS", ALC880_ASUS), /* default ASUS */ |
3563 | SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_3ST), | 3581 | SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_3ST), |
3564 | SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_3ST), | 3582 | SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_3ST), |
3565 | SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_5ST), | 3583 | SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_5ST), |
@@ -3602,7 +3620,8 @@ static struct snd_pci_quirk alc880_cfg_tbl[] = { | |||
3602 | SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_5ST_DIG), | 3620 | SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_5ST_DIG), |
3603 | SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_5ST_DIG), | 3621 | SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_5ST_DIG), |
3604 | SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_5ST_DIG), | 3622 | SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_5ST_DIG), |
3605 | SND_PCI_QUIRK(0x8086, 0, "Intel mobo", ALC880_3ST), /* default Intel */ | 3623 | /* default Intel */ |
3624 | SND_PCI_QUIRK_VENDOR(0x8086, "Intel mobo", ALC880_3ST), | ||
3606 | SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_5ST_DIG), | 3625 | SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_5ST_DIG), |
3607 | SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_6ST_DIG), | 3626 | SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_6ST_DIG), |
3608 | {} | 3627 | {} |
@@ -3782,7 +3801,7 @@ static struct alc_config_preset alc880_presets[] = { | |||
3782 | .input_mux = &alc880_capture_source, | 3801 | .input_mux = &alc880_capture_source, |
3783 | }, | 3802 | }, |
3784 | [ALC880_UNIWILL_DIG] = { | 3803 | [ALC880_UNIWILL_DIG] = { |
3785 | .mixers = { alc880_asus_mixer, alc880_pcbeep_mixer }, | 3804 | .mixers = { alc880_asus_mixer }, |
3786 | .init_verbs = { alc880_volume_init_verbs, | 3805 | .init_verbs = { alc880_volume_init_verbs, |
3787 | alc880_pin_asus_init_verbs }, | 3806 | alc880_pin_asus_init_verbs }, |
3788 | .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), | 3807 | .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), |
@@ -3820,8 +3839,7 @@ static struct alc_config_preset alc880_presets[] = { | |||
3820 | .init_hook = alc880_uniwill_p53_hp_automute, | 3839 | .init_hook = alc880_uniwill_p53_hp_automute, |
3821 | }, | 3840 | }, |
3822 | [ALC880_FUJITSU] = { | 3841 | [ALC880_FUJITSU] = { |
3823 | .mixers = { alc880_fujitsu_mixer, | 3842 | .mixers = { alc880_fujitsu_mixer }, |
3824 | alc880_pcbeep_mixer, }, | ||
3825 | .init_verbs = { alc880_volume_init_verbs, | 3843 | .init_verbs = { alc880_volume_init_verbs, |
3826 | alc880_uniwill_p53_init_verbs, | 3844 | alc880_uniwill_p53_init_verbs, |
3827 | alc880_beep_init_verbs }, | 3845 | alc880_beep_init_verbs }, |
@@ -4114,7 +4132,7 @@ static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, | |||
4114 | static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec, | 4132 | static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec, |
4115 | const struct auto_pin_cfg *cfg) | 4133 | const struct auto_pin_cfg *cfg) |
4116 | { | 4134 | { |
4117 | struct hda_input_mux *imux = &spec->private_imux; | 4135 | struct hda_input_mux *imux = &spec->private_imux[0]; |
4118 | int i, err, idx; | 4136 | int i, err, idx; |
4119 | 4137 | ||
4120 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 4138 | for (i = 0; i < AUTO_PIN_LAST; i++) { |
@@ -4202,11 +4220,9 @@ static void alc880_auto_init_analog_input(struct hda_codec *codec) | |||
4202 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 4220 | for (i = 0; i < AUTO_PIN_LAST; i++) { |
4203 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 4221 | hda_nid_t nid = spec->autocfg.input_pins[i]; |
4204 | if (alc880_is_input_pin(nid)) { | 4222 | if (alc880_is_input_pin(nid)) { |
4205 | snd_hda_codec_write(codec, nid, 0, | 4223 | alc_set_input_pin(codec, nid, i); |
4206 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 4224 | if (nid != ALC880_PIN_CD_NID && |
4207 | i <= AUTO_PIN_FRONT_MIC ? | 4225 | (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) |
4208 | PIN_VREF80 : PIN_IN); | ||
4209 | if (nid != ALC880_PIN_CD_NID) | ||
4210 | snd_hda_codec_write(codec, nid, 0, | 4226 | snd_hda_codec_write(codec, nid, 0, |
4211 | AC_VERB_SET_AMP_GAIN_MUTE, | 4227 | AC_VERB_SET_AMP_GAIN_MUTE, |
4212 | AMP_OUT_MUTE); | 4228 | AMP_OUT_MUTE); |
@@ -4221,7 +4237,7 @@ static void alc880_auto_init_analog_input(struct hda_codec *codec) | |||
4221 | static int alc880_parse_auto_config(struct hda_codec *codec) | 4237 | static int alc880_parse_auto_config(struct hda_codec *codec) |
4222 | { | 4238 | { |
4223 | struct alc_spec *spec = codec->spec; | 4239 | struct alc_spec *spec = codec->spec; |
4224 | int err; | 4240 | int i, err; |
4225 | static hda_nid_t alc880_ignore[] = { 0x1d, 0 }; | 4241 | static hda_nid_t alc880_ignore[] = { 0x1d, 0 }; |
4226 | 4242 | ||
4227 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, | 4243 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, |
@@ -4252,8 +4268,23 @@ static int alc880_parse_auto_config(struct hda_codec *codec) | |||
4252 | 4268 | ||
4253 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 4269 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
4254 | 4270 | ||
4255 | if (spec->autocfg.dig_out_pin) | 4271 | /* check multiple SPDIF-out (for recent codecs) */ |
4256 | spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; | 4272 | for (i = 0; i < spec->autocfg.dig_outs; i++) { |
4273 | hda_nid_t dig_nid; | ||
4274 | err = snd_hda_get_connections(codec, | ||
4275 | spec->autocfg.dig_out_pins[i], | ||
4276 | &dig_nid, 1); | ||
4277 | if (err < 0) | ||
4278 | continue; | ||
4279 | if (!i) | ||
4280 | spec->multiout.dig_out_nid = dig_nid; | ||
4281 | else { | ||
4282 | spec->multiout.slave_dig_outs = spec->slave_dig_outs; | ||
4283 | spec->slave_dig_outs[i - 1] = dig_nid; | ||
4284 | if (i == ARRAY_SIZE(spec->slave_dig_outs) - 1) | ||
4285 | break; | ||
4286 | } | ||
4287 | } | ||
4257 | if (spec->autocfg.dig_in_pin) | 4288 | if (spec->autocfg.dig_in_pin) |
4258 | spec->dig_in_nid = ALC880_DIGIN_NID; | 4289 | spec->dig_in_nid = ALC880_DIGIN_NID; |
4259 | 4290 | ||
@@ -4263,9 +4294,8 @@ static int alc880_parse_auto_config(struct hda_codec *codec) | |||
4263 | add_verb(spec, alc880_volume_init_verbs); | 4294 | add_verb(spec, alc880_volume_init_verbs); |
4264 | 4295 | ||
4265 | spec->num_mux_defs = 1; | 4296 | spec->num_mux_defs = 1; |
4266 | spec->input_mux = &spec->private_imux; | 4297 | spec->input_mux = &spec->private_imux[0]; |
4267 | 4298 | ||
4268 | store_pin_configs(codec); | ||
4269 | return 1; | 4299 | return 1; |
4270 | } | 4300 | } |
4271 | 4301 | ||
@@ -4280,21 +4310,33 @@ static void alc880_auto_init(struct hda_codec *codec) | |||
4280 | alc_inithook(codec); | 4310 | alc_inithook(codec); |
4281 | } | 4311 | } |
4282 | 4312 | ||
4283 | /* | ||
4284 | * OK, here we have finally the patch for ALC880 | ||
4285 | */ | ||
4286 | |||
4287 | static void set_capture_mixer(struct alc_spec *spec) | 4313 | static void set_capture_mixer(struct alc_spec *spec) |
4288 | { | 4314 | { |
4289 | static struct snd_kcontrol_new *caps[3] = { | 4315 | static struct snd_kcontrol_new *caps[2][3] = { |
4290 | alc_capture_mixer1, | 4316 | { alc_capture_mixer_nosrc1, |
4291 | alc_capture_mixer2, | 4317 | alc_capture_mixer_nosrc2, |
4292 | alc_capture_mixer3, | 4318 | alc_capture_mixer_nosrc3 }, |
4319 | { alc_capture_mixer1, | ||
4320 | alc_capture_mixer2, | ||
4321 | alc_capture_mixer3 }, | ||
4293 | }; | 4322 | }; |
4294 | if (spec->num_adc_nids > 0 && spec->num_adc_nids <= 3) | 4323 | if (spec->num_adc_nids > 0 && spec->num_adc_nids <= 3) { |
4295 | spec->cap_mixer = caps[spec->num_adc_nids - 1]; | 4324 | int mux; |
4325 | if (spec->input_mux && spec->input_mux->num_items > 1) | ||
4326 | mux = 1; | ||
4327 | else | ||
4328 | mux = 0; | ||
4329 | spec->cap_mixer = caps[mux][spec->num_adc_nids - 1]; | ||
4330 | } | ||
4296 | } | 4331 | } |
4297 | 4332 | ||
4333 | #define set_beep_amp(spec, nid, idx, dir) \ | ||
4334 | ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir)) | ||
4335 | |||
4336 | /* | ||
4337 | * OK, here we have finally the patch for ALC880 | ||
4338 | */ | ||
4339 | |||
4298 | static int patch_alc880(struct hda_codec *codec) | 4340 | static int patch_alc880(struct hda_codec *codec) |
4299 | { | 4341 | { |
4300 | struct alc_spec *spec; | 4342 | struct alc_spec *spec; |
@@ -4330,6 +4372,12 @@ static int patch_alc880(struct hda_codec *codec) | |||
4330 | } | 4372 | } |
4331 | } | 4373 | } |
4332 | 4374 | ||
4375 | err = snd_hda_attach_beep_device(codec, 0x1); | ||
4376 | if (err < 0) { | ||
4377 | alc_free(codec); | ||
4378 | return err; | ||
4379 | } | ||
4380 | |||
4333 | if (board_config != ALC880_AUTO) | 4381 | if (board_config != ALC880_AUTO) |
4334 | setup_preset(spec, &alc880_presets[board_config]); | 4382 | setup_preset(spec, &alc880_presets[board_config]); |
4335 | 4383 | ||
@@ -4356,6 +4404,7 @@ static int patch_alc880(struct hda_codec *codec) | |||
4356 | } | 4404 | } |
4357 | } | 4405 | } |
4358 | set_capture_mixer(spec); | 4406 | set_capture_mixer(spec); |
4407 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | ||
4359 | 4408 | ||
4360 | spec->vmaster_nid = 0x0c; | 4409 | spec->vmaster_nid = 0x0c; |
4361 | 4410 | ||
@@ -4463,6 +4512,26 @@ static struct hda_input_mux alc260_acer_capture_sources[2] = { | |||
4463 | }, | 4512 | }, |
4464 | }, | 4513 | }, |
4465 | }; | 4514 | }; |
4515 | |||
4516 | /* Maxdata Favorit 100XS */ | ||
4517 | static struct hda_input_mux alc260_favorit100_capture_sources[2] = { | ||
4518 | { | ||
4519 | .num_items = 2, | ||
4520 | .items = { | ||
4521 | { "Line/Mic", 0x0 }, | ||
4522 | { "CD", 0x4 }, | ||
4523 | }, | ||
4524 | }, | ||
4525 | { | ||
4526 | .num_items = 3, | ||
4527 | .items = { | ||
4528 | { "Line/Mic", 0x0 }, | ||
4529 | { "CD", 0x4 }, | ||
4530 | { "Mixer", 0x5 }, | ||
4531 | }, | ||
4532 | }, | ||
4533 | }; | ||
4534 | |||
4466 | /* | 4535 | /* |
4467 | * This is just place-holder, so there's something for alc_build_pcms to look | 4536 | * This is just place-holder, so there's something for alc_build_pcms to look |
4468 | * at when it calculates the maximum number of channels. ALC260 has no mixer | 4537 | * at when it calculates the maximum number of channels. ALC260 has no mixer |
@@ -4505,12 +4574,6 @@ static struct snd_kcontrol_new alc260_input_mixer[] = { | |||
4505 | { } /* end */ | 4574 | { } /* end */ |
4506 | }; | 4575 | }; |
4507 | 4576 | ||
4508 | static struct snd_kcontrol_new alc260_pc_beep_mixer[] = { | ||
4509 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x07, 0x05, HDA_INPUT), | ||
4510 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x07, 0x05, HDA_INPUT), | ||
4511 | { } /* end */ | ||
4512 | }; | ||
4513 | |||
4514 | /* update HP, line and mono out pins according to the master switch */ | 4577 | /* update HP, line and mono out pins according to the master switch */ |
4515 | static void alc260_hp_master_update(struct hda_codec *codec, | 4578 | static void alc260_hp_master_update(struct hda_codec *codec, |
4516 | hda_nid_t hp, hda_nid_t line, | 4579 | hda_nid_t hp, hda_nid_t line, |
@@ -4702,8 +4765,6 @@ static struct snd_kcontrol_new alc260_fujitsu_mixer[] = { | |||
4702 | HDA_CODEC_VOLUME("Mic/Line Playback Volume", 0x07, 0x0, HDA_INPUT), | 4765 | HDA_CODEC_VOLUME("Mic/Line Playback Volume", 0x07, 0x0, HDA_INPUT), |
4703 | HDA_CODEC_MUTE("Mic/Line Playback Switch", 0x07, 0x0, HDA_INPUT), | 4766 | HDA_CODEC_MUTE("Mic/Line Playback Switch", 0x07, 0x0, HDA_INPUT), |
4704 | ALC_PIN_MODE("Mic/Line Jack Mode", 0x12, ALC_PIN_DIR_IN), | 4767 | ALC_PIN_MODE("Mic/Line Jack Mode", 0x12, ALC_PIN_DIR_IN), |
4705 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT), | ||
4706 | HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT), | ||
4707 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT), | 4768 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT), |
4708 | HDA_BIND_MUTE("Speaker Playback Switch", 0x09, 2, HDA_INPUT), | 4769 | HDA_BIND_MUTE("Speaker Playback Switch", 0x09, 2, HDA_INPUT), |
4709 | { } /* end */ | 4770 | { } /* end */ |
@@ -4748,8 +4809,18 @@ static struct snd_kcontrol_new alc260_acer_mixer[] = { | |||
4748 | HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), | 4809 | HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), |
4749 | HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT), | 4810 | HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT), |
4750 | ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT), | 4811 | ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT), |
4751 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT), | 4812 | { } /* end */ |
4752 | HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT), | 4813 | }; |
4814 | |||
4815 | /* Maxdata Favorit 100XS: one output and one input (0x12) jack | ||
4816 | */ | ||
4817 | static struct snd_kcontrol_new alc260_favorit100_mixer[] = { | ||
4818 | HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT), | ||
4819 | HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT), | ||
4820 | ALC_PIN_MODE("Output Jack Mode", 0x0f, ALC_PIN_DIR_INOUT), | ||
4821 | HDA_CODEC_VOLUME("Line/Mic Playback Volume", 0x07, 0x0, HDA_INPUT), | ||
4822 | HDA_CODEC_MUTE("Line/Mic Playback Switch", 0x07, 0x0, HDA_INPUT), | ||
4823 | ALC_PIN_MODE("Line/Mic Jack Mode", 0x12, ALC_PIN_DIR_IN), | ||
4753 | { } /* end */ | 4824 | { } /* end */ |
4754 | }; | 4825 | }; |
4755 | 4826 | ||
@@ -4767,8 +4838,6 @@ static struct snd_kcontrol_new alc260_will_mixer[] = { | |||
4767 | ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT), | 4838 | ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT), |
4768 | HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), | 4839 | HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), |
4769 | HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), | 4840 | HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), |
4770 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT), | ||
4771 | HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT), | ||
4772 | { } /* end */ | 4841 | { } /* end */ |
4773 | }; | 4842 | }; |
4774 | 4843 | ||
@@ -5126,6 +5195,89 @@ static struct hda_verb alc260_acer_init_verbs[] = { | |||
5126 | { } | 5195 | { } |
5127 | }; | 5196 | }; |
5128 | 5197 | ||
5198 | /* Initialisation sequence for Maxdata Favorit 100XS | ||
5199 | * (adapted from Acer init verbs). | ||
5200 | */ | ||
5201 | static struct hda_verb alc260_favorit100_init_verbs[] = { | ||
5202 | /* GPIO 0 enables the output jack. | ||
5203 | * Turn this on and rely on the standard mute | ||
5204 | * methods whenever the user wants to turn these outputs off. | ||
5205 | */ | ||
5206 | {0x01, AC_VERB_SET_GPIO_MASK, 0x01}, | ||
5207 | {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, | ||
5208 | {0x01, AC_VERB_SET_GPIO_DATA, 0x01}, | ||
5209 | /* Line/Mic input jack is connected to Mic1 pin */ | ||
5210 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50}, | ||
5211 | /* Ensure all other unused pins are disabled and muted. */ | ||
5212 | {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
5213 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
5214 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
5215 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
5216 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
5217 | {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
5218 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
5219 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
5220 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
5221 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
5222 | /* Disable digital (SPDIF) pins */ | ||
5223 | {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0}, | ||
5224 | {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0}, | ||
5225 | |||
5226 | /* Ensure Mic1 and Line1 pin widgets take input from the OUT1 sum | ||
5227 | * bus when acting as outputs. | ||
5228 | */ | ||
5229 | {0x0b, AC_VERB_SET_CONNECT_SEL, 0}, | ||
5230 | {0x0d, AC_VERB_SET_CONNECT_SEL, 0}, | ||
5231 | |||
5232 | /* Start with output sum widgets muted and their output gains at min */ | ||
5233 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
5234 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
5235 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
5236 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
5237 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
5238 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
5239 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
5240 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
5241 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
5242 | |||
5243 | /* Unmute Line-out pin widget amp left and right | ||
5244 | * (no equiv mixer ctrl) | ||
5245 | */ | ||
5246 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
5247 | /* Unmute Mic1 and Line1 pin widget input buffers since they start as | ||
5248 | * inputs. If the pin mode is changed by the user the pin mode control | ||
5249 | * will take care of enabling the pin's input/output buffers as needed. | ||
5250 | * Therefore there's no need to enable the input buffer at this | ||
5251 | * stage. | ||
5252 | */ | ||
5253 | {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
5254 | |||
5255 | /* Mute capture amp left and right */ | ||
5256 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
5257 | /* Set ADC connection select to match default mixer setting - mic | ||
5258 | * (on mic1 pin) | ||
5259 | */ | ||
5260 | {0x04, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
5261 | |||
5262 | /* Do similar with the second ADC: mute capture input amp and | ||
5263 | * set ADC connection to mic to match ALSA's default state. | ||
5264 | */ | ||
5265 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
5266 | {0x05, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
5267 | |||
5268 | /* Mute all inputs to mixer widget (even unconnected ones) */ | ||
5269 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */ | ||
5270 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */ | ||
5271 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */ | ||
5272 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */ | ||
5273 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */ | ||
5274 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */ | ||
5275 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */ | ||
5276 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */ | ||
5277 | |||
5278 | { } | ||
5279 | }; | ||
5280 | |||
5129 | static struct hda_verb alc260_will_verbs[] = { | 5281 | static struct hda_verb alc260_will_verbs[] = { |
5130 | {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | 5282 | {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, |
5131 | {0x0b, AC_VERB_SET_CONNECT_SEL, 0x00}, | 5283 | {0x0b, AC_VERB_SET_CONNECT_SEL, 0x00}, |
@@ -5272,8 +5424,6 @@ static struct snd_kcontrol_new alc260_test_mixer[] = { | |||
5272 | HDA_CODEC_MUTE("LINE2 Playback Switch", 0x07, 0x03, HDA_INPUT), | 5424 | HDA_CODEC_MUTE("LINE2 Playback Switch", 0x07, 0x03, HDA_INPUT), |
5273 | HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), | 5425 | HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), |
5274 | HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), | 5426 | HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), |
5275 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT), | ||
5276 | HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT), | ||
5277 | HDA_CODEC_VOLUME("LINE-OUT loopback Playback Volume", 0x07, 0x06, HDA_INPUT), | 5427 | HDA_CODEC_VOLUME("LINE-OUT loopback Playback Volume", 0x07, 0x06, HDA_INPUT), |
5278 | HDA_CODEC_MUTE("LINE-OUT loopback Playback Switch", 0x07, 0x06, HDA_INPUT), | 5428 | HDA_CODEC_MUTE("LINE-OUT loopback Playback Switch", 0x07, 0x06, HDA_INPUT), |
5279 | HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x07, 0x7, HDA_INPUT), | 5429 | HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x07, 0x7, HDA_INPUT), |
@@ -5471,7 +5621,7 @@ static int alc260_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
5471 | static int alc260_auto_create_analog_input_ctls(struct alc_spec *spec, | 5621 | static int alc260_auto_create_analog_input_ctls(struct alc_spec *spec, |
5472 | const struct auto_pin_cfg *cfg) | 5622 | const struct auto_pin_cfg *cfg) |
5473 | { | 5623 | { |
5474 | struct hda_input_mux *imux = &spec->private_imux; | 5624 | struct hda_input_mux *imux = &spec->private_imux[0]; |
5475 | int i, err, idx; | 5625 | int i, err, idx; |
5476 | 5626 | ||
5477 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 5627 | for (i = 0; i < AUTO_PIN_LAST; i++) { |
@@ -5546,11 +5696,9 @@ static void alc260_auto_init_analog_input(struct hda_codec *codec) | |||
5546 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 5696 | for (i = 0; i < AUTO_PIN_LAST; i++) { |
5547 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 5697 | hda_nid_t nid = spec->autocfg.input_pins[i]; |
5548 | if (nid >= 0x12) { | 5698 | if (nid >= 0x12) { |
5549 | snd_hda_codec_write(codec, nid, 0, | 5699 | alc_set_input_pin(codec, nid, i); |
5550 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 5700 | if (nid != ALC260_PIN_CD_NID && |
5551 | i <= AUTO_PIN_FRONT_MIC ? | 5701 | (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) |
5552 | PIN_VREF80 : PIN_IN); | ||
5553 | if (nid != ALC260_PIN_CD_NID) | ||
5554 | snd_hda_codec_write(codec, nid, 0, | 5702 | snd_hda_codec_write(codec, nid, 0, |
5555 | AC_VERB_SET_AMP_GAIN_MUTE, | 5703 | AC_VERB_SET_AMP_GAIN_MUTE, |
5556 | AMP_OUT_MUTE); | 5704 | AMP_OUT_MUTE); |
@@ -5623,7 +5771,7 @@ static int alc260_parse_auto_config(struct hda_codec *codec) | |||
5623 | 5771 | ||
5624 | spec->multiout.max_channels = 2; | 5772 | spec->multiout.max_channels = 2; |
5625 | 5773 | ||
5626 | if (spec->autocfg.dig_out_pin) | 5774 | if (spec->autocfg.dig_outs) |
5627 | spec->multiout.dig_out_nid = ALC260_DIGOUT_NID; | 5775 | spec->multiout.dig_out_nid = ALC260_DIGOUT_NID; |
5628 | if (spec->kctls.list) | 5776 | if (spec->kctls.list) |
5629 | add_mixer(spec, spec->kctls.list); | 5777 | add_mixer(spec, spec->kctls.list); |
@@ -5631,9 +5779,8 @@ static int alc260_parse_auto_config(struct hda_codec *codec) | |||
5631 | add_verb(spec, alc260_volume_init_verbs); | 5779 | add_verb(spec, alc260_volume_init_verbs); |
5632 | 5780 | ||
5633 | spec->num_mux_defs = 1; | 5781 | spec->num_mux_defs = 1; |
5634 | spec->input_mux = &spec->private_imux; | 5782 | spec->input_mux = &spec->private_imux[0]; |
5635 | 5783 | ||
5636 | store_pin_configs(codec); | ||
5637 | return 1; | 5784 | return 1; |
5638 | } | 5785 | } |
5639 | 5786 | ||
@@ -5670,6 +5817,7 @@ static const char *alc260_models[ALC260_MODEL_LAST] = { | |||
5670 | [ALC260_ACER] = "acer", | 5817 | [ALC260_ACER] = "acer", |
5671 | [ALC260_WILL] = "will", | 5818 | [ALC260_WILL] = "will", |
5672 | [ALC260_REPLACER_672V] = "replacer", | 5819 | [ALC260_REPLACER_672V] = "replacer", |
5820 | [ALC260_FAVORIT100] = "favorit100", | ||
5673 | #ifdef CONFIG_SND_DEBUG | 5821 | #ifdef CONFIG_SND_DEBUG |
5674 | [ALC260_TEST] = "test", | 5822 | [ALC260_TEST] = "test", |
5675 | #endif | 5823 | #endif |
@@ -5679,6 +5827,7 @@ static const char *alc260_models[ALC260_MODEL_LAST] = { | |||
5679 | static struct snd_pci_quirk alc260_cfg_tbl[] = { | 5827 | static struct snd_pci_quirk alc260_cfg_tbl[] = { |
5680 | SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_ACER), | 5828 | SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_ACER), |
5681 | SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_ACER), | 5829 | SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_ACER), |
5830 | SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FAVORIT100), | ||
5682 | SND_PCI_QUIRK(0x103c, 0x2808, "HP d5700", ALC260_HP_3013), | 5831 | SND_PCI_QUIRK(0x103c, 0x2808, "HP d5700", ALC260_HP_3013), |
5683 | SND_PCI_QUIRK(0x103c, 0x280a, "HP d5750", ALC260_HP_3013), | 5832 | SND_PCI_QUIRK(0x103c, 0x280a, "HP d5750", ALC260_HP_3013), |
5684 | SND_PCI_QUIRK(0x103c, 0x3010, "HP", ALC260_HP_3013), | 5833 | SND_PCI_QUIRK(0x103c, 0x3010, "HP", ALC260_HP_3013), |
@@ -5701,8 +5850,7 @@ static struct snd_pci_quirk alc260_cfg_tbl[] = { | |||
5701 | static struct alc_config_preset alc260_presets[] = { | 5850 | static struct alc_config_preset alc260_presets[] = { |
5702 | [ALC260_BASIC] = { | 5851 | [ALC260_BASIC] = { |
5703 | .mixers = { alc260_base_output_mixer, | 5852 | .mixers = { alc260_base_output_mixer, |
5704 | alc260_input_mixer, | 5853 | alc260_input_mixer }, |
5705 | alc260_pc_beep_mixer }, | ||
5706 | .init_verbs = { alc260_init_verbs }, | 5854 | .init_verbs = { alc260_init_verbs }, |
5707 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), | 5855 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), |
5708 | .dac_nids = alc260_dac_nids, | 5856 | .dac_nids = alc260_dac_nids, |
@@ -5781,6 +5929,18 @@ static struct alc_config_preset alc260_presets[] = { | |||
5781 | .num_mux_defs = ARRAY_SIZE(alc260_acer_capture_sources), | 5929 | .num_mux_defs = ARRAY_SIZE(alc260_acer_capture_sources), |
5782 | .input_mux = alc260_acer_capture_sources, | 5930 | .input_mux = alc260_acer_capture_sources, |
5783 | }, | 5931 | }, |
5932 | [ALC260_FAVORIT100] = { | ||
5933 | .mixers = { alc260_favorit100_mixer }, | ||
5934 | .init_verbs = { alc260_favorit100_init_verbs }, | ||
5935 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), | ||
5936 | .dac_nids = alc260_dac_nids, | ||
5937 | .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids), | ||
5938 | .adc_nids = alc260_dual_adc_nids, | ||
5939 | .num_channel_mode = ARRAY_SIZE(alc260_modes), | ||
5940 | .channel_mode = alc260_modes, | ||
5941 | .num_mux_defs = ARRAY_SIZE(alc260_favorit100_capture_sources), | ||
5942 | .input_mux = alc260_favorit100_capture_sources, | ||
5943 | }, | ||
5784 | [ALC260_WILL] = { | 5944 | [ALC260_WILL] = { |
5785 | .mixers = { alc260_will_mixer }, | 5945 | .mixers = { alc260_will_mixer }, |
5786 | .init_verbs = { alc260_init_verbs, alc260_will_verbs }, | 5946 | .init_verbs = { alc260_init_verbs, alc260_will_verbs }, |
@@ -5857,6 +6017,12 @@ static int patch_alc260(struct hda_codec *codec) | |||
5857 | } | 6017 | } |
5858 | } | 6018 | } |
5859 | 6019 | ||
6020 | err = snd_hda_attach_beep_device(codec, 0x1); | ||
6021 | if (err < 0) { | ||
6022 | alc_free(codec); | ||
6023 | return err; | ||
6024 | } | ||
6025 | |||
5860 | if (board_config != ALC260_AUTO) | 6026 | if (board_config != ALC260_AUTO) |
5861 | setup_preset(spec, &alc260_presets[board_config]); | 6027 | setup_preset(spec, &alc260_presets[board_config]); |
5862 | 6028 | ||
@@ -5882,6 +6048,7 @@ static int patch_alc260(struct hda_codec *codec) | |||
5882 | } | 6048 | } |
5883 | } | 6049 | } |
5884 | set_capture_mixer(spec); | 6050 | set_capture_mixer(spec); |
6051 | set_beep_amp(spec, 0x07, 0x05, HDA_INPUT); | ||
5885 | 6052 | ||
5886 | spec->vmaster_nid = 0x08; | 6053 | spec->vmaster_nid = 0x08; |
5887 | 6054 | ||
@@ -6053,8 +6220,6 @@ static struct snd_kcontrol_new alc882_base_mixer[] = { | |||
6053 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 6220 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
6054 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | 6221 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), |
6055 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 6222 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
6056 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
6057 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
6058 | { } /* end */ | 6223 | { } /* end */ |
6059 | }; | 6224 | }; |
6060 | 6225 | ||
@@ -6081,8 +6246,6 @@ static struct snd_kcontrol_new alc882_w2jc_mixer[] = { | |||
6081 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 6246 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
6082 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 6247 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), |
6083 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 6248 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
6084 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
6085 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
6086 | { } /* end */ | 6249 | { } /* end */ |
6087 | }; | 6250 | }; |
6088 | 6251 | ||
@@ -6134,8 +6297,6 @@ static struct snd_kcontrol_new alc882_asus_a7m_mixer[] = { | |||
6134 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 6297 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
6135 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 6298 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), |
6136 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 6299 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
6137 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
6138 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
6139 | { } /* end */ | 6300 | { } /* end */ |
6140 | }; | 6301 | }; |
6141 | 6302 | ||
@@ -6244,8 +6405,10 @@ static struct snd_kcontrol_new alc882_macpro_mixer[] = { | |||
6244 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x18, 0x0, HDA_OUTPUT), | 6405 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x18, 0x0, HDA_OUTPUT), |
6245 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT), | 6406 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT), |
6246 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT), | 6407 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT), |
6408 | /* FIXME: this looks suspicious... | ||
6247 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x02, HDA_INPUT), | 6409 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x02, HDA_INPUT), |
6248 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x02, HDA_INPUT), | 6410 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x02, HDA_INPUT), |
6411 | */ | ||
6249 | { } /* end */ | 6412 | { } /* end */ |
6250 | }; | 6413 | }; |
6251 | 6414 | ||
@@ -6877,19 +7040,9 @@ static void alc882_auto_init_analog_input(struct hda_codec *codec) | |||
6877 | 7040 | ||
6878 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 7041 | for (i = 0; i < AUTO_PIN_LAST; i++) { |
6879 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 7042 | hda_nid_t nid = spec->autocfg.input_pins[i]; |
6880 | unsigned int vref; | ||
6881 | if (!nid) | 7043 | if (!nid) |
6882 | continue; | 7044 | continue; |
6883 | vref = PIN_IN; | 7045 | alc_set_input_pin(codec, nid, AUTO_PIN_FRONT_MIC /*i*/); |
6884 | if (1 /*i <= AUTO_PIN_FRONT_MIC*/) { | ||
6885 | unsigned int pincap; | ||
6886 | pincap = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); | ||
6887 | if ((pincap >> AC_PINCAP_VREF_SHIFT) & | ||
6888 | AC_PINCAP_VREF_80) | ||
6889 | vref = PIN_VREF80; | ||
6890 | } | ||
6891 | snd_hda_codec_write(codec, nid, 0, | ||
6892 | AC_VERB_SET_PIN_WIDGET_CONTROL, vref); | ||
6893 | if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) | 7046 | if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) |
6894 | snd_hda_codec_write(codec, nid, 0, | 7047 | snd_hda_codec_write(codec, nid, 0, |
6895 | AC_VERB_SET_AMP_GAIN_MUTE, | 7048 | AC_VERB_SET_AMP_GAIN_MUTE, |
@@ -6900,18 +7053,21 @@ static void alc882_auto_init_analog_input(struct hda_codec *codec) | |||
6900 | static void alc882_auto_init_input_src(struct hda_codec *codec) | 7053 | static void alc882_auto_init_input_src(struct hda_codec *codec) |
6901 | { | 7054 | { |
6902 | struct alc_spec *spec = codec->spec; | 7055 | struct alc_spec *spec = codec->spec; |
6903 | const struct hda_input_mux *imux = spec->input_mux; | ||
6904 | int c; | 7056 | int c; |
6905 | 7057 | ||
6906 | for (c = 0; c < spec->num_adc_nids; c++) { | 7058 | for (c = 0; c < spec->num_adc_nids; c++) { |
6907 | hda_nid_t conn_list[HDA_MAX_NUM_INPUTS]; | 7059 | hda_nid_t conn_list[HDA_MAX_NUM_INPUTS]; |
6908 | hda_nid_t nid = spec->capsrc_nids[c]; | 7060 | hda_nid_t nid = spec->capsrc_nids[c]; |
7061 | unsigned int mux_idx; | ||
7062 | const struct hda_input_mux *imux; | ||
6909 | int conns, mute, idx, item; | 7063 | int conns, mute, idx, item; |
6910 | 7064 | ||
6911 | conns = snd_hda_get_connections(codec, nid, conn_list, | 7065 | conns = snd_hda_get_connections(codec, nid, conn_list, |
6912 | ARRAY_SIZE(conn_list)); | 7066 | ARRAY_SIZE(conn_list)); |
6913 | if (conns < 0) | 7067 | if (conns < 0) |
6914 | continue; | 7068 | continue; |
7069 | mux_idx = c >= spec->num_mux_defs ? 0 : c; | ||
7070 | imux = &spec->input_mux[mux_idx]; | ||
6915 | for (idx = 0; idx < conns; idx++) { | 7071 | for (idx = 0; idx < conns; idx++) { |
6916 | /* if the current connection is the selected one, | 7072 | /* if the current connection is the selected one, |
6917 | * unmute it as default - otherwise mute it | 7073 | * unmute it as default - otherwise mute it |
@@ -6924,8 +7080,20 @@ static void alc882_auto_init_input_src(struct hda_codec *codec) | |||
6924 | break; | 7080 | break; |
6925 | } | 7081 | } |
6926 | } | 7082 | } |
6927 | snd_hda_codec_write(codec, nid, 0, | 7083 | /* check if we have a selector or mixer |
6928 | AC_VERB_SET_AMP_GAIN_MUTE, mute); | 7084 | * we could check for the widget type instead, but |
7085 | * just check for Amp-In presence (in case of mixer | ||
7086 | * without amp-in there is something wrong, this | ||
7087 | * function shouldn't be used or capsrc nid is wrong) | ||
7088 | */ | ||
7089 | if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) | ||
7090 | snd_hda_codec_write(codec, nid, 0, | ||
7091 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
7092 | mute); | ||
7093 | else if (mute != AMP_IN_MUTE(idx)) | ||
7094 | snd_hda_codec_write(codec, nid, 0, | ||
7095 | AC_VERB_SET_CONNECT_SEL, | ||
7096 | idx); | ||
6929 | } | 7097 | } |
6930 | } | 7098 | } |
6931 | } | 7099 | } |
@@ -7054,6 +7222,12 @@ static int patch_alc882(struct hda_codec *codec) | |||
7054 | } | 7222 | } |
7055 | } | 7223 | } |
7056 | 7224 | ||
7225 | err = snd_hda_attach_beep_device(codec, 0x1); | ||
7226 | if (err < 0) { | ||
7227 | alc_free(codec); | ||
7228 | return err; | ||
7229 | } | ||
7230 | |||
7057 | if (board_config != ALC882_AUTO) | 7231 | if (board_config != ALC882_AUTO) |
7058 | setup_preset(spec, &alc882_presets[board_config]); | 7232 | setup_preset(spec, &alc882_presets[board_config]); |
7059 | 7233 | ||
@@ -7074,7 +7248,7 @@ static int patch_alc882(struct hda_codec *codec) | |||
7074 | spec->stream_digital_playback = &alc882_pcm_digital_playback; | 7248 | spec->stream_digital_playback = &alc882_pcm_digital_playback; |
7075 | spec->stream_digital_capture = &alc882_pcm_digital_capture; | 7249 | spec->stream_digital_capture = &alc882_pcm_digital_capture; |
7076 | 7250 | ||
7077 | spec->is_mix_capture = 1; /* matrix-style capture */ | 7251 | spec->capture_style = CAPT_MIX; /* matrix-style capture */ |
7078 | if (!spec->adc_nids && spec->input_mux) { | 7252 | if (!spec->adc_nids && spec->input_mux) { |
7079 | /* check whether NID 0x07 is valid */ | 7253 | /* check whether NID 0x07 is valid */ |
7080 | unsigned int wcap = get_wcaps(codec, 0x07); | 7254 | unsigned int wcap = get_wcaps(codec, 0x07); |
@@ -7091,6 +7265,7 @@ static int patch_alc882(struct hda_codec *codec) | |||
7091 | } | 7265 | } |
7092 | } | 7266 | } |
7093 | set_capture_mixer(spec); | 7267 | set_capture_mixer(spec); |
7268 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | ||
7094 | 7269 | ||
7095 | spec->vmaster_nid = 0x0c; | 7270 | spec->vmaster_nid = 0x0c; |
7096 | 7271 | ||
@@ -7142,10 +7317,14 @@ static hda_nid_t alc883_adc_nids_rev[2] = { | |||
7142 | 0x09, 0x08 | 7317 | 0x09, 0x08 |
7143 | }; | 7318 | }; |
7144 | 7319 | ||
7320 | #define alc889_adc_nids alc880_adc_nids | ||
7321 | |||
7145 | static hda_nid_t alc883_capsrc_nids[2] = { 0x23, 0x22 }; | 7322 | static hda_nid_t alc883_capsrc_nids[2] = { 0x23, 0x22 }; |
7146 | 7323 | ||
7147 | static hda_nid_t alc883_capsrc_nids_rev[2] = { 0x22, 0x23 }; | 7324 | static hda_nid_t alc883_capsrc_nids_rev[2] = { 0x22, 0x23 }; |
7148 | 7325 | ||
7326 | #define alc889_capsrc_nids alc882_capsrc_nids | ||
7327 | |||
7149 | /* input MUX */ | 7328 | /* input MUX */ |
7150 | /* FIXME: should be a matrix-type input source selection */ | 7329 | /* FIXME: should be a matrix-type input source selection */ |
7151 | 7330 | ||
@@ -7363,8 +7542,6 @@ static struct snd_kcontrol_new alc883_base_mixer[] = { | |||
7363 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 7542 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
7364 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | 7543 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), |
7365 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 7544 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
7366 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
7367 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
7368 | { } /* end */ | 7545 | { } /* end */ |
7369 | }; | 7546 | }; |
7370 | 7547 | ||
@@ -7427,8 +7604,6 @@ static struct snd_kcontrol_new alc883_3ST_2ch_mixer[] = { | |||
7427 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 7604 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
7428 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | 7605 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), |
7429 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 7606 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
7430 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
7431 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
7432 | { } /* end */ | 7607 | { } /* end */ |
7433 | }; | 7608 | }; |
7434 | 7609 | ||
@@ -7452,8 +7627,6 @@ static struct snd_kcontrol_new alc883_3ST_6ch_mixer[] = { | |||
7452 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 7627 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
7453 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | 7628 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), |
7454 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 7629 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
7455 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
7456 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
7457 | { } /* end */ | 7630 | { } /* end */ |
7458 | }; | 7631 | }; |
7459 | 7632 | ||
@@ -7478,8 +7651,6 @@ static struct snd_kcontrol_new alc883_3ST_6ch_intel_mixer[] = { | |||
7478 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 7651 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
7479 | HDA_CODEC_VOLUME("Front Mic Boost", 0x18, 0, HDA_INPUT), | 7652 | HDA_CODEC_VOLUME("Front Mic Boost", 0x18, 0, HDA_INPUT), |
7480 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 7653 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
7481 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
7482 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
7483 | { } /* end */ | 7654 | { } /* end */ |
7484 | }; | 7655 | }; |
7485 | 7656 | ||
@@ -7503,8 +7674,6 @@ static struct snd_kcontrol_new alc883_fivestack_mixer[] = { | |||
7503 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 7674 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
7504 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | 7675 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), |
7505 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 7676 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
7506 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
7507 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
7508 | { } /* end */ | 7677 | { } /* end */ |
7509 | }; | 7678 | }; |
7510 | 7679 | ||
@@ -7912,36 +8081,83 @@ static struct hda_verb alc888_lenovo_sky_verbs[] = { | |||
7912 | { } /* end */ | 8081 | { } /* end */ |
7913 | }; | 8082 | }; |
7914 | 8083 | ||
8084 | static struct hda_verb alc888_6st_dell_verbs[] = { | ||
8085 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, | ||
8086 | { } | ||
8087 | }; | ||
8088 | |||
8089 | static void alc888_3st_hp_front_automute(struct hda_codec *codec) | ||
8090 | { | ||
8091 | unsigned int present, bits; | ||
8092 | |||
8093 | present = snd_hda_codec_read(codec, 0x1b, 0, | ||
8094 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
8095 | bits = present ? HDA_AMP_MUTE : 0; | ||
8096 | snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, | ||
8097 | HDA_AMP_MUTE, bits); | ||
8098 | snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0, | ||
8099 | HDA_AMP_MUTE, bits); | ||
8100 | snd_hda_codec_amp_stereo(codec, 0x18, HDA_OUTPUT, 0, | ||
8101 | HDA_AMP_MUTE, bits); | ||
8102 | } | ||
8103 | |||
8104 | static void alc888_3st_hp_unsol_event(struct hda_codec *codec, | ||
8105 | unsigned int res) | ||
8106 | { | ||
8107 | switch (res >> 26) { | ||
8108 | case ALC880_HP_EVENT: | ||
8109 | alc888_3st_hp_front_automute(codec); | ||
8110 | break; | ||
8111 | } | ||
8112 | } | ||
8113 | |||
7915 | static struct hda_verb alc888_3st_hp_verbs[] = { | 8114 | static struct hda_verb alc888_3st_hp_verbs[] = { |
7916 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front: output 0 (0x0c) */ | 8115 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front: output 0 (0x0c) */ |
7917 | {0x16, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Rear : output 1 (0x0d) */ | 8116 | {0x16, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Rear : output 1 (0x0d) */ |
7918 | {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* CLFE : output 2 (0x0e) */ | 8117 | {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* CLFE : output 2 (0x0e) */ |
7919 | { } | ||
7920 | }; | ||
7921 | |||
7922 | static struct hda_verb alc888_6st_dell_verbs[] = { | ||
7923 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, | 8118 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, |
7924 | { } | 8119 | { } /* end */ |
7925 | }; | 8120 | }; |
7926 | 8121 | ||
8122 | /* | ||
8123 | * 2ch mode | ||
8124 | */ | ||
7927 | static struct hda_verb alc888_3st_hp_2ch_init[] = { | 8125 | static struct hda_verb alc888_3st_hp_2ch_init[] = { |
7928 | { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, | 8126 | { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, |
7929 | { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, | 8127 | { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, |
7930 | { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | 8128 | { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, |
7931 | { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, | 8129 | { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, |
7932 | { } | 8130 | { } /* end */ |
8131 | }; | ||
8132 | |||
8133 | /* | ||
8134 | * 4ch mode | ||
8135 | */ | ||
8136 | static struct hda_verb alc888_3st_hp_4ch_init[] = { | ||
8137 | { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, | ||
8138 | { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, | ||
8139 | { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
8140 | { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, | ||
8141 | { 0x16, AC_VERB_SET_CONNECT_SEL, 0x01 }, | ||
8142 | { } /* end */ | ||
7933 | }; | 8143 | }; |
7934 | 8144 | ||
8145 | /* | ||
8146 | * 6ch mode | ||
8147 | */ | ||
7935 | static struct hda_verb alc888_3st_hp_6ch_init[] = { | 8148 | static struct hda_verb alc888_3st_hp_6ch_init[] = { |
7936 | { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | 8149 | { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, |
7937 | { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, | 8150 | { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, |
8151 | { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 }, | ||
7938 | { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | 8152 | { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, |
7939 | { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, | 8153 | { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, |
7940 | { } | 8154 | { 0x16, AC_VERB_SET_CONNECT_SEL, 0x01 }, |
8155 | { } /* end */ | ||
7941 | }; | 8156 | }; |
7942 | 8157 | ||
7943 | static struct hda_channel_mode alc888_3st_hp_modes[2] = { | 8158 | static struct hda_channel_mode alc888_3st_hp_modes[3] = { |
7944 | { 2, alc888_3st_hp_2ch_init }, | 8159 | { 2, alc888_3st_hp_2ch_init }, |
8160 | { 4, alc888_3st_hp_4ch_init }, | ||
7945 | { 6, alc888_3st_hp_6ch_init }, | 8161 | { 6, alc888_3st_hp_6ch_init }, |
7946 | }; | 8162 | }; |
7947 | 8163 | ||
@@ -8202,7 +8418,7 @@ static void alc888_6st_dell_unsol_event(struct hda_codec *codec, | |||
8202 | { | 8418 | { |
8203 | switch (res >> 26) { | 8419 | switch (res >> 26) { |
8204 | case ALC880_HP_EVENT: | 8420 | case ALC880_HP_EVENT: |
8205 | printk("hp_event\n"); | 8421 | /* printk(KERN_DEBUG "hp_event\n"); */ |
8206 | alc888_6st_dell_front_automute(codec); | 8422 | alc888_6st_dell_front_automute(codec); |
8207 | break; | 8423 | break; |
8208 | } | 8424 | } |
@@ -8461,6 +8677,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { | |||
8461 | SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC883_3ST_6ch_DIG), | 8677 | SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC883_3ST_6ch_DIG), |
8462 | SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_ACER_ASPIRE), | 8678 | SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_ACER_ASPIRE), |
8463 | SND_PCI_QUIRK(0x1025, 0x0090, "Acer Aspire", ALC883_ACER_ASPIRE), | 8679 | SND_PCI_QUIRK(0x1025, 0x0090, "Acer Aspire", ALC883_ACER_ASPIRE), |
8680 | SND_PCI_QUIRK(0x1025, 0x010a, "Acer Ferrari 5000", ALC883_ACER_ASPIRE), | ||
8464 | SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_ACER_ASPIRE), | 8681 | SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_ACER_ASPIRE), |
8465 | SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_ACER_ASPIRE), | 8682 | SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_ACER_ASPIRE), |
8466 | SND_PCI_QUIRK(0x1025, 0x0121, "Acer Aspire 5920G", ALC883_ACER_ASPIRE), | 8683 | SND_PCI_QUIRK(0x1025, 0x0121, "Acer Aspire 5920G", ALC883_ACER_ASPIRE), |
@@ -8468,17 +8685,21 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { | |||
8468 | ALC888_ACER_ASPIRE_4930G), | 8685 | ALC888_ACER_ASPIRE_4930G), |
8469 | SND_PCI_QUIRK(0x1025, 0x013f, "Acer Aspire 5930G", | 8686 | SND_PCI_QUIRK(0x1025, 0x013f, "Acer Aspire 5930G", |
8470 | ALC888_ACER_ASPIRE_4930G), | 8687 | ALC888_ACER_ASPIRE_4930G), |
8688 | SND_PCI_QUIRK(0x1025, 0x0157, "Acer X3200", ALC883_AUTO), | ||
8689 | SND_PCI_QUIRK(0x1025, 0x0158, "Acer AX1700-U3700A", ALC883_AUTO), | ||
8471 | SND_PCI_QUIRK(0x1025, 0x015e, "Acer Aspire 6930G", | 8690 | SND_PCI_QUIRK(0x1025, 0x015e, "Acer Aspire 6930G", |
8472 | ALC888_ACER_ASPIRE_4930G), | 8691 | ALC888_ACER_ASPIRE_4930G), |
8473 | SND_PCI_QUIRK(0x1025, 0x0166, "Acer Aspire 6530G", | 8692 | SND_PCI_QUIRK(0x1025, 0x0166, "Acer Aspire 6530G", |
8474 | ALC888_ACER_ASPIRE_4930G), | 8693 | ALC888_ACER_ASPIRE_4930G), |
8475 | SND_PCI_QUIRK(0x1025, 0, "Acer laptop", ALC883_ACER), /* default Acer */ | 8694 | /* default Acer */ |
8695 | SND_PCI_QUIRK_VENDOR(0x1025, "Acer laptop", ALC883_ACER), | ||
8476 | SND_PCI_QUIRK(0x1028, 0x020d, "Dell Inspiron 530", ALC888_6ST_DELL), | 8696 | SND_PCI_QUIRK(0x1028, 0x020d, "Dell Inspiron 530", ALC888_6ST_DELL), |
8477 | SND_PCI_QUIRK(0x103c, 0x2a3d, "HP Pavillion", ALC883_6ST_DIG), | 8697 | SND_PCI_QUIRK(0x103c, 0x2a3d, "HP Pavillion", ALC883_6ST_DIG), |
8478 | SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP), | 8698 | SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP), |
8479 | SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP), | 8699 | SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP), |
8480 | SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC883_6ST_DIG), | 8700 | SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC883_6ST_DIG), |
8481 | SND_PCI_QUIRK(0x103c, 0x2a66, "HP Acacia", ALC888_3ST_HP), | 8701 | SND_PCI_QUIRK(0x103c, 0x2a66, "HP Acacia", ALC888_3ST_HP), |
8702 | SND_PCI_QUIRK(0x103c, 0x2a72, "HP Educ.ar", ALC888_3ST_HP), | ||
8482 | SND_PCI_QUIRK(0x1043, 0x1873, "Asus M90V", ALC888_ASUS_M90V), | 8703 | SND_PCI_QUIRK(0x1043, 0x1873, "Asus M90V", ALC888_ASUS_M90V), |
8483 | SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG), | 8704 | SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG), |
8484 | SND_PCI_QUIRK(0x1043, 0x8284, "Asus Z37E", ALC883_6ST_DIG), | 8705 | SND_PCI_QUIRK(0x1043, 0x8284, "Asus Z37E", ALC883_6ST_DIG), |
@@ -8518,7 +8739,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { | |||
8518 | SND_PCI_QUIRK(0x147b, 0x1083, "Abit IP35-PRO", ALC883_6ST_DIG), | 8739 | SND_PCI_QUIRK(0x147b, 0x1083, "Abit IP35-PRO", ALC883_6ST_DIG), |
8519 | SND_PCI_QUIRK(0x1558, 0x0721, "Clevo laptop M720R", ALC883_CLEVO_M720), | 8740 | SND_PCI_QUIRK(0x1558, 0x0721, "Clevo laptop M720R", ALC883_CLEVO_M720), |
8520 | SND_PCI_QUIRK(0x1558, 0x0722, "Clevo laptop M720SR", ALC883_CLEVO_M720), | 8741 | SND_PCI_QUIRK(0x1558, 0x0722, "Clevo laptop M720SR", ALC883_CLEVO_M720), |
8521 | SND_PCI_QUIRK(0x1558, 0, "Clevo laptop", ALC883_LAPTOP_EAPD), | 8742 | SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC883_LAPTOP_EAPD), |
8522 | SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch), | 8743 | SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch), |
8523 | SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION), | 8744 | SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION), |
8524 | SND_PCI_QUIRK(0x1734, 0x1107, "FSC AMILO Xi2550", | 8745 | SND_PCI_QUIRK(0x1734, 0x1107, "FSC AMILO Xi2550", |
@@ -8543,6 +8764,10 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { | |||
8543 | {} | 8764 | {} |
8544 | }; | 8765 | }; |
8545 | 8766 | ||
8767 | static hda_nid_t alc1200_slave_dig_outs[] = { | ||
8768 | ALC883_DIGOUT_NID, 0, | ||
8769 | }; | ||
8770 | |||
8546 | static struct alc_config_preset alc883_presets[] = { | 8771 | static struct alc_config_preset alc883_presets[] = { |
8547 | [ALC883_3ST_2ch_DIG] = { | 8772 | [ALC883_3ST_2ch_DIG] = { |
8548 | .mixers = { alc883_3ST_2ch_mixer }, | 8773 | .mixers = { alc883_3ST_2ch_mixer }, |
@@ -8778,6 +9003,8 @@ static struct alc_config_preset alc883_presets[] = { | |||
8778 | .channel_mode = alc888_3st_hp_modes, | 9003 | .channel_mode = alc888_3st_hp_modes, |
8779 | .need_dac_fix = 1, | 9004 | .need_dac_fix = 1, |
8780 | .input_mux = &alc883_capture_source, | 9005 | .input_mux = &alc883_capture_source, |
9006 | .unsol_event = alc888_3st_hp_unsol_event, | ||
9007 | .init_hook = alc888_3st_hp_front_automute, | ||
8781 | }, | 9008 | }, |
8782 | [ALC888_6ST_DELL] = { | 9009 | [ALC888_6ST_DELL] = { |
8783 | .mixers = { alc883_base_mixer, alc883_chmode_mixer }, | 9010 | .mixers = { alc883_base_mixer, alc883_chmode_mixer }, |
@@ -8883,6 +9110,7 @@ static struct alc_config_preset alc883_presets[] = { | |||
8883 | .dac_nids = alc883_dac_nids, | 9110 | .dac_nids = alc883_dac_nids, |
8884 | .dig_out_nid = ALC1200_DIGOUT_NID, | 9111 | .dig_out_nid = ALC1200_DIGOUT_NID, |
8885 | .dig_in_nid = ALC883_DIGIN_NID, | 9112 | .dig_in_nid = ALC883_DIGIN_NID, |
9113 | .slave_dig_outs = alc1200_slave_dig_outs, | ||
8886 | .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes), | 9114 | .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes), |
8887 | .channel_mode = alc883_sixstack_modes, | 9115 | .channel_mode = alc883_sixstack_modes, |
8888 | .input_mux = &alc883_capture_source, | 9116 | .input_mux = &alc883_capture_source, |
@@ -8950,11 +9178,9 @@ static void alc883_auto_init_analog_input(struct hda_codec *codec) | |||
8950 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 9178 | for (i = 0; i < AUTO_PIN_LAST; i++) { |
8951 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 9179 | hda_nid_t nid = spec->autocfg.input_pins[i]; |
8952 | if (alc883_is_input_pin(nid)) { | 9180 | if (alc883_is_input_pin(nid)) { |
8953 | snd_hda_codec_write(codec, nid, 0, | 9181 | alc_set_input_pin(codec, nid, i); |
8954 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 9182 | if (nid != ALC883_PIN_CD_NID && |
8955 | (i <= AUTO_PIN_FRONT_MIC ? | 9183 | (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) |
8956 | PIN_VREF80 : PIN_IN)); | ||
8957 | if (nid != ALC883_PIN_CD_NID) | ||
8958 | snd_hda_codec_write(codec, nid, 0, | 9184 | snd_hda_codec_write(codec, nid, 0, |
8959 | AC_VERB_SET_AMP_GAIN_MUTE, | 9185 | AC_VERB_SET_AMP_GAIN_MUTE, |
8960 | AMP_OUT_MUTE); | 9186 | AMP_OUT_MUTE); |
@@ -8969,6 +9195,8 @@ static int alc883_parse_auto_config(struct hda_codec *codec) | |||
8969 | { | 9195 | { |
8970 | struct alc_spec *spec = codec->spec; | 9196 | struct alc_spec *spec = codec->spec; |
8971 | int err = alc880_parse_auto_config(codec); | 9197 | int err = alc880_parse_auto_config(codec); |
9198 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
9199 | int i; | ||
8972 | 9200 | ||
8973 | if (err < 0) | 9201 | if (err < 0) |
8974 | return err; | 9202 | return err; |
@@ -8982,6 +9210,26 @@ static int alc883_parse_auto_config(struct hda_codec *codec) | |||
8982 | /* hack - override the init verbs */ | 9210 | /* hack - override the init verbs */ |
8983 | spec->init_verbs[0] = alc883_auto_init_verbs; | 9211 | spec->init_verbs[0] = alc883_auto_init_verbs; |
8984 | 9212 | ||
9213 | /* setup input_mux for ALC889 */ | ||
9214 | if (codec->vendor_id == 0x10ec0889) { | ||
9215 | /* digital-mic input pin is excluded in alc880_auto_create..() | ||
9216 | * because it's under 0x18 | ||
9217 | */ | ||
9218 | if (cfg->input_pins[AUTO_PIN_MIC] == 0x12 || | ||
9219 | cfg->input_pins[AUTO_PIN_FRONT_MIC] == 0x12) { | ||
9220 | struct hda_input_mux *imux = &spec->private_imux[0]; | ||
9221 | for (i = 1; i < 3; i++) | ||
9222 | memcpy(&spec->private_imux[i], | ||
9223 | &spec->private_imux[0], | ||
9224 | sizeof(spec->private_imux[0])); | ||
9225 | imux->items[imux->num_items].label = "Int DMic"; | ||
9226 | imux->items[imux->num_items].index = 0x0b; | ||
9227 | imux->num_items++; | ||
9228 | spec->num_mux_defs = 3; | ||
9229 | spec->input_mux = spec->private_imux; | ||
9230 | } | ||
9231 | } | ||
9232 | |||
8985 | return 1; /* config found */ | 9233 | return 1; /* config found */ |
8986 | } | 9234 | } |
8987 | 9235 | ||
@@ -9033,6 +9281,12 @@ static int patch_alc883(struct hda_codec *codec) | |||
9033 | } | 9281 | } |
9034 | } | 9282 | } |
9035 | 9283 | ||
9284 | err = snd_hda_attach_beep_device(codec, 0x1); | ||
9285 | if (err < 0) { | ||
9286 | alc_free(codec); | ||
9287 | return err; | ||
9288 | } | ||
9289 | |||
9036 | if (board_config != ALC883_AUTO) | 9290 | if (board_config != ALC883_AUTO) |
9037 | setup_preset(spec, &alc883_presets[board_config]); | 9291 | setup_preset(spec, &alc883_presets[board_config]); |
9038 | 9292 | ||
@@ -9045,14 +9299,36 @@ static int patch_alc883(struct hda_codec *codec) | |||
9045 | spec->stream_name_analog = "ALC888 Analog"; | 9299 | spec->stream_name_analog = "ALC888 Analog"; |
9046 | spec->stream_name_digital = "ALC888 Digital"; | 9300 | spec->stream_name_digital = "ALC888 Digital"; |
9047 | } | 9301 | } |
9302 | if (!spec->num_adc_nids) { | ||
9303 | spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids); | ||
9304 | spec->adc_nids = alc883_adc_nids; | ||
9305 | } | ||
9306 | if (!spec->capsrc_nids) | ||
9307 | spec->capsrc_nids = alc883_capsrc_nids; | ||
9308 | spec->capture_style = CAPT_MIX; /* matrix-style capture */ | ||
9048 | break; | 9309 | break; |
9049 | case 0x10ec0889: | 9310 | case 0x10ec0889: |
9050 | spec->stream_name_analog = "ALC889 Analog"; | 9311 | spec->stream_name_analog = "ALC889 Analog"; |
9051 | spec->stream_name_digital = "ALC889 Digital"; | 9312 | spec->stream_name_digital = "ALC889 Digital"; |
9313 | if (!spec->num_adc_nids) { | ||
9314 | spec->num_adc_nids = ARRAY_SIZE(alc889_adc_nids); | ||
9315 | spec->adc_nids = alc889_adc_nids; | ||
9316 | } | ||
9317 | if (!spec->capsrc_nids) | ||
9318 | spec->capsrc_nids = alc889_capsrc_nids; | ||
9319 | spec->capture_style = CAPT_1MUX_MIX; /* 1mux/Nmix-style | ||
9320 | capture */ | ||
9052 | break; | 9321 | break; |
9053 | default: | 9322 | default: |
9054 | spec->stream_name_analog = "ALC883 Analog"; | 9323 | spec->stream_name_analog = "ALC883 Analog"; |
9055 | spec->stream_name_digital = "ALC883 Digital"; | 9324 | spec->stream_name_digital = "ALC883 Digital"; |
9325 | if (!spec->num_adc_nids) { | ||
9326 | spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids); | ||
9327 | spec->adc_nids = alc883_adc_nids; | ||
9328 | } | ||
9329 | if (!spec->capsrc_nids) | ||
9330 | spec->capsrc_nids = alc883_capsrc_nids; | ||
9331 | spec->capture_style = CAPT_MIX; /* matrix-style capture */ | ||
9056 | break; | 9332 | break; |
9057 | } | 9333 | } |
9058 | 9334 | ||
@@ -9063,15 +9339,9 @@ static int patch_alc883(struct hda_codec *codec) | |||
9063 | spec->stream_digital_playback = &alc883_pcm_digital_playback; | 9339 | spec->stream_digital_playback = &alc883_pcm_digital_playback; |
9064 | spec->stream_digital_capture = &alc883_pcm_digital_capture; | 9340 | spec->stream_digital_capture = &alc883_pcm_digital_capture; |
9065 | 9341 | ||
9066 | if (!spec->num_adc_nids) { | ||
9067 | spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids); | ||
9068 | spec->adc_nids = alc883_adc_nids; | ||
9069 | } | ||
9070 | if (!spec->capsrc_nids) | ||
9071 | spec->capsrc_nids = alc883_capsrc_nids; | ||
9072 | spec->is_mix_capture = 1; /* matrix-style capture */ | ||
9073 | if (!spec->cap_mixer) | 9342 | if (!spec->cap_mixer) |
9074 | set_capture_mixer(spec); | 9343 | set_capture_mixer(spec); |
9344 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | ||
9075 | 9345 | ||
9076 | spec->vmaster_nid = 0x0c; | 9346 | spec->vmaster_nid = 0x0c; |
9077 | 9347 | ||
@@ -9124,8 +9394,6 @@ static struct snd_kcontrol_new alc262_base_mixer[] = { | |||
9124 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), | 9394 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), |
9125 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), | 9395 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), |
9126 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | 9396 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), |
9127 | /* HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
9128 | HDA_CODEC_MUTE("PC Beep Playback Switch", 0x0b, 0x05, HDA_INPUT), */ | ||
9129 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT), | 9397 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT), |
9130 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), | 9398 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), |
9131 | HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), | 9399 | HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), |
@@ -9146,8 +9414,6 @@ static struct snd_kcontrol_new alc262_hippo1_mixer[] = { | |||
9146 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), | 9414 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), |
9147 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), | 9415 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), |
9148 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | 9416 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), |
9149 | /* HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
9150 | HDA_CODEC_MUTE("PC Beep Playback Switch", 0x0b, 0x05, HDA_INPUT), */ | ||
9151 | /*HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),*/ | 9417 | /*HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),*/ |
9152 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | 9418 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), |
9153 | { } /* end */ | 9419 | { } /* end */ |
@@ -9256,8 +9522,6 @@ static struct snd_kcontrol_new alc262_HP_BPC_mixer[] = { | |||
9256 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | 9522 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), |
9257 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | 9523 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), |
9258 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | 9524 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), |
9259 | HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
9260 | HDA_CODEC_MUTE("PC Beep Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
9261 | HDA_CODEC_VOLUME("AUX IN Playback Volume", 0x0b, 0x06, HDA_INPUT), | 9525 | HDA_CODEC_VOLUME("AUX IN Playback Volume", 0x0b, 0x06, HDA_INPUT), |
9262 | HDA_CODEC_MUTE("AUX IN Playback Switch", 0x0b, 0x06, HDA_INPUT), | 9526 | HDA_CODEC_MUTE("AUX IN Playback Switch", 0x0b, 0x06, HDA_INPUT), |
9263 | { } /* end */ | 9527 | { } /* end */ |
@@ -9286,8 +9550,6 @@ static struct snd_kcontrol_new alc262_HP_BPC_WildWest_mixer[] = { | |||
9286 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT), | 9550 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT), |
9287 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | 9551 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), |
9288 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | 9552 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), |
9289 | HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
9290 | HDA_CODEC_MUTE("PC Beep Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
9291 | { } /* end */ | 9553 | { } /* end */ |
9292 | }; | 9554 | }; |
9293 | 9555 | ||
@@ -9435,6 +9697,67 @@ static struct snd_kcontrol_new alc262_benq_t31_mixer[] = { | |||
9435 | { } /* end */ | 9697 | { } /* end */ |
9436 | }; | 9698 | }; |
9437 | 9699 | ||
9700 | static struct snd_kcontrol_new alc262_tyan_mixer[] = { | ||
9701 | HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
9702 | HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT), | ||
9703 | HDA_CODEC_VOLUME("Aux Playback Volume", 0x0b, 0x06, HDA_INPUT), | ||
9704 | HDA_CODEC_MUTE("Aux Playback Switch", 0x0b, 0x06, HDA_INPUT), | ||
9705 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | ||
9706 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | ||
9707 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
9708 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
9709 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | ||
9710 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), | ||
9711 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), | ||
9712 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | ||
9713 | { } /* end */ | ||
9714 | }; | ||
9715 | |||
9716 | static struct hda_verb alc262_tyan_verbs[] = { | ||
9717 | /* Headphone automute */ | ||
9718 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, | ||
9719 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
9720 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
9721 | |||
9722 | /* P11 AUX_IN, white 4-pin connector */ | ||
9723 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
9724 | {0x14, AC_VERB_SET_CONFIG_DEFAULT_BYTES_1, 0xe1}, | ||
9725 | {0x14, AC_VERB_SET_CONFIG_DEFAULT_BYTES_2, 0x93}, | ||
9726 | {0x14, AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, 0x19}, | ||
9727 | |||
9728 | {} | ||
9729 | }; | ||
9730 | |||
9731 | /* unsolicited event for HP jack sensing */ | ||
9732 | static void alc262_tyan_automute(struct hda_codec *codec) | ||
9733 | { | ||
9734 | unsigned int mute; | ||
9735 | unsigned int present; | ||
9736 | |||
9737 | snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_SET_PIN_SENSE, 0); | ||
9738 | present = snd_hda_codec_read(codec, 0x1b, 0, | ||
9739 | AC_VERB_GET_PIN_SENSE, 0); | ||
9740 | present = (present & 0x80000000) != 0; | ||
9741 | if (present) { | ||
9742 | /* mute line output on ATX panel */ | ||
9743 | snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, | ||
9744 | HDA_AMP_MUTE, HDA_AMP_MUTE); | ||
9745 | } else { | ||
9746 | /* unmute line output if necessary */ | ||
9747 | mute = snd_hda_codec_amp_read(codec, 0x1b, 0, HDA_OUTPUT, 0); | ||
9748 | snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, | ||
9749 | HDA_AMP_MUTE, mute); | ||
9750 | } | ||
9751 | } | ||
9752 | |||
9753 | static void alc262_tyan_unsol_event(struct hda_codec *codec, | ||
9754 | unsigned int res) | ||
9755 | { | ||
9756 | if ((res >> 26) != ALC880_HP_EVENT) | ||
9757 | return; | ||
9758 | alc262_tyan_automute(codec); | ||
9759 | } | ||
9760 | |||
9438 | #define alc262_capture_mixer alc882_capture_mixer | 9761 | #define alc262_capture_mixer alc882_capture_mixer |
9439 | #define alc262_capture_alt_mixer alc882_capture_alt_mixer | 9762 | #define alc262_capture_alt_mixer alc882_capture_alt_mixer |
9440 | 9763 | ||
@@ -9901,8 +10224,6 @@ static struct snd_kcontrol_new alc262_fujitsu_mixer[] = { | |||
9901 | }, | 10224 | }, |
9902 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | 10225 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), |
9903 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | 10226 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), |
9904 | HDA_CODEC_VOLUME("PC Speaker Volume", 0x0b, 0x05, HDA_INPUT), | ||
9905 | HDA_CODEC_MUTE("PC Speaker Switch", 0x0b, 0x05, HDA_INPUT), | ||
9906 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 10227 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), |
9907 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 10228 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
9908 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 10229 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
@@ -10474,8 +10795,14 @@ static int alc262_parse_auto_config(struct hda_codec *codec) | |||
10474 | alc262_ignore); | 10795 | alc262_ignore); |
10475 | if (err < 0) | 10796 | if (err < 0) |
10476 | return err; | 10797 | return err; |
10477 | if (!spec->autocfg.line_outs) | 10798 | if (!spec->autocfg.line_outs) { |
10799 | if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) { | ||
10800 | spec->multiout.max_channels = 2; | ||
10801 | spec->no_analog = 1; | ||
10802 | goto dig_only; | ||
10803 | } | ||
10478 | return 0; /* can't find valid BIOS pin config */ | 10804 | return 0; /* can't find valid BIOS pin config */ |
10805 | } | ||
10479 | err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg); | 10806 | err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg); |
10480 | if (err < 0) | 10807 | if (err < 0) |
10481 | return err; | 10808 | return err; |
@@ -10485,8 +10812,11 @@ static int alc262_parse_auto_config(struct hda_codec *codec) | |||
10485 | 10812 | ||
10486 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 10813 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
10487 | 10814 | ||
10488 | if (spec->autocfg.dig_out_pin) | 10815 | dig_only: |
10816 | if (spec->autocfg.dig_outs) { | ||
10489 | spec->multiout.dig_out_nid = ALC262_DIGOUT_NID; | 10817 | spec->multiout.dig_out_nid = ALC262_DIGOUT_NID; |
10818 | spec->dig_out_type = spec->autocfg.dig_out_type[0]; | ||
10819 | } | ||
10490 | if (spec->autocfg.dig_in_pin) | 10820 | if (spec->autocfg.dig_in_pin) |
10491 | spec->dig_in_nid = ALC262_DIGIN_NID; | 10821 | spec->dig_in_nid = ALC262_DIGIN_NID; |
10492 | 10822 | ||
@@ -10495,13 +10825,12 @@ static int alc262_parse_auto_config(struct hda_codec *codec) | |||
10495 | 10825 | ||
10496 | add_verb(spec, alc262_volume_init_verbs); | 10826 | add_verb(spec, alc262_volume_init_verbs); |
10497 | spec->num_mux_defs = 1; | 10827 | spec->num_mux_defs = 1; |
10498 | spec->input_mux = &spec->private_imux; | 10828 | spec->input_mux = &spec->private_imux[0]; |
10499 | 10829 | ||
10500 | err = alc_auto_add_mic_boost(codec); | 10830 | err = alc_auto_add_mic_boost(codec); |
10501 | if (err < 0) | 10831 | if (err < 0) |
10502 | return err; | 10832 | return err; |
10503 | 10833 | ||
10504 | store_pin_configs(codec); | ||
10505 | return 1; | 10834 | return 1; |
10506 | } | 10835 | } |
10507 | 10836 | ||
@@ -10543,21 +10872,19 @@ static const char *alc262_models[ALC262_MODEL_LAST] = { | |||
10543 | [ALC262_ULTRA] = "ultra", | 10872 | [ALC262_ULTRA] = "ultra", |
10544 | [ALC262_LENOVO_3000] = "lenovo-3000", | 10873 | [ALC262_LENOVO_3000] = "lenovo-3000", |
10545 | [ALC262_NEC] = "nec", | 10874 | [ALC262_NEC] = "nec", |
10875 | [ALC262_TYAN] = "tyan", | ||
10546 | [ALC262_AUTO] = "auto", | 10876 | [ALC262_AUTO] = "auto", |
10547 | }; | 10877 | }; |
10548 | 10878 | ||
10549 | static struct snd_pci_quirk alc262_cfg_tbl[] = { | 10879 | static struct snd_pci_quirk alc262_cfg_tbl[] = { |
10550 | SND_PCI_QUIRK(0x1002, 0x437b, "Hippo", ALC262_HIPPO), | 10880 | SND_PCI_QUIRK(0x1002, 0x437b, "Hippo", ALC262_HIPPO), |
10551 | SND_PCI_QUIRK(0x1033, 0x8895, "NEC Versa S9100", ALC262_NEC), | 10881 | SND_PCI_QUIRK(0x1033, 0x8895, "NEC Versa S9100", ALC262_NEC), |
10552 | SND_PCI_QUIRK(0x103c, 0x12fe, "HP xw9400", ALC262_HP_BPC), | 10882 | SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1200, "HP xw series", |
10553 | SND_PCI_QUIRK(0x103c, 0x12ff, "HP xw4550", ALC262_HP_BPC), | 10883 | ALC262_HP_BPC), |
10554 | SND_PCI_QUIRK(0x103c, 0x1306, "HP xw8600", ALC262_HP_BPC), | 10884 | SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1300, "HP xw series", |
10555 | SND_PCI_QUIRK(0x103c, 0x1307, "HP xw6600", ALC262_HP_BPC), | 10885 | ALC262_HP_BPC), |
10556 | SND_PCI_QUIRK(0x103c, 0x1308, "HP xw4600", ALC262_HP_BPC), | 10886 | SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1700, "HP xw series", |
10557 | SND_PCI_QUIRK(0x103c, 0x1309, "HP xw4*00", ALC262_HP_BPC), | 10887 | ALC262_HP_BPC), |
10558 | SND_PCI_QUIRK(0x103c, 0x130a, "HP xw6*00", ALC262_HP_BPC), | ||
10559 | SND_PCI_QUIRK(0x103c, 0x130b, "HP xw8*00", ALC262_HP_BPC), | ||
10560 | SND_PCI_QUIRK(0x103c, 0x170b, "HP xw*", ALC262_HP_BPC), | ||
10561 | SND_PCI_QUIRK(0x103c, 0x2800, "HP D7000", ALC262_HP_BPC_D7000_WL), | 10888 | SND_PCI_QUIRK(0x103c, 0x2800, "HP D7000", ALC262_HP_BPC_D7000_WL), |
10562 | SND_PCI_QUIRK(0x103c, 0x2801, "HP D7000", ALC262_HP_BPC_D7000_WF), | 10889 | SND_PCI_QUIRK(0x103c, 0x2801, "HP D7000", ALC262_HP_BPC_D7000_WF), |
10563 | SND_PCI_QUIRK(0x103c, 0x2802, "HP D7000", ALC262_HP_BPC_D7000_WL), | 10890 | SND_PCI_QUIRK(0x103c, 0x2802, "HP D7000", ALC262_HP_BPC_D7000_WL), |
@@ -10575,17 +10902,17 @@ static struct snd_pci_quirk alc262_cfg_tbl[] = { | |||
10575 | SND_PCI_QUIRK(0x104d, 0x1f00, "Sony ASSAMD", ALC262_SONY_ASSAMD), | 10902 | SND_PCI_QUIRK(0x104d, 0x1f00, "Sony ASSAMD", ALC262_SONY_ASSAMD), |
10576 | SND_PCI_QUIRK(0x104d, 0x8203, "Sony UX-90", ALC262_HIPPO), | 10903 | SND_PCI_QUIRK(0x104d, 0x8203, "Sony UX-90", ALC262_HIPPO), |
10577 | SND_PCI_QUIRK(0x104d, 0x820f, "Sony ASSAMD", ALC262_SONY_ASSAMD), | 10904 | SND_PCI_QUIRK(0x104d, 0x820f, "Sony ASSAMD", ALC262_SONY_ASSAMD), |
10578 | SND_PCI_QUIRK(0x104d, 0x900e, "Sony ASSAMD", ALC262_SONY_ASSAMD), | 10905 | SND_PCI_QUIRK(0x104d, 0x9016, "Sony VAIO", ALC262_AUTO), /* dig-only */ |
10579 | SND_PCI_QUIRK(0x104d, 0x9015, "Sony 0x9015", ALC262_SONY_ASSAMD), | 10906 | SND_PCI_QUIRK_MASK(0x104d, 0xff00, 0x9000, "Sony VAIO", |
10580 | SND_PCI_QUIRK(0x104d, 0x9033, "Sony VAIO VGN-SR19XN", | 10907 | ALC262_SONY_ASSAMD), |
10581 | ALC262_SONY_ASSAMD), | ||
10582 | SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba dynabook SS RX1", | 10908 | SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba dynabook SS RX1", |
10583 | ALC262_TOSHIBA_RX1), | 10909 | ALC262_TOSHIBA_RX1), |
10584 | SND_PCI_QUIRK(0x1179, 0xff7b, "Toshiba S06", ALC262_TOSHIBA_S06), | 10910 | SND_PCI_QUIRK(0x1179, 0xff7b, "Toshiba S06", ALC262_TOSHIBA_S06), |
10585 | SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU), | 10911 | SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU), |
10586 | SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FUJITSU), | 10912 | SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FUJITSU), |
10587 | SND_PCI_QUIRK(0x144d, 0xc032, "Samsung Q1 Ultra", ALC262_ULTRA), | 10913 | SND_PCI_QUIRK(0x10f1, 0x2915, "Tyan Thunder n6650W", ALC262_TYAN), |
10588 | SND_PCI_QUIRK(0x144d, 0xc039, "Samsung Q1U EL", ALC262_ULTRA), | 10914 | SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc032, "Samsung Q1", |
10915 | ALC262_ULTRA), | ||
10589 | SND_PCI_QUIRK(0x144d, 0xc510, "Samsung Q45", ALC262_HIPPO), | 10916 | SND_PCI_QUIRK(0x144d, 0xc510, "Samsung Q45", ALC262_HIPPO), |
10590 | SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000 y410", ALC262_LENOVO_3000), | 10917 | SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000 y410", ALC262_LENOVO_3000), |
10591 | SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8), | 10918 | SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8), |
@@ -10802,6 +11129,19 @@ static struct alc_config_preset alc262_presets[] = { | |||
10802 | .unsol_event = alc262_hippo_unsol_event, | 11129 | .unsol_event = alc262_hippo_unsol_event, |
10803 | .init_hook = alc262_hippo_automute, | 11130 | .init_hook = alc262_hippo_automute, |
10804 | }, | 11131 | }, |
11132 | [ALC262_TYAN] = { | ||
11133 | .mixers = { alc262_tyan_mixer }, | ||
11134 | .init_verbs = { alc262_init_verbs, alc262_tyan_verbs}, | ||
11135 | .num_dacs = ARRAY_SIZE(alc262_dac_nids), | ||
11136 | .dac_nids = alc262_dac_nids, | ||
11137 | .hp_nid = 0x02, | ||
11138 | .dig_out_nid = ALC262_DIGOUT_NID, | ||
11139 | .num_channel_mode = ARRAY_SIZE(alc262_modes), | ||
11140 | .channel_mode = alc262_modes, | ||
11141 | .input_mux = &alc262_capture_source, | ||
11142 | .unsol_event = alc262_tyan_unsol_event, | ||
11143 | .init_hook = alc262_tyan_automute, | ||
11144 | }, | ||
10805 | }; | 11145 | }; |
10806 | 11146 | ||
10807 | static int patch_alc262(struct hda_codec *codec) | 11147 | static int patch_alc262(struct hda_codec *codec) |
@@ -10854,6 +11194,14 @@ static int patch_alc262(struct hda_codec *codec) | |||
10854 | } | 11194 | } |
10855 | } | 11195 | } |
10856 | 11196 | ||
11197 | if (!spec->no_analog) { | ||
11198 | err = snd_hda_attach_beep_device(codec, 0x1); | ||
11199 | if (err < 0) { | ||
11200 | alc_free(codec); | ||
11201 | return err; | ||
11202 | } | ||
11203 | } | ||
11204 | |||
10857 | if (board_config != ALC262_AUTO) | 11205 | if (board_config != ALC262_AUTO) |
10858 | setup_preset(spec, &alc262_presets[board_config]); | 11206 | setup_preset(spec, &alc262_presets[board_config]); |
10859 | 11207 | ||
@@ -10865,7 +11213,7 @@ static int patch_alc262(struct hda_codec *codec) | |||
10865 | spec->stream_digital_playback = &alc262_pcm_digital_playback; | 11213 | spec->stream_digital_playback = &alc262_pcm_digital_playback; |
10866 | spec->stream_digital_capture = &alc262_pcm_digital_capture; | 11214 | spec->stream_digital_capture = &alc262_pcm_digital_capture; |
10867 | 11215 | ||
10868 | spec->is_mix_capture = 1; | 11216 | spec->capture_style = CAPT_MIX; |
10869 | if (!spec->adc_nids && spec->input_mux) { | 11217 | if (!spec->adc_nids && spec->input_mux) { |
10870 | /* check whether NID 0x07 is valid */ | 11218 | /* check whether NID 0x07 is valid */ |
10871 | unsigned int wcap = get_wcaps(codec, 0x07); | 11219 | unsigned int wcap = get_wcaps(codec, 0x07); |
@@ -10882,8 +11230,10 @@ static int patch_alc262(struct hda_codec *codec) | |||
10882 | spec->capsrc_nids = alc262_capsrc_nids; | 11230 | spec->capsrc_nids = alc262_capsrc_nids; |
10883 | } | 11231 | } |
10884 | } | 11232 | } |
10885 | if (!spec->cap_mixer) | 11233 | if (!spec->cap_mixer && !spec->no_analog) |
10886 | set_capture_mixer(spec); | 11234 | set_capture_mixer(spec); |
11235 | if (!spec->no_analog) | ||
11236 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | ||
10887 | 11237 | ||
10888 | spec->vmaster_nid = 0x0c; | 11238 | spec->vmaster_nid = 0x0c; |
10889 | 11239 | ||
@@ -11263,19 +11613,13 @@ static void alc267_quanta_il1_unsol_event(struct hda_codec *codec, | |||
11263 | static struct hda_verb alc268_base_init_verbs[] = { | 11613 | static struct hda_verb alc268_base_init_verbs[] = { |
11264 | /* Unmute DAC0-1 and set vol = 0 */ | 11614 | /* Unmute DAC0-1 and set vol = 0 */ |
11265 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | 11615 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, |
11266 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
11267 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
11268 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | 11616 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, |
11269 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
11270 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
11271 | 11617 | ||
11272 | /* | 11618 | /* |
11273 | * Set up output mixers (0x0c - 0x0e) | 11619 | * Set up output mixers (0x0c - 0x0e) |
11274 | */ | 11620 | */ |
11275 | /* set vol=0 to output mixers */ | 11621 | /* set vol=0 to output mixers */ |
11276 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 11622 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
11277 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
11278 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
11279 | {0x0e, AC_VERB_SET_CONNECT_SEL, 0x00}, | 11623 | {0x0e, AC_VERB_SET_CONNECT_SEL, 0x00}, |
11280 | 11624 | ||
11281 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 11625 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
@@ -11294,9 +11638,7 @@ static struct hda_verb alc268_base_init_verbs[] = { | |||
11294 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | 11638 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, |
11295 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | 11639 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, |
11296 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | 11640 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, |
11297 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
11298 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | 11641 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, |
11299 | {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
11300 | 11642 | ||
11301 | /* set PCBEEP vol = 0, mute connections */ | 11643 | /* set PCBEEP vol = 0, mute connections */ |
11302 | {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 11644 | {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
@@ -11318,10 +11660,8 @@ static struct hda_verb alc268_base_init_verbs[] = { | |||
11318 | */ | 11660 | */ |
11319 | static struct hda_verb alc268_volume_init_verbs[] = { | 11661 | static struct hda_verb alc268_volume_init_verbs[] = { |
11320 | /* set output DAC */ | 11662 | /* set output DAC */ |
11321 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 11663 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, |
11322 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 11664 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, |
11323 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
11324 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
11325 | 11665 | ||
11326 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, | 11666 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, |
11327 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, | 11667 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, |
@@ -11329,16 +11669,12 @@ static struct hda_verb alc268_volume_init_verbs[] = { | |||
11329 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, | 11669 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, |
11330 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, | 11670 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, |
11331 | 11671 | ||
11332 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
11333 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 11672 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
11334 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
11335 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 11673 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
11336 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 11674 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
11337 | 11675 | ||
11338 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | 11676 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, |
11339 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
11340 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | 11677 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, |
11341 | {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
11342 | 11678 | ||
11343 | /* set PCBEEP vol = 0, mute connections */ | 11679 | /* set PCBEEP vol = 0, mute connections */ |
11344 | {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 11680 | {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
@@ -11537,7 +11873,7 @@ static int alc268_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
11537 | static int alc268_auto_create_analog_input_ctls(struct alc_spec *spec, | 11873 | static int alc268_auto_create_analog_input_ctls(struct alc_spec *spec, |
11538 | const struct auto_pin_cfg *cfg) | 11874 | const struct auto_pin_cfg *cfg) |
11539 | { | 11875 | { |
11540 | struct hda_input_mux *imux = &spec->private_imux; | 11876 | struct hda_input_mux *imux = &spec->private_imux[0]; |
11541 | int i, idx1; | 11877 | int i, idx1; |
11542 | 11878 | ||
11543 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 11879 | for (i = 0; i < AUTO_PIN_LAST; i++) { |
@@ -11631,9 +11967,14 @@ static int alc268_parse_auto_config(struct hda_codec *codec) | |||
11631 | alc268_ignore); | 11967 | alc268_ignore); |
11632 | if (err < 0) | 11968 | if (err < 0) |
11633 | return err; | 11969 | return err; |
11634 | if (!spec->autocfg.line_outs) | 11970 | if (!spec->autocfg.line_outs) { |
11971 | if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) { | ||
11972 | spec->multiout.max_channels = 2; | ||
11973 | spec->no_analog = 1; | ||
11974 | goto dig_only; | ||
11975 | } | ||
11635 | return 0; /* can't find valid BIOS pin config */ | 11976 | return 0; /* can't find valid BIOS pin config */ |
11636 | 11977 | } | |
11637 | err = alc268_auto_create_multi_out_ctls(spec, &spec->autocfg); | 11978 | err = alc268_auto_create_multi_out_ctls(spec, &spec->autocfg); |
11638 | if (err < 0) | 11979 | if (err < 0) |
11639 | return err; | 11980 | return err; |
@@ -11643,25 +11984,26 @@ static int alc268_parse_auto_config(struct hda_codec *codec) | |||
11643 | 11984 | ||
11644 | spec->multiout.max_channels = 2; | 11985 | spec->multiout.max_channels = 2; |
11645 | 11986 | ||
11987 | dig_only: | ||
11646 | /* digital only support output */ | 11988 | /* digital only support output */ |
11647 | if (spec->autocfg.dig_out_pin) | 11989 | if (spec->autocfg.dig_outs) { |
11648 | spec->multiout.dig_out_nid = ALC268_DIGOUT_NID; | 11990 | spec->multiout.dig_out_nid = ALC268_DIGOUT_NID; |
11649 | 11991 | spec->dig_out_type = spec->autocfg.dig_out_type[0]; | |
11992 | } | ||
11650 | if (spec->kctls.list) | 11993 | if (spec->kctls.list) |
11651 | add_mixer(spec, spec->kctls.list); | 11994 | add_mixer(spec, spec->kctls.list); |
11652 | 11995 | ||
11653 | if (spec->autocfg.speaker_pins[0] != 0x1d) | 11996 | if (!spec->no_analog && spec->autocfg.speaker_pins[0] != 0x1d) |
11654 | add_mixer(spec, alc268_beep_mixer); | 11997 | add_mixer(spec, alc268_beep_mixer); |
11655 | 11998 | ||
11656 | add_verb(spec, alc268_volume_init_verbs); | 11999 | add_verb(spec, alc268_volume_init_verbs); |
11657 | spec->num_mux_defs = 1; | 12000 | spec->num_mux_defs = 1; |
11658 | spec->input_mux = &spec->private_imux; | 12001 | spec->input_mux = &spec->private_imux[0]; |
11659 | 12002 | ||
11660 | err = alc_auto_add_mic_boost(codec); | 12003 | err = alc_auto_add_mic_boost(codec); |
11661 | if (err < 0) | 12004 | if (err < 0) |
11662 | return err; | 12005 | return err; |
11663 | 12006 | ||
11664 | store_pin_configs(codec); | ||
11665 | return 1; | 12007 | return 1; |
11666 | } | 12008 | } |
11667 | 12009 | ||
@@ -11723,7 +12065,7 @@ static struct snd_pci_quirk alc268_cfg_tbl[] = { | |||
11723 | 12065 | ||
11724 | static struct alc_config_preset alc268_presets[] = { | 12066 | static struct alc_config_preset alc268_presets[] = { |
11725 | [ALC267_QUANTA_IL1] = { | 12067 | [ALC267_QUANTA_IL1] = { |
11726 | .mixers = { alc267_quanta_il1_mixer }, | 12068 | .mixers = { alc267_quanta_il1_mixer, alc268_beep_mixer }, |
11727 | .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, | 12069 | .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, |
11728 | alc267_quanta_il1_verbs }, | 12070 | alc267_quanta_il1_verbs }, |
11729 | .num_dacs = ARRAY_SIZE(alc268_dac_nids), | 12071 | .num_dacs = ARRAY_SIZE(alc268_dac_nids), |
@@ -11805,7 +12147,8 @@ static struct alc_config_preset alc268_presets[] = { | |||
11805 | }, | 12147 | }, |
11806 | [ALC268_ACER_ASPIRE_ONE] = { | 12148 | [ALC268_ACER_ASPIRE_ONE] = { |
11807 | .mixers = { alc268_acer_aspire_one_mixer, | 12149 | .mixers = { alc268_acer_aspire_one_mixer, |
11808 | alc268_capture_alt_mixer }, | 12150 | alc268_beep_mixer, |
12151 | alc268_capture_alt_mixer }, | ||
11809 | .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, | 12152 | .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, |
11810 | alc268_acer_aspire_one_verbs }, | 12153 | alc268_acer_aspire_one_verbs }, |
11811 | .num_dacs = ARRAY_SIZE(alc268_dac_nids), | 12154 | .num_dacs = ARRAY_SIZE(alc268_dac_nids), |
@@ -11874,7 +12217,7 @@ static int patch_alc268(struct hda_codec *codec) | |||
11874 | { | 12217 | { |
11875 | struct alc_spec *spec; | 12218 | struct alc_spec *spec; |
11876 | int board_config; | 12219 | int board_config; |
11877 | int err; | 12220 | int i, has_beep, err; |
11878 | 12221 | ||
11879 | spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); | 12222 | spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); |
11880 | if (spec == NULL) | 12223 | if (spec == NULL) |
@@ -11923,15 +12266,30 @@ static int patch_alc268(struct hda_codec *codec) | |||
11923 | 12266 | ||
11924 | spec->stream_digital_playback = &alc268_pcm_digital_playback; | 12267 | spec->stream_digital_playback = &alc268_pcm_digital_playback; |
11925 | 12268 | ||
11926 | if (!query_amp_caps(codec, 0x1d, HDA_INPUT)) | 12269 | has_beep = 0; |
11927 | /* override the amp caps for beep generator */ | 12270 | for (i = 0; i < spec->num_mixers; i++) { |
11928 | snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT, | 12271 | if (spec->mixers[i] == alc268_beep_mixer) { |
12272 | has_beep = 1; | ||
12273 | break; | ||
12274 | } | ||
12275 | } | ||
12276 | |||
12277 | if (has_beep) { | ||
12278 | err = snd_hda_attach_beep_device(codec, 0x1); | ||
12279 | if (err < 0) { | ||
12280 | alc_free(codec); | ||
12281 | return err; | ||
12282 | } | ||
12283 | if (!query_amp_caps(codec, 0x1d, HDA_INPUT)) | ||
12284 | /* override the amp caps for beep generator */ | ||
12285 | snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT, | ||
11929 | (0x0c << AC_AMPCAP_OFFSET_SHIFT) | | 12286 | (0x0c << AC_AMPCAP_OFFSET_SHIFT) | |
11930 | (0x0c << AC_AMPCAP_NUM_STEPS_SHIFT) | | 12287 | (0x0c << AC_AMPCAP_NUM_STEPS_SHIFT) | |
11931 | (0x07 << AC_AMPCAP_STEP_SIZE_SHIFT) | | 12288 | (0x07 << AC_AMPCAP_STEP_SIZE_SHIFT) | |
11932 | (0 << AC_AMPCAP_MUTE_SHIFT)); | 12289 | (0 << AC_AMPCAP_MUTE_SHIFT)); |
12290 | } | ||
11933 | 12291 | ||
11934 | if (!spec->adc_nids && spec->input_mux) { | 12292 | if (!spec->no_analog && !spec->adc_nids && spec->input_mux) { |
11935 | /* check whether NID 0x07 is valid */ | 12293 | /* check whether NID 0x07 is valid */ |
11936 | unsigned int wcap = get_wcaps(codec, 0x07); | 12294 | unsigned int wcap = get_wcaps(codec, 0x07); |
11937 | int i; | 12295 | int i; |
@@ -12012,8 +12370,6 @@ static struct snd_kcontrol_new alc269_base_mixer[] = { | |||
12012 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | 12370 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), |
12013 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 12371 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
12014 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 12372 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
12015 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x0b, 0x4, HDA_INPUT), | ||
12016 | HDA_CODEC_MUTE("Beep Playback Switch", 0x0b, 0x4, HDA_INPUT), | ||
12017 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 12373 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), |
12018 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), | 12374 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), |
12019 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), | 12375 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), |
@@ -12040,8 +12396,6 @@ static struct snd_kcontrol_new alc269_quanta_fl1_mixer[] = { | |||
12040 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), | 12396 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), |
12041 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), | 12397 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), |
12042 | HDA_CODEC_VOLUME("Internal Mic Boost", 0x19, 0, HDA_INPUT), | 12398 | HDA_CODEC_VOLUME("Internal Mic Boost", 0x19, 0, HDA_INPUT), |
12043 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
12044 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
12045 | { } | 12399 | { } |
12046 | }; | 12400 | }; |
12047 | 12401 | ||
@@ -12065,8 +12419,6 @@ static struct snd_kcontrol_new alc269_lifebook_mixer[] = { | |||
12065 | HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x0b, 0x03, HDA_INPUT), | 12419 | HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x0b, 0x03, HDA_INPUT), |
12066 | HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x0b, 0x03, HDA_INPUT), | 12420 | HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x0b, 0x03, HDA_INPUT), |
12067 | HDA_CODEC_VOLUME("Dock Mic Boost", 0x1b, 0, HDA_INPUT), | 12421 | HDA_CODEC_VOLUME("Dock Mic Boost", 0x1b, 0, HDA_INPUT), |
12068 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
12069 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
12070 | { } | 12422 | { } |
12071 | }; | 12423 | }; |
12072 | 12424 | ||
@@ -12103,13 +12455,6 @@ static struct snd_kcontrol_new alc269_fujitsu_mixer[] = { | |||
12103 | { } /* end */ | 12455 | { } /* end */ |
12104 | }; | 12456 | }; |
12105 | 12457 | ||
12106 | /* beep control */ | ||
12107 | static struct snd_kcontrol_new alc269_beep_mixer[] = { | ||
12108 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x0b, 0x4, HDA_INPUT), | ||
12109 | HDA_CODEC_MUTE("Beep Playback Switch", 0x0b, 0x4, HDA_INPUT), | ||
12110 | { } /* end */ | ||
12111 | }; | ||
12112 | |||
12113 | static struct hda_verb alc269_quanta_fl1_verbs[] = { | 12458 | static struct hda_verb alc269_quanta_fl1_verbs[] = { |
12114 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, | 12459 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, |
12115 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | 12460 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, |
@@ -12509,7 +12854,7 @@ static int alc269_auto_create_analog_input_ctls(struct alc_spec *spec, | |||
12509 | */ | 12854 | */ |
12510 | if (cfg->input_pins[AUTO_PIN_MIC] == 0x12 || | 12855 | if (cfg->input_pins[AUTO_PIN_MIC] == 0x12 || |
12511 | cfg->input_pins[AUTO_PIN_FRONT_MIC] == 0x12) { | 12856 | cfg->input_pins[AUTO_PIN_FRONT_MIC] == 0x12) { |
12512 | struct hda_input_mux *imux = &spec->private_imux; | 12857 | struct hda_input_mux *imux = &spec->private_imux[0]; |
12513 | imux->items[imux->num_items].label = "Int Mic"; | 12858 | imux->items[imux->num_items].label = "Int Mic"; |
12514 | imux->items[imux->num_items].index = 0x05; | 12859 | imux->items[imux->num_items].index = 0x05; |
12515 | imux->num_items++; | 12860 | imux->num_items++; |
@@ -12527,13 +12872,34 @@ static int alc269_auto_create_analog_input_ctls(struct alc_spec *spec, | |||
12527 | #define alc269_pcm_digital_playback alc880_pcm_digital_playback | 12872 | #define alc269_pcm_digital_playback alc880_pcm_digital_playback |
12528 | #define alc269_pcm_digital_capture alc880_pcm_digital_capture | 12873 | #define alc269_pcm_digital_capture alc880_pcm_digital_capture |
12529 | 12874 | ||
12875 | static struct hda_pcm_stream alc269_44k_pcm_analog_playback = { | ||
12876 | .substreams = 1, | ||
12877 | .channels_min = 2, | ||
12878 | .channels_max = 8, | ||
12879 | .rates = SNDRV_PCM_RATE_44100, /* fixed rate */ | ||
12880 | /* NID is set in alc_build_pcms */ | ||
12881 | .ops = { | ||
12882 | .open = alc880_playback_pcm_open, | ||
12883 | .prepare = alc880_playback_pcm_prepare, | ||
12884 | .cleanup = alc880_playback_pcm_cleanup | ||
12885 | }, | ||
12886 | }; | ||
12887 | |||
12888 | static struct hda_pcm_stream alc269_44k_pcm_analog_capture = { | ||
12889 | .substreams = 1, | ||
12890 | .channels_min = 2, | ||
12891 | .channels_max = 2, | ||
12892 | .rates = SNDRV_PCM_RATE_44100, /* fixed rate */ | ||
12893 | /* NID is set in alc_build_pcms */ | ||
12894 | }; | ||
12895 | |||
12530 | /* | 12896 | /* |
12531 | * BIOS auto configuration | 12897 | * BIOS auto configuration |
12532 | */ | 12898 | */ |
12533 | static int alc269_parse_auto_config(struct hda_codec *codec) | 12899 | static int alc269_parse_auto_config(struct hda_codec *codec) |
12534 | { | 12900 | { |
12535 | struct alc_spec *spec = codec->spec; | 12901 | struct alc_spec *spec = codec->spec; |
12536 | int i, err; | 12902 | int err; |
12537 | static hda_nid_t alc269_ignore[] = { 0x1d, 0 }; | 12903 | static hda_nid_t alc269_ignore[] = { 0x1d, 0 }; |
12538 | 12904 | ||
12539 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, | 12905 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, |
@@ -12550,22 +12916,15 @@ static int alc269_parse_auto_config(struct hda_codec *codec) | |||
12550 | 12916 | ||
12551 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 12917 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
12552 | 12918 | ||
12553 | if (spec->autocfg.dig_out_pin) | 12919 | if (spec->autocfg.dig_outs) |
12554 | spec->multiout.dig_out_nid = ALC269_DIGOUT_NID; | 12920 | spec->multiout.dig_out_nid = ALC269_DIGOUT_NID; |
12555 | 12921 | ||
12556 | if (spec->kctls.list) | 12922 | if (spec->kctls.list) |
12557 | add_mixer(spec, spec->kctls.list); | 12923 | add_mixer(spec, spec->kctls.list); |
12558 | 12924 | ||
12559 | /* create a beep mixer control if the pin 0x1d isn't assigned */ | ||
12560 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.input_pins); i++) | ||
12561 | if (spec->autocfg.input_pins[i] == 0x1d) | ||
12562 | break; | ||
12563 | if (i >= ARRAY_SIZE(spec->autocfg.input_pins)) | ||
12564 | add_mixer(spec, alc269_beep_mixer); | ||
12565 | |||
12566 | add_verb(spec, alc269_init_verbs); | 12925 | add_verb(spec, alc269_init_verbs); |
12567 | spec->num_mux_defs = 1; | 12926 | spec->num_mux_defs = 1; |
12568 | spec->input_mux = &spec->private_imux; | 12927 | spec->input_mux = &spec->private_imux[0]; |
12569 | /* set default input source */ | 12928 | /* set default input source */ |
12570 | snd_hda_codec_write_cache(codec, alc269_capsrc_nids[0], | 12929 | snd_hda_codec_write_cache(codec, alc269_capsrc_nids[0], |
12571 | 0, AC_VERB_SET_CONNECT_SEL, | 12930 | 0, AC_VERB_SET_CONNECT_SEL, |
@@ -12575,10 +12934,9 @@ static int alc269_parse_auto_config(struct hda_codec *codec) | |||
12575 | if (err < 0) | 12934 | if (err < 0) |
12576 | return err; | 12935 | return err; |
12577 | 12936 | ||
12578 | if (!spec->cap_mixer) | 12937 | if (!spec->cap_mixer && !spec->no_analog) |
12579 | set_capture_mixer(spec); | 12938 | set_capture_mixer(spec); |
12580 | 12939 | ||
12581 | store_pin_configs(codec); | ||
12582 | return 1; | 12940 | return 1; |
12583 | } | 12941 | } |
12584 | 12942 | ||
@@ -12675,7 +13033,7 @@ static struct alc_config_preset alc269_presets[] = { | |||
12675 | .init_hook = alc269_eeepc_dmic_inithook, | 13033 | .init_hook = alc269_eeepc_dmic_inithook, |
12676 | }, | 13034 | }, |
12677 | [ALC269_FUJITSU] = { | 13035 | [ALC269_FUJITSU] = { |
12678 | .mixers = { alc269_fujitsu_mixer, alc269_beep_mixer }, | 13036 | .mixers = { alc269_fujitsu_mixer }, |
12679 | .cap_mixer = alc269_epc_capture_mixer, | 13037 | .cap_mixer = alc269_epc_capture_mixer, |
12680 | .init_verbs = { alc269_init_verbs, | 13038 | .init_verbs = { alc269_init_verbs, |
12681 | alc269_eeepc_dmic_init_verbs }, | 13039 | alc269_eeepc_dmic_init_verbs }, |
@@ -12740,13 +13098,26 @@ static int patch_alc269(struct hda_codec *codec) | |||
12740 | } | 13098 | } |
12741 | } | 13099 | } |
12742 | 13100 | ||
13101 | err = snd_hda_attach_beep_device(codec, 0x1); | ||
13102 | if (err < 0) { | ||
13103 | alc_free(codec); | ||
13104 | return err; | ||
13105 | } | ||
13106 | |||
12743 | if (board_config != ALC269_AUTO) | 13107 | if (board_config != ALC269_AUTO) |
12744 | setup_preset(spec, &alc269_presets[board_config]); | 13108 | setup_preset(spec, &alc269_presets[board_config]); |
12745 | 13109 | ||
12746 | spec->stream_name_analog = "ALC269 Analog"; | 13110 | spec->stream_name_analog = "ALC269 Analog"; |
12747 | spec->stream_analog_playback = &alc269_pcm_analog_playback; | 13111 | if (codec->subsystem_id == 0x17aa3bf8) { |
12748 | spec->stream_analog_capture = &alc269_pcm_analog_capture; | 13112 | /* Due to a hardware problem on Lenovo Ideadpad, we need to |
12749 | 13113 | * fix the sample rate of analog I/O to 44.1kHz | |
13114 | */ | ||
13115 | spec->stream_analog_playback = &alc269_44k_pcm_analog_playback; | ||
13116 | spec->stream_analog_capture = &alc269_44k_pcm_analog_capture; | ||
13117 | } else { | ||
13118 | spec->stream_analog_playback = &alc269_pcm_analog_playback; | ||
13119 | spec->stream_analog_capture = &alc269_pcm_analog_capture; | ||
13120 | } | ||
12750 | spec->stream_name_digital = "ALC269 Digital"; | 13121 | spec->stream_name_digital = "ALC269 Digital"; |
12751 | spec->stream_digital_playback = &alc269_pcm_digital_playback; | 13122 | spec->stream_digital_playback = &alc269_pcm_digital_playback; |
12752 | spec->stream_digital_capture = &alc269_pcm_digital_capture; | 13123 | spec->stream_digital_capture = &alc269_pcm_digital_capture; |
@@ -12756,6 +13127,7 @@ static int patch_alc269(struct hda_codec *codec) | |||
12756 | spec->capsrc_nids = alc269_capsrc_nids; | 13127 | spec->capsrc_nids = alc269_capsrc_nids; |
12757 | if (!spec->cap_mixer) | 13128 | if (!spec->cap_mixer) |
12758 | set_capture_mixer(spec); | 13129 | set_capture_mixer(spec); |
13130 | set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); | ||
12759 | 13131 | ||
12760 | codec->patch_ops = alc_patch_ops; | 13132 | codec->patch_ops = alc_patch_ops; |
12761 | if (board_config == ALC269_AUTO) | 13133 | if (board_config == ALC269_AUTO) |
@@ -13006,8 +13378,6 @@ static struct snd_kcontrol_new alc861_asus_mixer[] = { | |||
13006 | static struct snd_kcontrol_new alc861_asus_laptop_mixer[] = { | 13378 | static struct snd_kcontrol_new alc861_asus_laptop_mixer[] = { |
13007 | HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT), | 13379 | HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT), |
13008 | HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT), | 13380 | HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT), |
13009 | HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x23, 0x0, HDA_OUTPUT), | ||
13010 | HDA_CODEC_MUTE("PC Beep Playback Switch", 0x23, 0x0, HDA_OUTPUT), | ||
13011 | { } | 13381 | { } |
13012 | }; | 13382 | }; |
13013 | 13383 | ||
@@ -13481,7 +13851,7 @@ static int alc861_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin) | |||
13481 | static int alc861_auto_create_analog_input_ctls(struct alc_spec *spec, | 13851 | static int alc861_auto_create_analog_input_ctls(struct alc_spec *spec, |
13482 | const struct auto_pin_cfg *cfg) | 13852 | const struct auto_pin_cfg *cfg) |
13483 | { | 13853 | { |
13484 | struct hda_input_mux *imux = &spec->private_imux; | 13854 | struct hda_input_mux *imux = &spec->private_imux[0]; |
13485 | int i, err, idx, idx1; | 13855 | int i, err, idx, idx1; |
13486 | 13856 | ||
13487 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 13857 | for (i = 0; i < AUTO_PIN_LAST; i++) { |
@@ -13568,12 +13938,8 @@ static void alc861_auto_init_analog_input(struct hda_codec *codec) | |||
13568 | 13938 | ||
13569 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 13939 | for (i = 0; i < AUTO_PIN_LAST; i++) { |
13570 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 13940 | hda_nid_t nid = spec->autocfg.input_pins[i]; |
13571 | if (nid >= 0x0c && nid <= 0x11) { | 13941 | if (nid >= 0x0c && nid <= 0x11) |
13572 | snd_hda_codec_write(codec, nid, 0, | 13942 | alc_set_input_pin(codec, nid, i); |
13573 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
13574 | i <= AUTO_PIN_FRONT_MIC ? | ||
13575 | PIN_VREF80 : PIN_IN); | ||
13576 | } | ||
13577 | } | 13943 | } |
13578 | } | 13944 | } |
13579 | 13945 | ||
@@ -13609,7 +13975,7 @@ static int alc861_parse_auto_config(struct hda_codec *codec) | |||
13609 | 13975 | ||
13610 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 13976 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
13611 | 13977 | ||
13612 | if (spec->autocfg.dig_out_pin) | 13978 | if (spec->autocfg.dig_outs) |
13613 | spec->multiout.dig_out_nid = ALC861_DIGOUT_NID; | 13979 | spec->multiout.dig_out_nid = ALC861_DIGOUT_NID; |
13614 | 13980 | ||
13615 | if (spec->kctls.list) | 13981 | if (spec->kctls.list) |
@@ -13618,13 +13984,12 @@ static int alc861_parse_auto_config(struct hda_codec *codec) | |||
13618 | add_verb(spec, alc861_auto_init_verbs); | 13984 | add_verb(spec, alc861_auto_init_verbs); |
13619 | 13985 | ||
13620 | spec->num_mux_defs = 1; | 13986 | spec->num_mux_defs = 1; |
13621 | spec->input_mux = &spec->private_imux; | 13987 | spec->input_mux = &spec->private_imux[0]; |
13622 | 13988 | ||
13623 | spec->adc_nids = alc861_adc_nids; | 13989 | spec->adc_nids = alc861_adc_nids; |
13624 | spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids); | 13990 | spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids); |
13625 | set_capture_mixer(spec); | 13991 | set_capture_mixer(spec); |
13626 | 13992 | ||
13627 | store_pin_configs(codec); | ||
13628 | return 1; | 13993 | return 1; |
13629 | } | 13994 | } |
13630 | 13995 | ||
@@ -13833,6 +14198,12 @@ static int patch_alc861(struct hda_codec *codec) | |||
13833 | } | 14198 | } |
13834 | } | 14199 | } |
13835 | 14200 | ||
14201 | err = snd_hda_attach_beep_device(codec, 0x23); | ||
14202 | if (err < 0) { | ||
14203 | alc_free(codec); | ||
14204 | return err; | ||
14205 | } | ||
14206 | |||
13836 | if (board_config != ALC861_AUTO) | 14207 | if (board_config != ALC861_AUTO) |
13837 | setup_preset(spec, &alc861_presets[board_config]); | 14208 | setup_preset(spec, &alc861_presets[board_config]); |
13838 | 14209 | ||
@@ -13844,6 +14215,8 @@ static int patch_alc861(struct hda_codec *codec) | |||
13844 | spec->stream_digital_playback = &alc861_pcm_digital_playback; | 14215 | spec->stream_digital_playback = &alc861_pcm_digital_playback; |
13845 | spec->stream_digital_capture = &alc861_pcm_digital_capture; | 14216 | spec->stream_digital_capture = &alc861_pcm_digital_capture; |
13846 | 14217 | ||
14218 | set_beep_amp(spec, 0x23, 0, HDA_OUTPUT); | ||
14219 | |||
13847 | spec->vmaster_nid = 0x03; | 14220 | spec->vmaster_nid = 0x03; |
13848 | 14221 | ||
13849 | codec->patch_ops = alc_patch_ops; | 14222 | codec->patch_ops = alc_patch_ops; |
@@ -14000,9 +14373,6 @@ static struct snd_kcontrol_new alc861vd_6st_mixer[] = { | |||
14000 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | 14373 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), |
14001 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | 14374 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), |
14002 | 14375 | ||
14003 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
14004 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
14005 | |||
14006 | { } /* end */ | 14376 | { } /* end */ |
14007 | }; | 14377 | }; |
14008 | 14378 | ||
@@ -14026,9 +14396,6 @@ static struct snd_kcontrol_new alc861vd_3st_mixer[] = { | |||
14026 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | 14396 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), |
14027 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | 14397 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), |
14028 | 14398 | ||
14029 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
14030 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
14031 | |||
14032 | { } /* end */ | 14399 | { } /* end */ |
14033 | }; | 14400 | }; |
14034 | 14401 | ||
@@ -14067,8 +14434,6 @@ static struct snd_kcontrol_new alc861vd_dallas_mixer[] = { | |||
14067 | HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT), | 14434 | HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT), |
14068 | HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 14435 | HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
14069 | HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 14436 | HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
14070 | HDA_CODEC_VOLUME("PC Beep Volume", 0x0b, 0x05, HDA_INPUT), | ||
14071 | HDA_CODEC_MUTE("PC Beep Switch", 0x0b, 0x05, HDA_INPUT), | ||
14072 | { } /* end */ | 14437 | { } /* end */ |
14073 | }; | 14438 | }; |
14074 | 14439 | ||
@@ -14379,9 +14744,7 @@ static struct snd_pci_quirk alc861vd_cfg_tbl[] = { | |||
14379 | SND_PCI_QUIRK(0x1179, 0xff03, "Toshiba P205", ALC861VD_LENOVO), | 14744 | SND_PCI_QUIRK(0x1179, 0xff03, "Toshiba P205", ALC861VD_LENOVO), |
14380 | SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba L30-149", ALC861VD_DALLAS), | 14745 | SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba L30-149", ALC861VD_DALLAS), |
14381 | SND_PCI_QUIRK(0x1565, 0x820d, "Biostar NF61S SE", ALC861VD_6ST_DIG), | 14746 | SND_PCI_QUIRK(0x1565, 0x820d, "Biostar NF61S SE", ALC861VD_6ST_DIG), |
14382 | SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo", ALC861VD_LENOVO), | 14747 | SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", ALC861VD_LENOVO), |
14383 | SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo 3000 C200", ALC861VD_LENOVO), | ||
14384 | SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000 N200", ALC861VD_LENOVO), | ||
14385 | SND_PCI_QUIRK(0x1849, 0x0862, "ASRock K8NF6G-VSTA", ALC861VD_6ST_DIG), | 14748 | SND_PCI_QUIRK(0x1849, 0x0862, "ASRock K8NF6G-VSTA", ALC861VD_6ST_DIG), |
14386 | {} | 14749 | {} |
14387 | }; | 14750 | }; |
@@ -14543,11 +14906,9 @@ static void alc861vd_auto_init_analog_input(struct hda_codec *codec) | |||
14543 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 14906 | for (i = 0; i < AUTO_PIN_LAST; i++) { |
14544 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 14907 | hda_nid_t nid = spec->autocfg.input_pins[i]; |
14545 | if (alc861vd_is_input_pin(nid)) { | 14908 | if (alc861vd_is_input_pin(nid)) { |
14546 | snd_hda_codec_write(codec, nid, 0, | 14909 | alc_set_input_pin(codec, nid, i); |
14547 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 14910 | if (nid != ALC861VD_PIN_CD_NID && |
14548 | i <= AUTO_PIN_FRONT_MIC ? | 14911 | (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) |
14549 | PIN_VREF80 : PIN_IN); | ||
14550 | if (nid != ALC861VD_PIN_CD_NID) | ||
14551 | snd_hda_codec_write(codec, nid, 0, | 14912 | snd_hda_codec_write(codec, nid, 0, |
14552 | AC_VERB_SET_AMP_GAIN_MUTE, | 14913 | AC_VERB_SET_AMP_GAIN_MUTE, |
14553 | AMP_OUT_MUTE); | 14914 | AMP_OUT_MUTE); |
@@ -14713,7 +15074,7 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec) | |||
14713 | 15074 | ||
14714 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 15075 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
14715 | 15076 | ||
14716 | if (spec->autocfg.dig_out_pin) | 15077 | if (spec->autocfg.dig_outs) |
14717 | spec->multiout.dig_out_nid = ALC861VD_DIGOUT_NID; | 15078 | spec->multiout.dig_out_nid = ALC861VD_DIGOUT_NID; |
14718 | 15079 | ||
14719 | if (spec->kctls.list) | 15080 | if (spec->kctls.list) |
@@ -14722,13 +15083,12 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec) | |||
14722 | add_verb(spec, alc861vd_volume_init_verbs); | 15083 | add_verb(spec, alc861vd_volume_init_verbs); |
14723 | 15084 | ||
14724 | spec->num_mux_defs = 1; | 15085 | spec->num_mux_defs = 1; |
14725 | spec->input_mux = &spec->private_imux; | 15086 | spec->input_mux = &spec->private_imux[0]; |
14726 | 15087 | ||
14727 | err = alc_auto_add_mic_boost(codec); | 15088 | err = alc_auto_add_mic_boost(codec); |
14728 | if (err < 0) | 15089 | if (err < 0) |
14729 | return err; | 15090 | return err; |
14730 | 15091 | ||
14731 | store_pin_configs(codec); | ||
14732 | return 1; | 15092 | return 1; |
14733 | } | 15093 | } |
14734 | 15094 | ||
@@ -14779,6 +15139,12 @@ static int patch_alc861vd(struct hda_codec *codec) | |||
14779 | } | 15139 | } |
14780 | } | 15140 | } |
14781 | 15141 | ||
15142 | err = snd_hda_attach_beep_device(codec, 0x23); | ||
15143 | if (err < 0) { | ||
15144 | alc_free(codec); | ||
15145 | return err; | ||
15146 | } | ||
15147 | |||
14782 | if (board_config != ALC861VD_AUTO) | 15148 | if (board_config != ALC861VD_AUTO) |
14783 | setup_preset(spec, &alc861vd_presets[board_config]); | 15149 | setup_preset(spec, &alc861vd_presets[board_config]); |
14784 | 15150 | ||
@@ -14801,9 +15167,10 @@ static int patch_alc861vd(struct hda_codec *codec) | |||
14801 | spec->adc_nids = alc861vd_adc_nids; | 15167 | spec->adc_nids = alc861vd_adc_nids; |
14802 | spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids); | 15168 | spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids); |
14803 | spec->capsrc_nids = alc861vd_capsrc_nids; | 15169 | spec->capsrc_nids = alc861vd_capsrc_nids; |
14804 | spec->is_mix_capture = 1; | 15170 | spec->capture_style = CAPT_MIX; |
14805 | 15171 | ||
14806 | set_capture_mixer(spec); | 15172 | set_capture_mixer(spec); |
15173 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | ||
14807 | 15174 | ||
14808 | spec->vmaster_nid = 0x02; | 15175 | spec->vmaster_nid = 0x02; |
14809 | 15176 | ||
@@ -14992,8 +15359,6 @@ static struct snd_kcontrol_new alc662_3ST_2ch_mixer[] = { | |||
14992 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 15359 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
14993 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 15360 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
14994 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 15361 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
14995 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
14996 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
14997 | { } /* end */ | 15362 | { } /* end */ |
14998 | }; | 15363 | }; |
14999 | 15364 | ||
@@ -15015,8 +15380,6 @@ static struct snd_kcontrol_new alc662_3ST_6ch_mixer[] = { | |||
15015 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 15380 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
15016 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 15381 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
15017 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 15382 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
15018 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
15019 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
15020 | { } /* end */ | 15383 | { } /* end */ |
15021 | }; | 15384 | }; |
15022 | 15385 | ||
@@ -15992,56 +16355,55 @@ static const char *alc662_models[ALC662_MODEL_LAST] = { | |||
15992 | }; | 16355 | }; |
15993 | 16356 | ||
15994 | static struct snd_pci_quirk alc662_cfg_tbl[] = { | 16357 | static struct snd_pci_quirk alc662_cfg_tbl[] = { |
15995 | SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M51VA", ALC663_ASUS_M51VA), | 16358 | SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_ECS), |
15996 | SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS G50V", ALC663_ASUS_G50V), | ||
15997 | SND_PCI_QUIRK(0x1043, 0x8290, "ASUS P5GC-MX", ALC662_3ST_6ch_DIG), | ||
15998 | SND_PCI_QUIRK(0x1043, 0x82a1, "ASUS Eeepc", ALC662_ASUS_EEEPC_P701), | ||
15999 | SND_PCI_QUIRK(0x1043, 0x82d1, "ASUS Eeepc EP20", ALC662_ASUS_EEEPC_EP20), | ||
16000 | SND_PCI_QUIRK(0x1043, 0x1903, "ASUS F5GL", ALC663_ASUS_MODE1), | ||
16001 | SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M50Vr", ALC663_ASUS_MODE1), | ||
16002 | SND_PCI_QUIRK(0x1043, 0x1000, "ASUS N50Vm", ALC663_ASUS_MODE1), | 16359 | SND_PCI_QUIRK(0x1043, 0x1000, "ASUS N50Vm", ALC663_ASUS_MODE1), |
16003 | SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS F7Z", ALC663_ASUS_MODE1), | 16360 | SND_PCI_QUIRK(0x1043, 0x1092, "ASUS NB", ALC663_ASUS_MODE3), |
16004 | SND_PCI_QUIRK(0x1043, 0x1953, "ASUS NB", ALC663_ASUS_MODE1), | 16361 | SND_PCI_QUIRK(0x1043, 0x11c3, "ASUS M70V", ALC663_ASUS_MODE3), |
16005 | SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS NB", ALC663_ASUS_MODE1), | ||
16006 | SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC663_ASUS_MODE1), | 16362 | SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC663_ASUS_MODE1), |
16363 | SND_PCI_QUIRK(0x1043, 0x11f3, "ASUS NB", ALC662_ASUS_MODE2), | ||
16007 | SND_PCI_QUIRK(0x1043, 0x1203, "ASUS NB", ALC663_ASUS_MODE1), | 16364 | SND_PCI_QUIRK(0x1043, 0x1203, "ASUS NB", ALC663_ASUS_MODE1), |
16008 | SND_PCI_QUIRK(0x1043, 0x19e3, "ASUS NB", ALC663_ASUS_MODE1), | ||
16009 | SND_PCI_QUIRK(0x1043, 0x1993, "ASUS N20", ALC663_ASUS_MODE1), | ||
16010 | SND_PCI_QUIRK(0x1043, 0x19c3, "ASUS F5Z/F6x", ALC662_ASUS_MODE2), | ||
16011 | SND_PCI_QUIRK(0x1043, 0x1339, "ASUS NB", ALC662_ASUS_MODE2), | 16365 | SND_PCI_QUIRK(0x1043, 0x1339, "ASUS NB", ALC662_ASUS_MODE2), |
16012 | SND_PCI_QUIRK(0x1043, 0x1913, "ASUS NB", ALC662_ASUS_MODE2), | 16366 | SND_PCI_QUIRK(0x1043, 0x16c3, "ASUS NB", ALC662_ASUS_MODE2), |
16013 | SND_PCI_QUIRK(0x1043, 0x1843, "ASUS NB", ALC662_ASUS_MODE2), | 16367 | SND_PCI_QUIRK(0x1043, 0x1753, "ASUS NB", ALC662_ASUS_MODE2), |
16368 | SND_PCI_QUIRK(0x1043, 0x1763, "ASUS NB", ALC663_ASUS_MODE6), | ||
16369 | SND_PCI_QUIRK(0x1043, 0x1765, "ASUS NB", ALC663_ASUS_MODE6), | ||
16370 | SND_PCI_QUIRK(0x1043, 0x1783, "ASUS NB", ALC662_ASUS_MODE2), | ||
16014 | SND_PCI_QUIRK(0x1043, 0x1813, "ASUS NB", ALC662_ASUS_MODE2), | 16371 | SND_PCI_QUIRK(0x1043, 0x1813, "ASUS NB", ALC662_ASUS_MODE2), |
16015 | SND_PCI_QUIRK(0x1043, 0x11f3, "ASUS NB", ALC662_ASUS_MODE2), | 16372 | SND_PCI_QUIRK(0x1043, 0x1823, "ASUS NB", ALC663_ASUS_MODE5), |
16016 | SND_PCI_QUIRK(0x1043, 0x1876, "ASUS NB", ALC662_ASUS_MODE2), | 16373 | SND_PCI_QUIRK(0x1043, 0x1833, "ASUS NB", ALC663_ASUS_MODE6), |
16374 | SND_PCI_QUIRK(0x1043, 0x1843, "ASUS NB", ALC662_ASUS_MODE2), | ||
16017 | SND_PCI_QUIRK(0x1043, 0x1864, "ASUS NB", ALC662_ASUS_MODE2), | 16375 | SND_PCI_QUIRK(0x1043, 0x1864, "ASUS NB", ALC662_ASUS_MODE2), |
16018 | SND_PCI_QUIRK(0x1043, 0x1783, "ASUS NB", ALC662_ASUS_MODE2), | 16376 | SND_PCI_QUIRK(0x1043, 0x1876, "ASUS NB", ALC662_ASUS_MODE2), |
16019 | SND_PCI_QUIRK(0x1043, 0x1753, "ASUS NB", ALC662_ASUS_MODE2), | 16377 | SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M51VA", ALC663_ASUS_M51VA), |
16020 | SND_PCI_QUIRK(0x1043, 0x16c3, "ASUS NB", ALC662_ASUS_MODE2), | 16378 | /*SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M50Vr", ALC663_ASUS_MODE1),*/ |
16021 | SND_PCI_QUIRK(0x1043, 0x1933, "ASUS F80Q", ALC662_ASUS_MODE2), | ||
16022 | SND_PCI_QUIRK(0x1043, 0x1893, "ASUS M50Vm", ALC663_ASUS_MODE3), | 16379 | SND_PCI_QUIRK(0x1043, 0x1893, "ASUS M50Vm", ALC663_ASUS_MODE3), |
16023 | SND_PCI_QUIRK(0x1043, 0x11c3, "ASUS M70V", ALC663_ASUS_MODE3), | ||
16024 | SND_PCI_QUIRK(0x1043, 0x1963, "ASUS X71C", ALC663_ASUS_MODE3), | ||
16025 | SND_PCI_QUIRK(0x1043, 0x1894, "ASUS X55", ALC663_ASUS_MODE3), | 16380 | SND_PCI_QUIRK(0x1043, 0x1894, "ASUS X55", ALC663_ASUS_MODE3), |
16026 | SND_PCI_QUIRK(0x1043, 0x1092, "ASUS NB", ALC663_ASUS_MODE3), | 16381 | SND_PCI_QUIRK(0x1043, 0x1903, "ASUS F5GL", ALC663_ASUS_MODE1), |
16382 | SND_PCI_QUIRK(0x1043, 0x1913, "ASUS NB", ALC662_ASUS_MODE2), | ||
16383 | SND_PCI_QUIRK(0x1043, 0x1933, "ASUS F80Q", ALC662_ASUS_MODE2), | ||
16384 | SND_PCI_QUIRK(0x1043, 0x1953, "ASUS NB", ALC663_ASUS_MODE1), | ||
16385 | SND_PCI_QUIRK(0x1043, 0x1963, "ASUS X71C", ALC663_ASUS_MODE3), | ||
16386 | SND_PCI_QUIRK(0x1043, 0x1993, "ASUS N20", ALC663_ASUS_MODE1), | ||
16387 | SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS G50V", ALC663_ASUS_G50V), | ||
16388 | /*SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS NB", ALC663_ASUS_MODE1),*/ | ||
16389 | SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS F7Z", ALC663_ASUS_MODE1), | ||
16390 | SND_PCI_QUIRK(0x1043, 0x19c3, "ASUS F5Z/F6x", ALC662_ASUS_MODE2), | ||
16391 | SND_PCI_QUIRK(0x1043, 0x19e3, "ASUS NB", ALC663_ASUS_MODE1), | ||
16027 | SND_PCI_QUIRK(0x1043, 0x19f3, "ASUS NB", ALC663_ASUS_MODE4), | 16392 | SND_PCI_QUIRK(0x1043, 0x19f3, "ASUS NB", ALC663_ASUS_MODE4), |
16028 | SND_PCI_QUIRK(0x1043, 0x1823, "ASUS NB", ALC663_ASUS_MODE5), | 16393 | SND_PCI_QUIRK(0x1043, 0x8290, "ASUS P5GC-MX", ALC662_3ST_6ch_DIG), |
16029 | SND_PCI_QUIRK(0x1043, 0x1833, "ASUS NB", ALC663_ASUS_MODE6), | 16394 | SND_PCI_QUIRK(0x1043, 0x82a1, "ASUS Eeepc", ALC662_ASUS_EEEPC_P701), |
16030 | SND_PCI_QUIRK(0x1043, 0x1763, "ASUS NB", ALC663_ASUS_MODE6), | 16395 | SND_PCI_QUIRK(0x1043, 0x82d1, "ASUS Eeepc EP20", ALC662_ASUS_EEEPC_EP20), |
16031 | SND_PCI_QUIRK(0x1043, 0x1765, "ASUS NB", ALC663_ASUS_MODE6), | 16396 | SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_ECS), |
16032 | SND_PCI_QUIRK(0x105b, 0x0d47, "Foxconn 45CMX/45GMX/45CMX-K", | 16397 | SND_PCI_QUIRK(0x105b, 0x0d47, "Foxconn 45CMX/45GMX/45CMX-K", |
16033 | ALC662_3ST_6ch_DIG), | 16398 | ALC662_3ST_6ch_DIG), |
16034 | SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E), | ||
16035 | SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_ECS), | ||
16036 | SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_ECS), | ||
16037 | SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L", | 16399 | SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L", |
16038 | ALC662_3ST_6ch_DIG), | 16400 | ALC662_3ST_6ch_DIG), |
16039 | SND_PCI_QUIRK(0x1565, 0x820f, "Biostar TA780G M2+", ALC662_3ST_6ch_DIG), | 16401 | SND_PCI_QUIRK(0x1565, 0x820f, "Biostar TA780G M2+", ALC662_3ST_6ch_DIG), |
16402 | SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E), | ||
16040 | SND_PCI_QUIRK(0x1849, 0x3662, "ASROCK K10N78FullHD-hSLI R3.0", | 16403 | SND_PCI_QUIRK(0x1849, 0x3662, "ASROCK K10N78FullHD-hSLI R3.0", |
16041 | ALC662_3ST_6ch_DIG), | 16404 | ALC662_3ST_6ch_DIG), |
16042 | SND_PCI_QUIRK(0x1854, 0x2000, "ASUS H13-2000", ALC663_ASUS_H13), | 16405 | SND_PCI_QUIRK_MASK(0x1854, 0xf000, 0x2000, "ASUS H13-200x", |
16043 | SND_PCI_QUIRK(0x1854, 0x2001, "ASUS H13-2001", ALC663_ASUS_H13), | 16406 | ALC663_ASUS_H13), |
16044 | SND_PCI_QUIRK(0x1854, 0x2002, "ASUS H13-2002", ALC663_ASUS_H13), | ||
16045 | {} | 16407 | {} |
16046 | }; | 16408 | }; |
16047 | 16409 | ||
@@ -16361,7 +16723,7 @@ static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin, | |||
16361 | 16723 | ||
16362 | if (alc880_is_fixed_pin(pin)) { | 16724 | if (alc880_is_fixed_pin(pin)) { |
16363 | nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); | 16725 | nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); |
16364 | /* printk("DAC nid=%x\n",nid); */ | 16726 | /* printk(KERN_DEBUG "DAC nid=%x\n",nid); */ |
16365 | /* specify the DAC as the extra output */ | 16727 | /* specify the DAC as the extra output */ |
16366 | if (!spec->multiout.hp_nid) | 16728 | if (!spec->multiout.hp_nid) |
16367 | spec->multiout.hp_nid = nid; | 16729 | spec->multiout.hp_nid = nid; |
@@ -16391,26 +16753,58 @@ static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin, | |||
16391 | return 0; | 16753 | return 0; |
16392 | } | 16754 | } |
16393 | 16755 | ||
16756 | /* return the index of the src widget from the connection list of the nid. | ||
16757 | * return -1 if not found | ||
16758 | */ | ||
16759 | static int alc662_input_pin_idx(struct hda_codec *codec, hda_nid_t nid, | ||
16760 | hda_nid_t src) | ||
16761 | { | ||
16762 | hda_nid_t conn_list[HDA_MAX_CONNECTIONS]; | ||
16763 | int i, conns; | ||
16764 | |||
16765 | conns = snd_hda_get_connections(codec, nid, conn_list, | ||
16766 | ARRAY_SIZE(conn_list)); | ||
16767 | if (conns < 0) | ||
16768 | return -1; | ||
16769 | for (i = 0; i < conns; i++) | ||
16770 | if (conn_list[i] == src) | ||
16771 | return i; | ||
16772 | return -1; | ||
16773 | } | ||
16774 | |||
16775 | static int alc662_is_input_pin(struct hda_codec *codec, hda_nid_t nid) | ||
16776 | { | ||
16777 | unsigned int pincap = snd_hda_query_pin_caps(codec, nid); | ||
16778 | return (pincap & AC_PINCAP_IN) != 0; | ||
16779 | } | ||
16780 | |||
16394 | /* create playback/capture controls for input pins */ | 16781 | /* create playback/capture controls for input pins */ |
16395 | static int alc662_auto_create_analog_input_ctls(struct alc_spec *spec, | 16782 | static int alc662_auto_create_analog_input_ctls(struct hda_codec *codec, |
16396 | const struct auto_pin_cfg *cfg) | 16783 | const struct auto_pin_cfg *cfg) |
16397 | { | 16784 | { |
16398 | struct hda_input_mux *imux = &spec->private_imux; | 16785 | struct alc_spec *spec = codec->spec; |
16786 | struct hda_input_mux *imux = &spec->private_imux[0]; | ||
16399 | int i, err, idx; | 16787 | int i, err, idx; |
16400 | 16788 | ||
16401 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 16789 | for (i = 0; i < AUTO_PIN_LAST; i++) { |
16402 | if (alc880_is_input_pin(cfg->input_pins[i])) { | 16790 | if (alc662_is_input_pin(codec, cfg->input_pins[i])) { |
16403 | idx = alc880_input_pin_idx(cfg->input_pins[i]); | 16791 | idx = alc662_input_pin_idx(codec, 0x0b, |
16404 | err = new_analog_input(spec, cfg->input_pins[i], | 16792 | cfg->input_pins[i]); |
16405 | auto_pin_cfg_labels[i], | 16793 | if (idx >= 0) { |
16406 | idx, 0x0b); | 16794 | err = new_analog_input(spec, cfg->input_pins[i], |
16407 | if (err < 0) | 16795 | auto_pin_cfg_labels[i], |
16408 | return err; | 16796 | idx, 0x0b); |
16409 | imux->items[imux->num_items].label = | 16797 | if (err < 0) |
16410 | auto_pin_cfg_labels[i]; | 16798 | return err; |
16411 | imux->items[imux->num_items].index = | 16799 | } |
16412 | alc880_input_pin_idx(cfg->input_pins[i]); | 16800 | idx = alc662_input_pin_idx(codec, 0x22, |
16413 | imux->num_items++; | 16801 | cfg->input_pins[i]); |
16802 | if (idx >= 0) { | ||
16803 | imux->items[imux->num_items].label = | ||
16804 | auto_pin_cfg_labels[i]; | ||
16805 | imux->items[imux->num_items].index = idx; | ||
16806 | imux->num_items++; | ||
16807 | } | ||
16414 | } | 16808 | } |
16415 | } | 16809 | } |
16416 | return 0; | 16810 | return 0; |
@@ -16460,7 +16854,6 @@ static void alc662_auto_init_hp_out(struct hda_codec *codec) | |||
16460 | alc662_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); | 16854 | alc662_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); |
16461 | } | 16855 | } |
16462 | 16856 | ||
16463 | #define alc662_is_input_pin(nid) alc880_is_input_pin(nid) | ||
16464 | #define ALC662_PIN_CD_NID ALC880_PIN_CD_NID | 16857 | #define ALC662_PIN_CD_NID ALC880_PIN_CD_NID |
16465 | 16858 | ||
16466 | static void alc662_auto_init_analog_input(struct hda_codec *codec) | 16859 | static void alc662_auto_init_analog_input(struct hda_codec *codec) |
@@ -16470,12 +16863,10 @@ static void alc662_auto_init_analog_input(struct hda_codec *codec) | |||
16470 | 16863 | ||
16471 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 16864 | for (i = 0; i < AUTO_PIN_LAST; i++) { |
16472 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 16865 | hda_nid_t nid = spec->autocfg.input_pins[i]; |
16473 | if (alc662_is_input_pin(nid)) { | 16866 | if (alc662_is_input_pin(codec, nid)) { |
16474 | snd_hda_codec_write(codec, nid, 0, | 16867 | alc_set_input_pin(codec, nid, i); |
16475 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 16868 | if (nid != ALC662_PIN_CD_NID && |
16476 | (i <= AUTO_PIN_FRONT_MIC ? | 16869 | (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) |
16477 | PIN_VREF80 : PIN_IN)); | ||
16478 | if (nid != ALC662_PIN_CD_NID) | ||
16479 | snd_hda_codec_write(codec, nid, 0, | 16870 | snd_hda_codec_write(codec, nid, 0, |
16480 | AC_VERB_SET_AMP_GAIN_MUTE, | 16871 | AC_VERB_SET_AMP_GAIN_MUTE, |
16481 | AMP_OUT_MUTE); | 16872 | AMP_OUT_MUTE); |
@@ -16513,20 +16904,20 @@ static int alc662_parse_auto_config(struct hda_codec *codec) | |||
16513 | "Headphone"); | 16904 | "Headphone"); |
16514 | if (err < 0) | 16905 | if (err < 0) |
16515 | return err; | 16906 | return err; |
16516 | err = alc662_auto_create_analog_input_ctls(spec, &spec->autocfg); | 16907 | err = alc662_auto_create_analog_input_ctls(codec, &spec->autocfg); |
16517 | if (err < 0) | 16908 | if (err < 0) |
16518 | return err; | 16909 | return err; |
16519 | 16910 | ||
16520 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 16911 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
16521 | 16912 | ||
16522 | if (spec->autocfg.dig_out_pin) | 16913 | if (spec->autocfg.dig_outs) |
16523 | spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; | 16914 | spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; |
16524 | 16915 | ||
16525 | if (spec->kctls.list) | 16916 | if (spec->kctls.list) |
16526 | add_mixer(spec, spec->kctls.list); | 16917 | add_mixer(spec, spec->kctls.list); |
16527 | 16918 | ||
16528 | spec->num_mux_defs = 1; | 16919 | spec->num_mux_defs = 1; |
16529 | spec->input_mux = &spec->private_imux; | 16920 | spec->input_mux = &spec->private_imux[0]; |
16530 | 16921 | ||
16531 | add_verb(spec, alc662_auto_init_verbs); | 16922 | add_verb(spec, alc662_auto_init_verbs); |
16532 | if (codec->vendor_id == 0x10ec0663) | 16923 | if (codec->vendor_id == 0x10ec0663) |
@@ -16536,7 +16927,6 @@ static int alc662_parse_auto_config(struct hda_codec *codec) | |||
16536 | if (err < 0) | 16927 | if (err < 0) |
16537 | return err; | 16928 | return err; |
16538 | 16929 | ||
16539 | store_pin_configs(codec); | ||
16540 | return 1; | 16930 | return 1; |
16541 | } | 16931 | } |
16542 | 16932 | ||
@@ -16588,6 +16978,12 @@ static int patch_alc662(struct hda_codec *codec) | |||
16588 | } | 16978 | } |
16589 | } | 16979 | } |
16590 | 16980 | ||
16981 | err = snd_hda_attach_beep_device(codec, 0x1); | ||
16982 | if (err < 0) { | ||
16983 | alc_free(codec); | ||
16984 | return err; | ||
16985 | } | ||
16986 | |||
16591 | if (board_config != ALC662_AUTO) | 16987 | if (board_config != ALC662_AUTO) |
16592 | setup_preset(spec, &alc662_presets[board_config]); | 16988 | setup_preset(spec, &alc662_presets[board_config]); |
16593 | 16989 | ||
@@ -16611,10 +17007,14 @@ static int patch_alc662(struct hda_codec *codec) | |||
16611 | spec->adc_nids = alc662_adc_nids; | 17007 | spec->adc_nids = alc662_adc_nids; |
16612 | spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids); | 17008 | spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids); |
16613 | spec->capsrc_nids = alc662_capsrc_nids; | 17009 | spec->capsrc_nids = alc662_capsrc_nids; |
16614 | spec->is_mix_capture = 1; | 17010 | spec->capture_style = CAPT_MIX; |
16615 | 17011 | ||
16616 | if (!spec->cap_mixer) | 17012 | if (!spec->cap_mixer) |
16617 | set_capture_mixer(spec); | 17013 | set_capture_mixer(spec); |
17014 | if (codec->vendor_id == 0x10ec0662) | ||
17015 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | ||
17016 | else | ||
17017 | set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); | ||
16618 | 17018 | ||
16619 | spec->vmaster_nid = 0x02; | 17019 | spec->vmaster_nid = 0x02; |
16620 | 17020 | ||
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 6094344fb223..b5e108aa8f63 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -43,6 +43,7 @@ enum { | |||
43 | }; | 43 | }; |
44 | 44 | ||
45 | enum { | 45 | enum { |
46 | STAC_AUTO, | ||
46 | STAC_REF, | 47 | STAC_REF, |
47 | STAC_9200_OQO, | 48 | STAC_9200_OQO, |
48 | STAC_9200_DELL_D21, | 49 | STAC_9200_DELL_D21, |
@@ -62,14 +63,17 @@ enum { | |||
62 | }; | 63 | }; |
63 | 64 | ||
64 | enum { | 65 | enum { |
66 | STAC_9205_AUTO, | ||
65 | STAC_9205_REF, | 67 | STAC_9205_REF, |
66 | STAC_9205_DELL_M42, | 68 | STAC_9205_DELL_M42, |
67 | STAC_9205_DELL_M43, | 69 | STAC_9205_DELL_M43, |
68 | STAC_9205_DELL_M44, | 70 | STAC_9205_DELL_M44, |
71 | STAC_9205_EAPD, | ||
69 | STAC_9205_MODELS | 72 | STAC_9205_MODELS |
70 | }; | 73 | }; |
71 | 74 | ||
72 | enum { | 75 | enum { |
76 | STAC_92HD73XX_AUTO, | ||
73 | STAC_92HD73XX_NO_JD, /* no jack-detection */ | 77 | STAC_92HD73XX_NO_JD, /* no jack-detection */ |
74 | STAC_92HD73XX_REF, | 78 | STAC_92HD73XX_REF, |
75 | STAC_DELL_M6_AMIC, | 79 | STAC_DELL_M6_AMIC, |
@@ -80,22 +84,27 @@ enum { | |||
80 | }; | 84 | }; |
81 | 85 | ||
82 | enum { | 86 | enum { |
87 | STAC_92HD83XXX_AUTO, | ||
83 | STAC_92HD83XXX_REF, | 88 | STAC_92HD83XXX_REF, |
84 | STAC_92HD83XXX_PWR_REF, | 89 | STAC_92HD83XXX_PWR_REF, |
90 | STAC_DELL_S14, | ||
85 | STAC_92HD83XXX_MODELS | 91 | STAC_92HD83XXX_MODELS |
86 | }; | 92 | }; |
87 | 93 | ||
88 | enum { | 94 | enum { |
95 | STAC_92HD71BXX_AUTO, | ||
89 | STAC_92HD71BXX_REF, | 96 | STAC_92HD71BXX_REF, |
90 | STAC_DELL_M4_1, | 97 | STAC_DELL_M4_1, |
91 | STAC_DELL_M4_2, | 98 | STAC_DELL_M4_2, |
92 | STAC_DELL_M4_3, | 99 | STAC_DELL_M4_3, |
93 | STAC_HP_M4, | 100 | STAC_HP_M4, |
94 | STAC_HP_DV5, | 101 | STAC_HP_DV5, |
102 | STAC_HP_HDX, | ||
95 | STAC_92HD71BXX_MODELS | 103 | STAC_92HD71BXX_MODELS |
96 | }; | 104 | }; |
97 | 105 | ||
98 | enum { | 106 | enum { |
107 | STAC_925x_AUTO, | ||
99 | STAC_925x_REF, | 108 | STAC_925x_REF, |
100 | STAC_M1, | 109 | STAC_M1, |
101 | STAC_M1_2, | 110 | STAC_M1_2, |
@@ -108,6 +117,7 @@ enum { | |||
108 | }; | 117 | }; |
109 | 118 | ||
110 | enum { | 119 | enum { |
120 | STAC_922X_AUTO, | ||
111 | STAC_D945_REF, | 121 | STAC_D945_REF, |
112 | STAC_D945GTP3, | 122 | STAC_D945GTP3, |
113 | STAC_D945GTP5, | 123 | STAC_D945GTP5, |
@@ -135,6 +145,7 @@ enum { | |||
135 | }; | 145 | }; |
136 | 146 | ||
137 | enum { | 147 | enum { |
148 | STAC_927X_AUTO, | ||
138 | STAC_D965_REF_NO_JD, /* no jack-detection */ | 149 | STAC_D965_REF_NO_JD, /* no jack-detection */ |
139 | STAC_D965_REF, | 150 | STAC_D965_REF, |
140 | STAC_D965_3ST, | 151 | STAC_D965_3ST, |
@@ -144,6 +155,12 @@ enum { | |||
144 | STAC_927X_MODELS | 155 | STAC_927X_MODELS |
145 | }; | 156 | }; |
146 | 157 | ||
158 | enum { | ||
159 | STAC_9872_AUTO, | ||
160 | STAC_9872_VAIO, | ||
161 | STAC_9872_MODELS | ||
162 | }; | ||
163 | |||
147 | struct sigmatel_event { | 164 | struct sigmatel_event { |
148 | hda_nid_t nid; | 165 | hda_nid_t nid; |
149 | unsigned char type; | 166 | unsigned char type; |
@@ -167,6 +184,7 @@ struct sigmatel_spec { | |||
167 | unsigned int alt_switch: 1; | 184 | unsigned int alt_switch: 1; |
168 | unsigned int hp_detect: 1; | 185 | unsigned int hp_detect: 1; |
169 | unsigned int spdif_mute: 1; | 186 | unsigned int spdif_mute: 1; |
187 | unsigned int check_volume_offset:1; | ||
170 | 188 | ||
171 | /* gpio lines */ | 189 | /* gpio lines */ |
172 | unsigned int eapd_mask; | 190 | unsigned int eapd_mask; |
@@ -179,6 +197,7 @@ struct sigmatel_spec { | |||
179 | unsigned int stream_delay; | 197 | unsigned int stream_delay; |
180 | 198 | ||
181 | /* analog loopback */ | 199 | /* analog loopback */ |
200 | struct snd_kcontrol_new *aloopback_ctl; | ||
182 | unsigned char aloopback_mask; | 201 | unsigned char aloopback_mask; |
183 | unsigned char aloopback_shift; | 202 | unsigned char aloopback_shift; |
184 | 203 | ||
@@ -203,6 +222,8 @@ struct sigmatel_spec { | |||
203 | hda_nid_t hp_dacs[5]; | 222 | hda_nid_t hp_dacs[5]; |
204 | hda_nid_t speaker_dacs[5]; | 223 | hda_nid_t speaker_dacs[5]; |
205 | 224 | ||
225 | int volume_offset; | ||
226 | |||
206 | /* capture */ | 227 | /* capture */ |
207 | hda_nid_t *adc_nids; | 228 | hda_nid_t *adc_nids; |
208 | unsigned int num_adcs; | 229 | unsigned int num_adcs; |
@@ -224,7 +245,6 @@ struct sigmatel_spec { | |||
224 | /* pin widgets */ | 245 | /* pin widgets */ |
225 | hda_nid_t *pin_nids; | 246 | hda_nid_t *pin_nids; |
226 | unsigned int num_pins; | 247 | unsigned int num_pins; |
227 | unsigned int *pin_configs; | ||
228 | 248 | ||
229 | /* codec specific stuff */ | 249 | /* codec specific stuff */ |
230 | struct hda_verb *init; | 250 | struct hda_verb *init; |
@@ -400,6 +420,10 @@ static hda_nid_t stac922x_mux_nids[2] = { | |||
400 | 0x12, 0x13, | 420 | 0x12, 0x13, |
401 | }; | 421 | }; |
402 | 422 | ||
423 | static hda_nid_t stac927x_slave_dig_outs[2] = { | ||
424 | 0x1f, 0, | ||
425 | }; | ||
426 | |||
403 | static hda_nid_t stac927x_adc_nids[3] = { | 427 | static hda_nid_t stac927x_adc_nids[3] = { |
404 | 0x07, 0x08, 0x09 | 428 | 0x07, 0x08, 0x09 |
405 | }; | 429 | }; |
@@ -472,15 +496,21 @@ static hda_nid_t stac92hd73xx_pin_nids[13] = { | |||
472 | 0x14, 0x22, 0x23 | 496 | 0x14, 0x22, 0x23 |
473 | }; | 497 | }; |
474 | 498 | ||
475 | static hda_nid_t stac92hd83xxx_pin_nids[14] = { | 499 | static hda_nid_t stac92hd83xxx_pin_nids[10] = { |
476 | 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, | 500 | 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, |
477 | 0x0f, 0x10, 0x11, 0x12, 0x13, | 501 | 0x0f, 0x10, 0x11, 0x1f, 0x20, |
478 | 0x1d, 0x1e, 0x1f, 0x20 | 502 | }; |
503 | |||
504 | #define STAC92HD71BXX_NUM_PINS 13 | ||
505 | static hda_nid_t stac92hd71bxx_pin_nids_4port[STAC92HD71BXX_NUM_PINS] = { | ||
506 | 0x0a, 0x0b, 0x0c, 0x0d, 0x00, | ||
507 | 0x00, 0x14, 0x18, 0x19, 0x1e, | ||
508 | 0x1f, 0x20, 0x27 | ||
479 | }; | 509 | }; |
480 | static hda_nid_t stac92hd71bxx_pin_nids[11] = { | 510 | static hda_nid_t stac92hd71bxx_pin_nids_6port[STAC92HD71BXX_NUM_PINS] = { |
481 | 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, | 511 | 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, |
482 | 0x0f, 0x14, 0x18, 0x19, 0x1e, | 512 | 0x0f, 0x14, 0x18, 0x19, 0x1e, |
483 | 0x1f, | 513 | 0x1f, 0x20, 0x27 |
484 | }; | 514 | }; |
485 | 515 | ||
486 | static hda_nid_t stac927x_pin_nids[14] = { | 516 | static hda_nid_t stac927x_pin_nids[14] = { |
@@ -842,9 +872,9 @@ static struct hda_verb stac92hd73xx_10ch_core_init[] = { | |||
842 | }; | 872 | }; |
843 | 873 | ||
844 | static struct hda_verb stac92hd83xxx_core_init[] = { | 874 | static struct hda_verb stac92hd83xxx_core_init[] = { |
845 | { 0xa, AC_VERB_SET_CONNECT_SEL, 0x0}, | 875 | { 0xa, AC_VERB_SET_CONNECT_SEL, 0x1}, |
846 | { 0xb, AC_VERB_SET_CONNECT_SEL, 0x0}, | 876 | { 0xb, AC_VERB_SET_CONNECT_SEL, 0x1}, |
847 | { 0xd, AC_VERB_SET_CONNECT_SEL, 0x1}, | 877 | { 0xd, AC_VERB_SET_CONNECT_SEL, 0x0}, |
848 | 878 | ||
849 | /* power state controls amps */ | 879 | /* power state controls amps */ |
850 | { 0x01, AC_VERB_SET_EAPD, 1 << 2}, | 880 | { 0x01, AC_VERB_SET_EAPD, 1 << 2}, |
@@ -854,26 +884,25 @@ static struct hda_verb stac92hd83xxx_core_init[] = { | |||
854 | static struct hda_verb stac92hd71bxx_core_init[] = { | 884 | static struct hda_verb stac92hd71bxx_core_init[] = { |
855 | /* set master volume and direct control */ | 885 | /* set master volume and direct control */ |
856 | { 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | 886 | { 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, |
857 | /* unmute right and left channels for nodes 0x0a, 0xd, 0x0f */ | ||
858 | { 0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
859 | { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
860 | { 0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
861 | {} | 887 | {} |
862 | }; | 888 | }; |
863 | 889 | ||
864 | #define HD_DISABLE_PORTF 2 | 890 | #define HD_DISABLE_PORTF 1 |
865 | static struct hda_verb stac92hd71bxx_analog_core_init[] = { | 891 | static struct hda_verb stac92hd71bxx_analog_core_init[] = { |
866 | /* start of config #1 */ | 892 | /* start of config #1 */ |
867 | 893 | ||
868 | /* connect port 0f to audio mixer */ | 894 | /* connect port 0f to audio mixer */ |
869 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2}, | 895 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2}, |
870 | /* unmute right and left channels for node 0x0f */ | ||
871 | { 0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
872 | /* start of config #2 */ | 896 | /* start of config #2 */ |
873 | 897 | ||
874 | /* set master volume and direct control */ | 898 | /* set master volume and direct control */ |
875 | { 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | 899 | { 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, |
876 | /* unmute right and left channels for nodes 0x0a, 0xd */ | 900 | {} |
901 | }; | ||
902 | |||
903 | static struct hda_verb stac92hd71bxx_unmute_core_init[] = { | ||
904 | /* unmute right and left channels for nodes 0x0f, 0xa, 0x0d */ | ||
905 | { 0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
877 | { 0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 906 | { 0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
878 | { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 907 | { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
879 | {} | 908 | {} |
@@ -954,16 +983,6 @@ static struct hda_verb stac9205_core_init[] = { | |||
954 | .private_value = HDA_COMPOSE_AMP_VAL(nid, chs, idx, dir) \ | 983 | .private_value = HDA_COMPOSE_AMP_VAL(nid, chs, idx, dir) \ |
955 | } | 984 | } |
956 | 985 | ||
957 | #define STAC_INPUT_SOURCE(cnt) \ | ||
958 | { \ | ||
959 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
960 | .name = "Input Source", \ | ||
961 | .count = cnt, \ | ||
962 | .info = stac92xx_mux_enum_info, \ | ||
963 | .get = stac92xx_mux_enum_get, \ | ||
964 | .put = stac92xx_mux_enum_put, \ | ||
965 | } | ||
966 | |||
967 | #define STAC_ANALOG_LOOPBACK(verb_read, verb_write, cnt) \ | 986 | #define STAC_ANALOG_LOOPBACK(verb_read, verb_write, cnt) \ |
968 | { \ | 987 | { \ |
969 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 988 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
@@ -978,7 +997,6 @@ static struct hda_verb stac9205_core_init[] = { | |||
978 | static struct snd_kcontrol_new stac9200_mixer[] = { | 997 | static struct snd_kcontrol_new stac9200_mixer[] = { |
979 | HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT), | 998 | HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT), |
980 | HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT), | 999 | HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT), |
981 | STAC_INPUT_SOURCE(1), | ||
982 | HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT), | 1000 | HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT), |
983 | HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT), | 1001 | HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT), |
984 | { } /* end */ | 1002 | { } /* end */ |
@@ -1003,8 +1021,6 @@ static struct snd_kcontrol_new stac92hd73xx_6ch_mixer[] = { | |||
1003 | HDA_CODEC_VOLUME("DAC Mixer Capture Volume", 0x1d, 0x3, HDA_INPUT), | 1021 | HDA_CODEC_VOLUME("DAC Mixer Capture Volume", 0x1d, 0x3, HDA_INPUT), |
1004 | HDA_CODEC_MUTE("DAC Mixer Capture Switch", 0x1d, 0x3, HDA_INPUT), | 1022 | HDA_CODEC_MUTE("DAC Mixer Capture Switch", 0x1d, 0x3, HDA_INPUT), |
1005 | 1023 | ||
1006 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 3), | ||
1007 | |||
1008 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x20, 0x0, HDA_OUTPUT), | 1024 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x20, 0x0, HDA_OUTPUT), |
1009 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x20, 0x0, HDA_OUTPUT), | 1025 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x20, 0x0, HDA_OUTPUT), |
1010 | 1026 | ||
@@ -1014,9 +1030,22 @@ static struct snd_kcontrol_new stac92hd73xx_6ch_mixer[] = { | |||
1014 | { } /* end */ | 1030 | { } /* end */ |
1015 | }; | 1031 | }; |
1016 | 1032 | ||
1017 | static struct snd_kcontrol_new stac92hd73xx_8ch_mixer[] = { | 1033 | static struct snd_kcontrol_new stac92hd73xx_6ch_loopback[] = { |
1034 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 3), | ||
1035 | {} | ||
1036 | }; | ||
1037 | |||
1038 | static struct snd_kcontrol_new stac92hd73xx_8ch_loopback[] = { | ||
1018 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 4), | 1039 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 4), |
1040 | {} | ||
1041 | }; | ||
1019 | 1042 | ||
1043 | static struct snd_kcontrol_new stac92hd73xx_10ch_loopback[] = { | ||
1044 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 5), | ||
1045 | {} | ||
1046 | }; | ||
1047 | |||
1048 | static struct snd_kcontrol_new stac92hd73xx_8ch_mixer[] = { | ||
1020 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x20, 0x0, HDA_OUTPUT), | 1049 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x20, 0x0, HDA_OUTPUT), |
1021 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x20, 0x0, HDA_OUTPUT), | 1050 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x20, 0x0, HDA_OUTPUT), |
1022 | 1051 | ||
@@ -1041,8 +1070,6 @@ static struct snd_kcontrol_new stac92hd73xx_8ch_mixer[] = { | |||
1041 | }; | 1070 | }; |
1042 | 1071 | ||
1043 | static struct snd_kcontrol_new stac92hd73xx_10ch_mixer[] = { | 1072 | static struct snd_kcontrol_new stac92hd73xx_10ch_mixer[] = { |
1044 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 5), | ||
1045 | |||
1046 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x20, 0x0, HDA_OUTPUT), | 1073 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x20, 0x0, HDA_OUTPUT), |
1047 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x20, 0x0, HDA_OUTPUT), | 1074 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x20, 0x0, HDA_OUTPUT), |
1048 | 1075 | ||
@@ -1094,9 +1121,6 @@ static struct snd_kcontrol_new stac92hd83xxx_mixer[] = { | |||
1094 | }; | 1121 | }; |
1095 | 1122 | ||
1096 | static struct snd_kcontrol_new stac92hd71bxx_analog_mixer[] = { | 1123 | static struct snd_kcontrol_new stac92hd71bxx_analog_mixer[] = { |
1097 | STAC_INPUT_SOURCE(2), | ||
1098 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A0, 2), | ||
1099 | |||
1100 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1c, 0x0, HDA_OUTPUT), | 1124 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1c, 0x0, HDA_OUTPUT), |
1101 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1c, 0x0, HDA_OUTPUT), | 1125 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1c, 0x0, HDA_OUTPUT), |
1102 | 1126 | ||
@@ -1122,10 +1146,11 @@ static struct snd_kcontrol_new stac92hd71bxx_analog_mixer[] = { | |||
1122 | { } /* end */ | 1146 | { } /* end */ |
1123 | }; | 1147 | }; |
1124 | 1148 | ||
1125 | static struct snd_kcontrol_new stac92hd71bxx_mixer[] = { | 1149 | static struct snd_kcontrol_new stac92hd71bxx_loopback[] = { |
1126 | STAC_INPUT_SOURCE(2), | 1150 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A0, 2) |
1127 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A0, 2), | 1151 | }; |
1128 | 1152 | ||
1153 | static struct snd_kcontrol_new stac92hd71bxx_mixer[] = { | ||
1129 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1c, 0x0, HDA_OUTPUT), | 1154 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1c, 0x0, HDA_OUTPUT), |
1130 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1c, 0x0, HDA_OUTPUT), | 1155 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1c, 0x0, HDA_OUTPUT), |
1131 | 1156 | ||
@@ -1137,16 +1162,12 @@ static struct snd_kcontrol_new stac92hd71bxx_mixer[] = { | |||
1137 | static struct snd_kcontrol_new stac925x_mixer[] = { | 1162 | static struct snd_kcontrol_new stac925x_mixer[] = { |
1138 | HDA_CODEC_VOLUME("Master Playback Volume", 0x0e, 0, HDA_OUTPUT), | 1163 | HDA_CODEC_VOLUME("Master Playback Volume", 0x0e, 0, HDA_OUTPUT), |
1139 | HDA_CODEC_MUTE("Master Playback Switch", 0x0e, 0, HDA_OUTPUT), | 1164 | HDA_CODEC_MUTE("Master Playback Switch", 0x0e, 0, HDA_OUTPUT), |
1140 | STAC_INPUT_SOURCE(1), | ||
1141 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_OUTPUT), | 1165 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_OUTPUT), |
1142 | HDA_CODEC_MUTE("Capture Switch", 0x14, 0, HDA_OUTPUT), | 1166 | HDA_CODEC_MUTE("Capture Switch", 0x14, 0, HDA_OUTPUT), |
1143 | { } /* end */ | 1167 | { } /* end */ |
1144 | }; | 1168 | }; |
1145 | 1169 | ||
1146 | static struct snd_kcontrol_new stac9205_mixer[] = { | 1170 | static struct snd_kcontrol_new stac9205_mixer[] = { |
1147 | STAC_INPUT_SOURCE(2), | ||
1148 | STAC_ANALOG_LOOPBACK(0xFE0, 0x7E0, 1), | ||
1149 | |||
1150 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1b, 0x0, HDA_INPUT), | 1171 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1b, 0x0, HDA_INPUT), |
1151 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1d, 0x0, HDA_OUTPUT), | 1172 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1d, 0x0, HDA_OUTPUT), |
1152 | 1173 | ||
@@ -1155,9 +1176,13 @@ static struct snd_kcontrol_new stac9205_mixer[] = { | |||
1155 | { } /* end */ | 1176 | { } /* end */ |
1156 | }; | 1177 | }; |
1157 | 1178 | ||
1179 | static struct snd_kcontrol_new stac9205_loopback[] = { | ||
1180 | STAC_ANALOG_LOOPBACK(0xFE0, 0x7E0, 1), | ||
1181 | {} | ||
1182 | }; | ||
1183 | |||
1158 | /* This needs to be generated dynamically based on sequence */ | 1184 | /* This needs to be generated dynamically based on sequence */ |
1159 | static struct snd_kcontrol_new stac922x_mixer[] = { | 1185 | static struct snd_kcontrol_new stac922x_mixer[] = { |
1160 | STAC_INPUT_SOURCE(2), | ||
1161 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x17, 0x0, HDA_INPUT), | 1186 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x17, 0x0, HDA_INPUT), |
1162 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x17, 0x0, HDA_INPUT), | 1187 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x17, 0x0, HDA_INPUT), |
1163 | 1188 | ||
@@ -1168,9 +1193,6 @@ static struct snd_kcontrol_new stac922x_mixer[] = { | |||
1168 | 1193 | ||
1169 | 1194 | ||
1170 | static struct snd_kcontrol_new stac927x_mixer[] = { | 1195 | static struct snd_kcontrol_new stac927x_mixer[] = { |
1171 | STAC_INPUT_SOURCE(3), | ||
1172 | STAC_ANALOG_LOOPBACK(0xFEB, 0x7EB, 1), | ||
1173 | |||
1174 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x18, 0x0, HDA_INPUT), | 1196 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x18, 0x0, HDA_INPUT), |
1175 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1b, 0x0, HDA_OUTPUT), | 1197 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1b, 0x0, HDA_OUTPUT), |
1176 | 1198 | ||
@@ -1182,6 +1204,11 @@ static struct snd_kcontrol_new stac927x_mixer[] = { | |||
1182 | { } /* end */ | 1204 | { } /* end */ |
1183 | }; | 1205 | }; |
1184 | 1206 | ||
1207 | static struct snd_kcontrol_new stac927x_loopback[] = { | ||
1208 | STAC_ANALOG_LOOPBACK(0xFEB, 0x7EB, 1), | ||
1209 | {} | ||
1210 | }; | ||
1211 | |||
1185 | static struct snd_kcontrol_new stac_dmux_mixer = { | 1212 | static struct snd_kcontrol_new stac_dmux_mixer = { |
1186 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1213 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1187 | .name = "Digital Input Source", | 1214 | .name = "Digital Input Source", |
@@ -1207,10 +1234,7 @@ static const char *slave_vols[] = { | |||
1207 | "LFE Playback Volume", | 1234 | "LFE Playback Volume", |
1208 | "Side Playback Volume", | 1235 | "Side Playback Volume", |
1209 | "Headphone Playback Volume", | 1236 | "Headphone Playback Volume", |
1210 | "Headphone2 Playback Volume", | ||
1211 | "Speaker Playback Volume", | 1237 | "Speaker Playback Volume", |
1212 | "External Speaker Playback Volume", | ||
1213 | "Speaker2 Playback Volume", | ||
1214 | NULL | 1238 | NULL |
1215 | }; | 1239 | }; |
1216 | 1240 | ||
@@ -1221,10 +1245,7 @@ static const char *slave_sws[] = { | |||
1221 | "LFE Playback Switch", | 1245 | "LFE Playback Switch", |
1222 | "Side Playback Switch", | 1246 | "Side Playback Switch", |
1223 | "Headphone Playback Switch", | 1247 | "Headphone Playback Switch", |
1224 | "Headphone2 Playback Switch", | ||
1225 | "Speaker Playback Switch", | 1248 | "Speaker Playback Switch", |
1226 | "External Speaker Playback Switch", | ||
1227 | "Speaker2 Playback Switch", | ||
1228 | "IEC958 Playback Switch", | 1249 | "IEC958 Playback Switch", |
1229 | NULL | 1250 | NULL |
1230 | }; | 1251 | }; |
@@ -1294,6 +1315,8 @@ static int stac92xx_build_controls(struct hda_codec *codec) | |||
1294 | unsigned int vmaster_tlv[4]; | 1315 | unsigned int vmaster_tlv[4]; |
1295 | snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0], | 1316 | snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0], |
1296 | HDA_OUTPUT, vmaster_tlv); | 1317 | HDA_OUTPUT, vmaster_tlv); |
1318 | /* correct volume offset */ | ||
1319 | vmaster_tlv[2] += vmaster_tlv[3] * spec->volume_offset; | ||
1297 | err = snd_hda_add_vmaster(codec, "Master Playback Volume", | 1320 | err = snd_hda_add_vmaster(codec, "Master Playback Volume", |
1298 | vmaster_tlv, slave_vols); | 1321 | vmaster_tlv, slave_vols); |
1299 | if (err < 0) | 1322 | if (err < 0) |
@@ -1306,6 +1329,13 @@ static int stac92xx_build_controls(struct hda_codec *codec) | |||
1306 | return err; | 1329 | return err; |
1307 | } | 1330 | } |
1308 | 1331 | ||
1332 | if (spec->aloopback_ctl && | ||
1333 | snd_hda_get_bool_hint(codec, "loopback") == 1) { | ||
1334 | err = snd_hda_add_new_ctls(codec, spec->aloopback_ctl); | ||
1335 | if (err < 0) | ||
1336 | return err; | ||
1337 | } | ||
1338 | |||
1309 | stac92xx_free_kctls(codec); /* no longer needed */ | 1339 | stac92xx_free_kctls(codec); /* no longer needed */ |
1310 | 1340 | ||
1311 | /* create jack input elements */ | 1341 | /* create jack input elements */ |
@@ -1490,6 +1520,7 @@ static unsigned int *stac9200_brd_tbl[STAC_9200_MODELS] = { | |||
1490 | }; | 1520 | }; |
1491 | 1521 | ||
1492 | static const char *stac9200_models[STAC_9200_MODELS] = { | 1522 | static const char *stac9200_models[STAC_9200_MODELS] = { |
1523 | [STAC_AUTO] = "auto", | ||
1493 | [STAC_REF] = "ref", | 1524 | [STAC_REF] = "ref", |
1494 | [STAC_9200_OQO] = "oqo", | 1525 | [STAC_9200_OQO] = "oqo", |
1495 | [STAC_9200_DELL_D21] = "dell-d21", | 1526 | [STAC_9200_DELL_D21] = "dell-d21", |
@@ -1511,6 +1542,8 @@ static struct snd_pci_quirk stac9200_cfg_tbl[] = { | |||
1511 | /* SigmaTel reference board */ | 1542 | /* SigmaTel reference board */ |
1512 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, | 1543 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, |
1513 | "DFI LanParty", STAC_REF), | 1544 | "DFI LanParty", STAC_REF), |
1545 | SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, | ||
1546 | "DFI LanParty", STAC_REF), | ||
1514 | /* Dell laptops have BIOS problem */ | 1547 | /* Dell laptops have BIOS problem */ |
1515 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01a8, | 1548 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01a8, |
1516 | "unknown Dell", STAC_9200_DELL_D21), | 1549 | "unknown Dell", STAC_9200_DELL_D21), |
@@ -1633,6 +1666,7 @@ static unsigned int *stac925x_brd_tbl[STAC_925x_MODELS] = { | |||
1633 | }; | 1666 | }; |
1634 | 1667 | ||
1635 | static const char *stac925x_models[STAC_925x_MODELS] = { | 1668 | static const char *stac925x_models[STAC_925x_MODELS] = { |
1669 | [STAC_925x_AUTO] = "auto", | ||
1636 | [STAC_REF] = "ref", | 1670 | [STAC_REF] = "ref", |
1637 | [STAC_M1] = "m1", | 1671 | [STAC_M1] = "m1", |
1638 | [STAC_M1_2] = "m1-2", | 1672 | [STAC_M1_2] = "m1-2", |
@@ -1660,6 +1694,7 @@ static struct snd_pci_quirk stac925x_codec_id_cfg_tbl[] = { | |||
1660 | static struct snd_pci_quirk stac925x_cfg_tbl[] = { | 1694 | static struct snd_pci_quirk stac925x_cfg_tbl[] = { |
1661 | /* SigmaTel reference board */ | 1695 | /* SigmaTel reference board */ |
1662 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, "DFI LanParty", STAC_REF), | 1696 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, "DFI LanParty", STAC_REF), |
1697 | SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, "DFI LanParty", STAC_REF), | ||
1663 | SND_PCI_QUIRK(0x8384, 0x7632, "Stac9202 Reference Board", STAC_REF), | 1698 | SND_PCI_QUIRK(0x8384, 0x7632, "Stac9202 Reference Board", STAC_REF), |
1664 | 1699 | ||
1665 | /* Default table for unknown ID */ | 1700 | /* Default table for unknown ID */ |
@@ -1691,6 +1726,7 @@ static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = { | |||
1691 | }; | 1726 | }; |
1692 | 1727 | ||
1693 | static const char *stac92hd73xx_models[STAC_92HD73XX_MODELS] = { | 1728 | static const char *stac92hd73xx_models[STAC_92HD73XX_MODELS] = { |
1729 | [STAC_92HD73XX_AUTO] = "auto", | ||
1694 | [STAC_92HD73XX_NO_JD] = "no-jd", | 1730 | [STAC_92HD73XX_NO_JD] = "no-jd", |
1695 | [STAC_92HD73XX_REF] = "ref", | 1731 | [STAC_92HD73XX_REF] = "ref", |
1696 | [STAC_DELL_M6_AMIC] = "dell-m6-amic", | 1732 | [STAC_DELL_M6_AMIC] = "dell-m6-amic", |
@@ -1703,6 +1739,8 @@ static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = { | |||
1703 | /* SigmaTel reference board */ | 1739 | /* SigmaTel reference board */ |
1704 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, | 1740 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, |
1705 | "DFI LanParty", STAC_92HD73XX_REF), | 1741 | "DFI LanParty", STAC_92HD73XX_REF), |
1742 | SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, | ||
1743 | "DFI LanParty", STAC_92HD73XX_REF), | ||
1706 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0254, | 1744 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0254, |
1707 | "Dell Studio 1535", STAC_DELL_M6_DMIC), | 1745 | "Dell Studio 1535", STAC_DELL_M6_DMIC), |
1708 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0255, | 1746 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0255, |
@@ -1726,52 +1764,68 @@ static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = { | |||
1726 | {} /* terminator */ | 1764 | {} /* terminator */ |
1727 | }; | 1765 | }; |
1728 | 1766 | ||
1729 | static unsigned int ref92hd83xxx_pin_configs[14] = { | 1767 | static unsigned int ref92hd83xxx_pin_configs[10] = { |
1730 | 0x02214030, 0x02211010, 0x02a19020, 0x02170130, | 1768 | 0x02214030, 0x02211010, 0x02a19020, 0x02170130, |
1731 | 0x01014050, 0x01819040, 0x01014020, 0x90a3014e, | 1769 | 0x01014050, 0x01819040, 0x01014020, 0x90a3014e, |
1732 | 0x40f000f0, 0x40f000f0, 0x40f000f0, 0x40f000f0, | ||
1733 | 0x01451160, 0x98560170, | 1770 | 0x01451160, 0x98560170, |
1734 | }; | 1771 | }; |
1735 | 1772 | ||
1773 | static unsigned int dell_s14_pin_configs[10] = { | ||
1774 | 0x02214030, 0x02211010, 0x02a19020, 0x01014050, | ||
1775 | 0x40f000f0, 0x01819040, 0x40f000f0, 0x90a60160, | ||
1776 | 0x40f000f0, 0x40f000f0, | ||
1777 | }; | ||
1778 | |||
1736 | static unsigned int *stac92hd83xxx_brd_tbl[STAC_92HD83XXX_MODELS] = { | 1779 | static unsigned int *stac92hd83xxx_brd_tbl[STAC_92HD83XXX_MODELS] = { |
1737 | [STAC_92HD83XXX_REF] = ref92hd83xxx_pin_configs, | 1780 | [STAC_92HD83XXX_REF] = ref92hd83xxx_pin_configs, |
1738 | [STAC_92HD83XXX_PWR_REF] = ref92hd83xxx_pin_configs, | 1781 | [STAC_92HD83XXX_PWR_REF] = ref92hd83xxx_pin_configs, |
1782 | [STAC_DELL_S14] = dell_s14_pin_configs, | ||
1739 | }; | 1783 | }; |
1740 | 1784 | ||
1741 | static const char *stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = { | 1785 | static const char *stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = { |
1786 | [STAC_92HD83XXX_AUTO] = "auto", | ||
1742 | [STAC_92HD83XXX_REF] = "ref", | 1787 | [STAC_92HD83XXX_REF] = "ref", |
1743 | [STAC_92HD83XXX_PWR_REF] = "mic-ref", | 1788 | [STAC_92HD83XXX_PWR_REF] = "mic-ref", |
1789 | [STAC_DELL_S14] = "dell-s14", | ||
1744 | }; | 1790 | }; |
1745 | 1791 | ||
1746 | static struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { | 1792 | static struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { |
1747 | /* SigmaTel reference board */ | 1793 | /* SigmaTel reference board */ |
1748 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, | 1794 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, |
1749 | "DFI LanParty", STAC_92HD83XXX_REF), | 1795 | "DFI LanParty", STAC_92HD83XXX_REF), |
1796 | SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, | ||
1797 | "DFI LanParty", STAC_92HD83XXX_REF), | ||
1798 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ba, | ||
1799 | "unknown Dell", STAC_DELL_S14), | ||
1750 | {} /* terminator */ | 1800 | {} /* terminator */ |
1751 | }; | 1801 | }; |
1752 | 1802 | ||
1753 | static unsigned int ref92hd71bxx_pin_configs[11] = { | 1803 | static unsigned int ref92hd71bxx_pin_configs[STAC92HD71BXX_NUM_PINS] = { |
1754 | 0x02214030, 0x02a19040, 0x01a19020, 0x01014010, | 1804 | 0x02214030, 0x02a19040, 0x01a19020, 0x01014010, |
1755 | 0x0181302e, 0x01014010, 0x01019020, 0x90a000f0, | 1805 | 0x0181302e, 0x01014010, 0x01019020, 0x90a000f0, |
1756 | 0x90a000f0, 0x01452050, 0x01452050, | 1806 | 0x90a000f0, 0x01452050, 0x01452050, 0x00000000, |
1807 | 0x00000000 | ||
1757 | }; | 1808 | }; |
1758 | 1809 | ||
1759 | static unsigned int dell_m4_1_pin_configs[11] = { | 1810 | static unsigned int dell_m4_1_pin_configs[STAC92HD71BXX_NUM_PINS] = { |
1760 | 0x0421101f, 0x04a11221, 0x40f000f0, 0x90170110, | 1811 | 0x0421101f, 0x04a11221, 0x40f000f0, 0x90170110, |
1761 | 0x23a1902e, 0x23014250, 0x40f000f0, 0x90a000f0, | 1812 | 0x23a1902e, 0x23014250, 0x40f000f0, 0x90a000f0, |
1762 | 0x40f000f0, 0x4f0000f0, 0x4f0000f0, | 1813 | 0x40f000f0, 0x4f0000f0, 0x4f0000f0, 0x00000000, |
1814 | 0x00000000 | ||
1763 | }; | 1815 | }; |
1764 | 1816 | ||
1765 | static unsigned int dell_m4_2_pin_configs[11] = { | 1817 | static unsigned int dell_m4_2_pin_configs[STAC92HD71BXX_NUM_PINS] = { |
1766 | 0x0421101f, 0x04a11221, 0x90a70330, 0x90170110, | 1818 | 0x0421101f, 0x04a11221, 0x90a70330, 0x90170110, |
1767 | 0x23a1902e, 0x23014250, 0x40f000f0, 0x40f000f0, | 1819 | 0x23a1902e, 0x23014250, 0x40f000f0, 0x40f000f0, |
1768 | 0x40f000f0, 0x044413b0, 0x044413b0, | 1820 | 0x40f000f0, 0x044413b0, 0x044413b0, 0x00000000, |
1821 | 0x00000000 | ||
1769 | }; | 1822 | }; |
1770 | 1823 | ||
1771 | static unsigned int dell_m4_3_pin_configs[11] = { | 1824 | static unsigned int dell_m4_3_pin_configs[STAC92HD71BXX_NUM_PINS] = { |
1772 | 0x0421101f, 0x04a11221, 0x90a70330, 0x90170110, | 1825 | 0x0421101f, 0x04a11221, 0x90a70330, 0x90170110, |
1773 | 0x40f000f0, 0x40f000f0, 0x40f000f0, 0x90a000f0, | 1826 | 0x40f000f0, 0x40f000f0, 0x40f000f0, 0x90a000f0, |
1774 | 0x40f000f0, 0x044413b0, 0x044413b0, | 1827 | 0x40f000f0, 0x044413b0, 0x044413b0, 0x00000000, |
1828 | 0x00000000 | ||
1775 | }; | 1829 | }; |
1776 | 1830 | ||
1777 | static unsigned int *stac92hd71bxx_brd_tbl[STAC_92HD71BXX_MODELS] = { | 1831 | static unsigned int *stac92hd71bxx_brd_tbl[STAC_92HD71BXX_MODELS] = { |
@@ -1781,35 +1835,38 @@ static unsigned int *stac92hd71bxx_brd_tbl[STAC_92HD71BXX_MODELS] = { | |||
1781 | [STAC_DELL_M4_3] = dell_m4_3_pin_configs, | 1835 | [STAC_DELL_M4_3] = dell_m4_3_pin_configs, |
1782 | [STAC_HP_M4] = NULL, | 1836 | [STAC_HP_M4] = NULL, |
1783 | [STAC_HP_DV5] = NULL, | 1837 | [STAC_HP_DV5] = NULL, |
1838 | [STAC_HP_HDX] = NULL, | ||
1784 | }; | 1839 | }; |
1785 | 1840 | ||
1786 | static const char *stac92hd71bxx_models[STAC_92HD71BXX_MODELS] = { | 1841 | static const char *stac92hd71bxx_models[STAC_92HD71BXX_MODELS] = { |
1842 | [STAC_92HD71BXX_AUTO] = "auto", | ||
1787 | [STAC_92HD71BXX_REF] = "ref", | 1843 | [STAC_92HD71BXX_REF] = "ref", |
1788 | [STAC_DELL_M4_1] = "dell-m4-1", | 1844 | [STAC_DELL_M4_1] = "dell-m4-1", |
1789 | [STAC_DELL_M4_2] = "dell-m4-2", | 1845 | [STAC_DELL_M4_2] = "dell-m4-2", |
1790 | [STAC_DELL_M4_3] = "dell-m4-3", | 1846 | [STAC_DELL_M4_3] = "dell-m4-3", |
1791 | [STAC_HP_M4] = "hp-m4", | 1847 | [STAC_HP_M4] = "hp-m4", |
1792 | [STAC_HP_DV5] = "hp-dv5", | 1848 | [STAC_HP_DV5] = "hp-dv5", |
1849 | [STAC_HP_HDX] = "hp-hdx", | ||
1793 | }; | 1850 | }; |
1794 | 1851 | ||
1795 | static struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = { | 1852 | static struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = { |
1796 | /* SigmaTel reference board */ | 1853 | /* SigmaTel reference board */ |
1797 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, | 1854 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, |
1798 | "DFI LanParty", STAC_92HD71BXX_REF), | 1855 | "DFI LanParty", STAC_92HD71BXX_REF), |
1799 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30f2, | 1856 | SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, |
1800 | "HP dv5", STAC_HP_M4), | 1857 | "DFI LanParty", STAC_92HD71BXX_REF), |
1801 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30f4, | 1858 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3080, |
1802 | "HP dv7", STAC_HP_DV5), | 1859 | "HP", STAC_HP_DV5), |
1803 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30f7, | 1860 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x30f0, |
1804 | "HP dv4", STAC_HP_DV5), | 1861 | "HP dv4-7", STAC_HP_DV5), |
1805 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30fc, | 1862 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3600, |
1806 | "HP dv7", STAC_HP_M4), | 1863 | "HP dv4-7", STAC_HP_DV5), |
1807 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3600, | 1864 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3610, |
1808 | "HP dv5", STAC_HP_DV5), | 1865 | "HP HDX", STAC_HP_HDX), /* HDX18 */ |
1809 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3603, | ||
1810 | "HP dv5", STAC_HP_DV5), | ||
1811 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x361a, | 1866 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x361a, |
1812 | "unknown HP", STAC_HP_M4), | 1867 | "HP mini 1000", STAC_HP_M4), |
1868 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x361b, | ||
1869 | "HP HDX", STAC_HP_HDX), /* HDX16 */ | ||
1813 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0233, | 1870 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0233, |
1814 | "unknown Dell", STAC_DELL_M4_1), | 1871 | "unknown Dell", STAC_DELL_M4_1), |
1815 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0234, | 1872 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0234, |
@@ -1961,6 +2018,7 @@ static unsigned int *stac922x_brd_tbl[STAC_922X_MODELS] = { | |||
1961 | }; | 2018 | }; |
1962 | 2019 | ||
1963 | static const char *stac922x_models[STAC_922X_MODELS] = { | 2020 | static const char *stac922x_models[STAC_922X_MODELS] = { |
2021 | [STAC_922X_AUTO] = "auto", | ||
1964 | [STAC_D945_REF] = "ref", | 2022 | [STAC_D945_REF] = "ref", |
1965 | [STAC_D945GTP5] = "5stack", | 2023 | [STAC_D945GTP5] = "5stack", |
1966 | [STAC_D945GTP3] = "3stack", | 2024 | [STAC_D945GTP3] = "3stack", |
@@ -1988,6 +2046,8 @@ static struct snd_pci_quirk stac922x_cfg_tbl[] = { | |||
1988 | /* SigmaTel reference board */ | 2046 | /* SigmaTel reference board */ |
1989 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, | 2047 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, |
1990 | "DFI LanParty", STAC_D945_REF), | 2048 | "DFI LanParty", STAC_D945_REF), |
2049 | SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, | ||
2050 | "DFI LanParty", STAC_D945_REF), | ||
1991 | /* Intel 945G based systems */ | 2051 | /* Intel 945G based systems */ |
1992 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0101, | 2052 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0101, |
1993 | "Intel D945G", STAC_D945GTP3), | 2053 | "Intel D945G", STAC_D945GTP3), |
@@ -2041,6 +2101,9 @@ static struct snd_pci_quirk stac922x_cfg_tbl[] = { | |||
2041 | "Intel D945P", STAC_D945GTP3), | 2101 | "Intel D945P", STAC_D945GTP3), |
2042 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0707, | 2102 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0707, |
2043 | "Intel D945P", STAC_D945GTP5), | 2103 | "Intel D945P", STAC_D945GTP5), |
2104 | /* other intel */ | ||
2105 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0204, | ||
2106 | "Intel D945", STAC_D945_REF), | ||
2044 | /* other systems */ | 2107 | /* other systems */ |
2045 | /* Apple Intel Mac (Mac Mini, MacBook, MacBook Pro...) */ | 2108 | /* Apple Intel Mac (Mac Mini, MacBook, MacBook Pro...) */ |
2046 | SND_PCI_QUIRK(0x8384, 0x7680, | 2109 | SND_PCI_QUIRK(0x8384, 0x7680, |
@@ -2065,31 +2128,7 @@ static struct snd_pci_quirk stac922x_cfg_tbl[] = { | |||
2065 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d7, | 2128 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d7, |
2066 | "Dell XPS M1210", STAC_922X_DELL_M82), | 2129 | "Dell XPS M1210", STAC_922X_DELL_M82), |
2067 | /* ECS/PC Chips boards */ | 2130 | /* ECS/PC Chips boards */ |
2068 | SND_PCI_QUIRK(0x1019, 0x2144, | 2131 | SND_PCI_QUIRK_MASK(0x1019, 0xf000, 0x2000, |
2069 | "ECS/PC chips", STAC_ECS_202), | ||
2070 | SND_PCI_QUIRK(0x1019, 0x2608, | ||
2071 | "ECS/PC chips", STAC_ECS_202), | ||
2072 | SND_PCI_QUIRK(0x1019, 0x2633, | ||
2073 | "ECS/PC chips P17G/1333", STAC_ECS_202), | ||
2074 | SND_PCI_QUIRK(0x1019, 0x2811, | ||
2075 | "ECS/PC chips", STAC_ECS_202), | ||
2076 | SND_PCI_QUIRK(0x1019, 0x2812, | ||
2077 | "ECS/PC chips", STAC_ECS_202), | ||
2078 | SND_PCI_QUIRK(0x1019, 0x2813, | ||
2079 | "ECS/PC chips", STAC_ECS_202), | ||
2080 | SND_PCI_QUIRK(0x1019, 0x2814, | ||
2081 | "ECS/PC chips", STAC_ECS_202), | ||
2082 | SND_PCI_QUIRK(0x1019, 0x2815, | ||
2083 | "ECS/PC chips", STAC_ECS_202), | ||
2084 | SND_PCI_QUIRK(0x1019, 0x2816, | ||
2085 | "ECS/PC chips", STAC_ECS_202), | ||
2086 | SND_PCI_QUIRK(0x1019, 0x2817, | ||
2087 | "ECS/PC chips", STAC_ECS_202), | ||
2088 | SND_PCI_QUIRK(0x1019, 0x2818, | ||
2089 | "ECS/PC chips", STAC_ECS_202), | ||
2090 | SND_PCI_QUIRK(0x1019, 0x2819, | ||
2091 | "ECS/PC chips", STAC_ECS_202), | ||
2092 | SND_PCI_QUIRK(0x1019, 0x2820, | ||
2093 | "ECS/PC chips", STAC_ECS_202), | 2132 | "ECS/PC chips", STAC_ECS_202), |
2094 | {} /* terminator */ | 2133 | {} /* terminator */ |
2095 | }; | 2134 | }; |
@@ -2132,6 +2171,7 @@ static unsigned int *stac927x_brd_tbl[STAC_927X_MODELS] = { | |||
2132 | }; | 2171 | }; |
2133 | 2172 | ||
2134 | static const char *stac927x_models[STAC_927X_MODELS] = { | 2173 | static const char *stac927x_models[STAC_927X_MODELS] = { |
2174 | [STAC_927X_AUTO] = "auto", | ||
2135 | [STAC_D965_REF_NO_JD] = "ref-no-jd", | 2175 | [STAC_D965_REF_NO_JD] = "ref-no-jd", |
2136 | [STAC_D965_REF] = "ref", | 2176 | [STAC_D965_REF] = "ref", |
2137 | [STAC_D965_3ST] = "3stack", | 2177 | [STAC_D965_3ST] = "3stack", |
@@ -2144,26 +2184,16 @@ static struct snd_pci_quirk stac927x_cfg_tbl[] = { | |||
2144 | /* SigmaTel reference board */ | 2184 | /* SigmaTel reference board */ |
2145 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, | 2185 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, |
2146 | "DFI LanParty", STAC_D965_REF), | 2186 | "DFI LanParty", STAC_D965_REF), |
2187 | SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, | ||
2188 | "DFI LanParty", STAC_D965_REF), | ||
2147 | /* Intel 946 based systems */ | 2189 | /* Intel 946 based systems */ |
2148 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x3d01, "Intel D946", STAC_D965_3ST), | 2190 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x3d01, "Intel D946", STAC_D965_3ST), |
2149 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0xa301, "Intel D946", STAC_D965_3ST), | 2191 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0xa301, "Intel D946", STAC_D965_3ST), |
2150 | /* 965 based 3 stack systems */ | 2192 | /* 965 based 3 stack systems */ |
2151 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2116, "Intel D965", STAC_D965_3ST), | 2193 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2100, |
2152 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2115, "Intel D965", STAC_D965_3ST), | 2194 | "Intel D965", STAC_D965_3ST), |
2153 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2114, "Intel D965", STAC_D965_3ST), | 2195 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2000, |
2154 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2113, "Intel D965", STAC_D965_3ST), | 2196 | "Intel D965", STAC_D965_3ST), |
2155 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2112, "Intel D965", STAC_D965_3ST), | ||
2156 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2111, "Intel D965", STAC_D965_3ST), | ||
2157 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2110, "Intel D965", STAC_D965_3ST), | ||
2158 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2009, "Intel D965", STAC_D965_3ST), | ||
2159 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2008, "Intel D965", STAC_D965_3ST), | ||
2160 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2007, "Intel D965", STAC_D965_3ST), | ||
2161 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2006, "Intel D965", STAC_D965_3ST), | ||
2162 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2005, "Intel D965", STAC_D965_3ST), | ||
2163 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2004, "Intel D965", STAC_D965_3ST), | ||
2164 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2003, "Intel D965", STAC_D965_3ST), | ||
2165 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2002, "Intel D965", STAC_D965_3ST), | ||
2166 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2001, "Intel D965", STAC_D965_3ST), | ||
2167 | /* Dell 3 stack systems */ | 2197 | /* Dell 3 stack systems */ |
2168 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f7, "Dell XPS M1730", STAC_DELL_3ST), | 2198 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f7, "Dell XPS M1730", STAC_DELL_3ST), |
2169 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01dd, "Dell Dimension E520", STAC_DELL_3ST), | 2199 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01dd, "Dell Dimension E520", STAC_DELL_3ST), |
@@ -2179,15 +2209,10 @@ static struct snd_pci_quirk stac927x_cfg_tbl[] = { | |||
2179 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ff, "Dell ", STAC_DELL_BIOS), | 2209 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ff, "Dell ", STAC_DELL_BIOS), |
2180 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0209, "Dell XPS 1330", STAC_DELL_BIOS), | 2210 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0209, "Dell XPS 1330", STAC_DELL_BIOS), |
2181 | /* 965 based 5 stack systems */ | 2211 | /* 965 based 5 stack systems */ |
2182 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2301, "Intel D965", STAC_D965_5ST), | 2212 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2300, |
2183 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2302, "Intel D965", STAC_D965_5ST), | 2213 | "Intel D965", STAC_D965_5ST), |
2184 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2303, "Intel D965", STAC_D965_5ST), | 2214 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2500, |
2185 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2304, "Intel D965", STAC_D965_5ST), | 2215 | "Intel D965", STAC_D965_5ST), |
2186 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2305, "Intel D965", STAC_D965_5ST), | ||
2187 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2501, "Intel D965", STAC_D965_5ST), | ||
2188 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2502, "Intel D965", STAC_D965_5ST), | ||
2189 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2503, "Intel D965", STAC_D965_5ST), | ||
2190 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2504, "Intel D965", STAC_D965_5ST), | ||
2191 | {} /* terminator */ | 2216 | {} /* terminator */ |
2192 | }; | 2217 | }; |
2193 | 2218 | ||
@@ -2240,19 +2265,25 @@ static unsigned int *stac9205_brd_tbl[STAC_9205_MODELS] = { | |||
2240 | [STAC_9205_DELL_M42] = dell_9205_m42_pin_configs, | 2265 | [STAC_9205_DELL_M42] = dell_9205_m42_pin_configs, |
2241 | [STAC_9205_DELL_M43] = dell_9205_m43_pin_configs, | 2266 | [STAC_9205_DELL_M43] = dell_9205_m43_pin_configs, |
2242 | [STAC_9205_DELL_M44] = dell_9205_m44_pin_configs, | 2267 | [STAC_9205_DELL_M44] = dell_9205_m44_pin_configs, |
2268 | [STAC_9205_EAPD] = NULL, | ||
2243 | }; | 2269 | }; |
2244 | 2270 | ||
2245 | static const char *stac9205_models[STAC_9205_MODELS] = { | 2271 | static const char *stac9205_models[STAC_9205_MODELS] = { |
2272 | [STAC_9205_AUTO] = "auto", | ||
2246 | [STAC_9205_REF] = "ref", | 2273 | [STAC_9205_REF] = "ref", |
2247 | [STAC_9205_DELL_M42] = "dell-m42", | 2274 | [STAC_9205_DELL_M42] = "dell-m42", |
2248 | [STAC_9205_DELL_M43] = "dell-m43", | 2275 | [STAC_9205_DELL_M43] = "dell-m43", |
2249 | [STAC_9205_DELL_M44] = "dell-m44", | 2276 | [STAC_9205_DELL_M44] = "dell-m44", |
2277 | [STAC_9205_EAPD] = "eapd", | ||
2250 | }; | 2278 | }; |
2251 | 2279 | ||
2252 | static struct snd_pci_quirk stac9205_cfg_tbl[] = { | 2280 | static struct snd_pci_quirk stac9205_cfg_tbl[] = { |
2253 | /* SigmaTel reference board */ | 2281 | /* SigmaTel reference board */ |
2254 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, | 2282 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, |
2255 | "DFI LanParty", STAC_9205_REF), | 2283 | "DFI LanParty", STAC_9205_REF), |
2284 | SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, | ||
2285 | "DFI LanParty", STAC_9205_REF), | ||
2286 | /* Dell */ | ||
2256 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f1, | 2287 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f1, |
2257 | "unknown Dell", STAC_9205_DELL_M42), | 2288 | "unknown Dell", STAC_9205_DELL_M42), |
2258 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f2, | 2289 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f2, |
@@ -2283,101 +2314,24 @@ static struct snd_pci_quirk stac9205_cfg_tbl[] = { | |||
2283 | "Dell Inspiron", STAC_9205_DELL_M44), | 2314 | "Dell Inspiron", STAC_9205_DELL_M44), |
2284 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0228, | 2315 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0228, |
2285 | "Dell Vostro 1500", STAC_9205_DELL_M42), | 2316 | "Dell Vostro 1500", STAC_9205_DELL_M42), |
2317 | /* Gateway */ | ||
2318 | SND_PCI_QUIRK(0x107b, 0x0565, "Gateway T1616", STAC_9205_EAPD), | ||
2286 | {} /* terminator */ | 2319 | {} /* terminator */ |
2287 | }; | 2320 | }; |
2288 | 2321 | ||
2289 | static int stac92xx_save_bios_config_regs(struct hda_codec *codec) | 2322 | static void stac92xx_set_config_regs(struct hda_codec *codec, |
2323 | unsigned int *pincfgs) | ||
2290 | { | 2324 | { |
2291 | int i; | 2325 | int i; |
2292 | struct sigmatel_spec *spec = codec->spec; | 2326 | struct sigmatel_spec *spec = codec->spec; |
2293 | |||
2294 | kfree(spec->pin_configs); | ||
2295 | spec->pin_configs = kcalloc(spec->num_pins, sizeof(*spec->pin_configs), | ||
2296 | GFP_KERNEL); | ||
2297 | if (!spec->pin_configs) | ||
2298 | return -ENOMEM; | ||
2299 | |||
2300 | for (i = 0; i < spec->num_pins; i++) { | ||
2301 | hda_nid_t nid = spec->pin_nids[i]; | ||
2302 | unsigned int pin_cfg; | ||
2303 | |||
2304 | pin_cfg = snd_hda_codec_read(codec, nid, 0, | ||
2305 | AC_VERB_GET_CONFIG_DEFAULT, 0x00); | ||
2306 | snd_printdd(KERN_INFO "hda_codec: pin nid %2.2x bios pin config %8.8x\n", | ||
2307 | nid, pin_cfg); | ||
2308 | spec->pin_configs[i] = pin_cfg; | ||
2309 | } | ||
2310 | |||
2311 | return 0; | ||
2312 | } | ||
2313 | 2327 | ||
2314 | static void stac92xx_set_config_reg(struct hda_codec *codec, | 2328 | if (!pincfgs) |
2315 | hda_nid_t pin_nid, unsigned int pin_config) | 2329 | return; |
2316 | { | ||
2317 | int i; | ||
2318 | snd_hda_codec_write(codec, pin_nid, 0, | ||
2319 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_0, | ||
2320 | pin_config & 0x000000ff); | ||
2321 | snd_hda_codec_write(codec, pin_nid, 0, | ||
2322 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_1, | ||
2323 | (pin_config & 0x0000ff00) >> 8); | ||
2324 | snd_hda_codec_write(codec, pin_nid, 0, | ||
2325 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_2, | ||
2326 | (pin_config & 0x00ff0000) >> 16); | ||
2327 | snd_hda_codec_write(codec, pin_nid, 0, | ||
2328 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, | ||
2329 | pin_config >> 24); | ||
2330 | i = snd_hda_codec_read(codec, pin_nid, 0, | ||
2331 | AC_VERB_GET_CONFIG_DEFAULT, | ||
2332 | 0x00); | ||
2333 | snd_printdd(KERN_INFO "hda_codec: pin nid %2.2x pin config %8.8x\n", | ||
2334 | pin_nid, i); | ||
2335 | } | ||
2336 | |||
2337 | static void stac92xx_set_config_regs(struct hda_codec *codec) | ||
2338 | { | ||
2339 | int i; | ||
2340 | struct sigmatel_spec *spec = codec->spec; | ||
2341 | |||
2342 | if (!spec->pin_configs) | ||
2343 | return; | ||
2344 | 2330 | ||
2345 | for (i = 0; i < spec->num_pins; i++) | 2331 | for (i = 0; i < spec->num_pins; i++) |
2346 | stac92xx_set_config_reg(codec, spec->pin_nids[i], | 2332 | if (spec->pin_nids[i] && pincfgs[i]) |
2347 | spec->pin_configs[i]); | 2333 | snd_hda_codec_set_pincfg(codec, spec->pin_nids[i], |
2348 | } | 2334 | pincfgs[i]); |
2349 | |||
2350 | static int stac_save_pin_cfgs(struct hda_codec *codec, unsigned int *pins) | ||
2351 | { | ||
2352 | struct sigmatel_spec *spec = codec->spec; | ||
2353 | |||
2354 | if (!pins) | ||
2355 | return stac92xx_save_bios_config_regs(codec); | ||
2356 | |||
2357 | kfree(spec->pin_configs); | ||
2358 | spec->pin_configs = kmemdup(pins, | ||
2359 | spec->num_pins * sizeof(*pins), | ||
2360 | GFP_KERNEL); | ||
2361 | if (!spec->pin_configs) | ||
2362 | return -ENOMEM; | ||
2363 | |||
2364 | stac92xx_set_config_regs(codec); | ||
2365 | return 0; | ||
2366 | } | ||
2367 | |||
2368 | static void stac_change_pin_config(struct hda_codec *codec, hda_nid_t nid, | ||
2369 | unsigned int cfg) | ||
2370 | { | ||
2371 | struct sigmatel_spec *spec = codec->spec; | ||
2372 | int i; | ||
2373 | |||
2374 | for (i = 0; i < spec->num_pins; i++) { | ||
2375 | if (spec->pin_nids[i] == nid) { | ||
2376 | spec->pin_configs[i] = cfg; | ||
2377 | stac92xx_set_config_reg(codec, nid, cfg); | ||
2378 | break; | ||
2379 | } | ||
2380 | } | ||
2381 | } | 2335 | } |
2382 | 2336 | ||
2383 | /* | 2337 | /* |
@@ -2567,7 +2521,7 @@ static int stac92xx_build_pcms(struct hda_codec *codec) | |||
2567 | codec->num_pcms++; | 2521 | codec->num_pcms++; |
2568 | info++; | 2522 | info++; |
2569 | info->name = "STAC92xx Digital"; | 2523 | info->name = "STAC92xx Digital"; |
2570 | info->pcm_type = HDA_PCM_TYPE_SPDIF; | 2524 | info->pcm_type = spec->autocfg.dig_out_type[0]; |
2571 | if (spec->multiout.dig_out_nid) { | 2525 | if (spec->multiout.dig_out_nid) { |
2572 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_digital_playback; | 2526 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_digital_playback; |
2573 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid; | 2527 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid; |
@@ -2583,8 +2537,7 @@ static int stac92xx_build_pcms(struct hda_codec *codec) | |||
2583 | 2537 | ||
2584 | static unsigned int stac92xx_get_vref(struct hda_codec *codec, hda_nid_t nid) | 2538 | static unsigned int stac92xx_get_vref(struct hda_codec *codec, hda_nid_t nid) |
2585 | { | 2539 | { |
2586 | unsigned int pincap = snd_hda_param_read(codec, nid, | 2540 | unsigned int pincap = snd_hda_query_pin_caps(codec, nid); |
2587 | AC_PAR_PIN_CAP); | ||
2588 | pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT; | 2541 | pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT; |
2589 | if (pincap & AC_PINCAP_VREF_100) | 2542 | if (pincap & AC_PINCAP_VREF_100) |
2590 | return AC_PINCTL_VREF_100; | 2543 | return AC_PINCTL_VREF_100; |
@@ -2759,22 +2712,37 @@ static struct snd_kcontrol_new stac92xx_control_templates[] = { | |||
2759 | }; | 2712 | }; |
2760 | 2713 | ||
2761 | /* add dynamic controls */ | 2714 | /* add dynamic controls */ |
2762 | static int stac92xx_add_control_temp(struct sigmatel_spec *spec, | 2715 | static struct snd_kcontrol_new * |
2763 | struct snd_kcontrol_new *ktemp, | 2716 | stac_control_new(struct sigmatel_spec *spec, |
2764 | int idx, const char *name, | 2717 | struct snd_kcontrol_new *ktemp, |
2765 | unsigned long val) | 2718 | const char *name) |
2766 | { | 2719 | { |
2767 | struct snd_kcontrol_new *knew; | 2720 | struct snd_kcontrol_new *knew; |
2768 | 2721 | ||
2769 | snd_array_init(&spec->kctls, sizeof(*knew), 32); | 2722 | snd_array_init(&spec->kctls, sizeof(*knew), 32); |
2770 | knew = snd_array_new(&spec->kctls); | 2723 | knew = snd_array_new(&spec->kctls); |
2771 | if (!knew) | 2724 | if (!knew) |
2772 | return -ENOMEM; | 2725 | return NULL; |
2773 | *knew = *ktemp; | 2726 | *knew = *ktemp; |
2774 | knew->index = idx; | ||
2775 | knew->name = kstrdup(name, GFP_KERNEL); | 2727 | knew->name = kstrdup(name, GFP_KERNEL); |
2776 | if (!knew->name) | 2728 | if (!knew->name) { |
2729 | /* roolback */ | ||
2730 | memset(knew, 0, sizeof(*knew)); | ||
2731 | spec->kctls.alloced--; | ||
2732 | return NULL; | ||
2733 | } | ||
2734 | return knew; | ||
2735 | } | ||
2736 | |||
2737 | static int stac92xx_add_control_temp(struct sigmatel_spec *spec, | ||
2738 | struct snd_kcontrol_new *ktemp, | ||
2739 | int idx, const char *name, | ||
2740 | unsigned long val) | ||
2741 | { | ||
2742 | struct snd_kcontrol_new *knew = stac_control_new(spec, ktemp, name); | ||
2743 | if (!knew) | ||
2777 | return -ENOMEM; | 2744 | return -ENOMEM; |
2745 | knew->index = idx; | ||
2778 | knew->private_value = val; | 2746 | knew->private_value = val; |
2779 | return 0; | 2747 | return 0; |
2780 | } | 2748 | } |
@@ -2796,6 +2764,29 @@ static inline int stac92xx_add_control(struct sigmatel_spec *spec, int type, | |||
2796 | return stac92xx_add_control_idx(spec, type, 0, name, val); | 2764 | return stac92xx_add_control_idx(spec, type, 0, name, val); |
2797 | } | 2765 | } |
2798 | 2766 | ||
2767 | static struct snd_kcontrol_new stac_input_src_temp = { | ||
2768 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2769 | .name = "Input Source", | ||
2770 | .info = stac92xx_mux_enum_info, | ||
2771 | .get = stac92xx_mux_enum_get, | ||
2772 | .put = stac92xx_mux_enum_put, | ||
2773 | }; | ||
2774 | |||
2775 | static int stac92xx_add_input_source(struct sigmatel_spec *spec) | ||
2776 | { | ||
2777 | struct snd_kcontrol_new *knew; | ||
2778 | struct hda_input_mux *imux = &spec->private_imux; | ||
2779 | |||
2780 | if (!spec->num_adcs || imux->num_items <= 1) | ||
2781 | return 0; /* no need for input source control */ | ||
2782 | knew = stac_control_new(spec, &stac_input_src_temp, | ||
2783 | stac_input_src_temp.name); | ||
2784 | if (!knew) | ||
2785 | return -ENOMEM; | ||
2786 | knew->count = spec->num_adcs; | ||
2787 | return 0; | ||
2788 | } | ||
2789 | |||
2799 | /* check whether the line-input can be used as line-out */ | 2790 | /* check whether the line-input can be used as line-out */ |
2800 | static hda_nid_t check_line_out_switch(struct hda_codec *codec) | 2791 | static hda_nid_t check_line_out_switch(struct hda_codec *codec) |
2801 | { | 2792 | { |
@@ -2807,7 +2798,7 @@ static hda_nid_t check_line_out_switch(struct hda_codec *codec) | |||
2807 | if (cfg->line_out_type != AUTO_PIN_LINE_OUT) | 2798 | if (cfg->line_out_type != AUTO_PIN_LINE_OUT) |
2808 | return 0; | 2799 | return 0; |
2809 | nid = cfg->input_pins[AUTO_PIN_LINE]; | 2800 | nid = cfg->input_pins[AUTO_PIN_LINE]; |
2810 | pincap = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); | 2801 | pincap = snd_hda_query_pin_caps(codec, nid); |
2811 | if (pincap & AC_PINCAP_OUT) | 2802 | if (pincap & AC_PINCAP_OUT) |
2812 | return nid; | 2803 | return nid; |
2813 | return 0; | 2804 | return 0; |
@@ -2826,12 +2817,11 @@ static hda_nid_t check_mic_out_switch(struct hda_codec *codec) | |||
2826 | mic_pin = AUTO_PIN_MIC; | 2817 | mic_pin = AUTO_PIN_MIC; |
2827 | for (;;) { | 2818 | for (;;) { |
2828 | hda_nid_t nid = cfg->input_pins[mic_pin]; | 2819 | hda_nid_t nid = cfg->input_pins[mic_pin]; |
2829 | def_conf = snd_hda_codec_read(codec, nid, 0, | 2820 | def_conf = snd_hda_codec_get_pincfg(codec, nid); |
2830 | AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
2831 | /* some laptops have an internal analog microphone | 2821 | /* some laptops have an internal analog microphone |
2832 | * which can't be used as a output */ | 2822 | * which can't be used as a output */ |
2833 | if (get_defcfg_connect(def_conf) != AC_JACK_PORT_FIXED) { | 2823 | if (get_defcfg_connect(def_conf) != AC_JACK_PORT_FIXED) { |
2834 | pincap = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); | 2824 | pincap = snd_hda_query_pin_caps(codec, nid); |
2835 | if (pincap & AC_PINCAP_OUT) | 2825 | if (pincap & AC_PINCAP_OUT) |
2836 | return nid; | 2826 | return nid; |
2837 | } | 2827 | } |
@@ -2879,8 +2869,7 @@ static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t nid) | |||
2879 | conn_len = snd_hda_get_connections(codec, nid, conn, | 2869 | conn_len = snd_hda_get_connections(codec, nid, conn, |
2880 | HDA_MAX_CONNECTIONS); | 2870 | HDA_MAX_CONNECTIONS); |
2881 | for (j = 0; j < conn_len; j++) { | 2871 | for (j = 0; j < conn_len; j++) { |
2882 | wcaps = snd_hda_param_read(codec, conn[j], | 2872 | wcaps = get_wcaps(codec, conn[j]); |
2883 | AC_PAR_AUDIO_WIDGET_CAP); | ||
2884 | wtype = (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; | 2873 | wtype = (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; |
2885 | /* we check only analog outputs */ | 2874 | /* we check only analog outputs */ |
2886 | if (wtype != AC_WID_AUD_OUT || (wcaps & AC_WCAP_DIGITAL)) | 2875 | if (wtype != AC_WID_AUD_OUT || (wcaps & AC_WCAP_DIGITAL)) |
@@ -2895,6 +2884,16 @@ static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t nid) | |||
2895 | return conn[j]; | 2884 | return conn[j]; |
2896 | } | 2885 | } |
2897 | } | 2886 | } |
2887 | /* if all DACs are already assigned, connect to the primary DAC */ | ||
2888 | if (conn_len > 1) { | ||
2889 | for (j = 0; j < conn_len; j++) { | ||
2890 | if (conn[j] == spec->multiout.dac_nids[0]) { | ||
2891 | snd_hda_codec_write_cache(codec, nid, 0, | ||
2892 | AC_VERB_SET_CONNECT_SEL, j); | ||
2893 | break; | ||
2894 | } | ||
2895 | } | ||
2896 | } | ||
2898 | return 0; | 2897 | return 0; |
2899 | } | 2898 | } |
2900 | 2899 | ||
@@ -2935,6 +2934,26 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec) | |||
2935 | add_spec_dacs(spec, dac); | 2934 | add_spec_dacs(spec, dac); |
2936 | } | 2935 | } |
2937 | 2936 | ||
2937 | for (i = 0; i < cfg->hp_outs; i++) { | ||
2938 | nid = cfg->hp_pins[i]; | ||
2939 | dac = get_unassigned_dac(codec, nid); | ||
2940 | if (dac) { | ||
2941 | if (!spec->multiout.hp_nid) | ||
2942 | spec->multiout.hp_nid = dac; | ||
2943 | else | ||
2944 | add_spec_extra_dacs(spec, dac); | ||
2945 | } | ||
2946 | spec->hp_dacs[i] = dac; | ||
2947 | } | ||
2948 | |||
2949 | for (i = 0; i < cfg->speaker_outs; i++) { | ||
2950 | nid = cfg->speaker_pins[i]; | ||
2951 | dac = get_unassigned_dac(codec, nid); | ||
2952 | if (dac) | ||
2953 | add_spec_extra_dacs(spec, dac); | ||
2954 | spec->speaker_dacs[i] = dac; | ||
2955 | } | ||
2956 | |||
2938 | /* add line-in as output */ | 2957 | /* add line-in as output */ |
2939 | nid = check_line_out_switch(codec); | 2958 | nid = check_line_out_switch(codec); |
2940 | if (nid) { | 2959 | if (nid) { |
@@ -2962,26 +2981,6 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec) | |||
2962 | } | 2981 | } |
2963 | } | 2982 | } |
2964 | 2983 | ||
2965 | for (i = 0; i < cfg->hp_outs; i++) { | ||
2966 | nid = cfg->hp_pins[i]; | ||
2967 | dac = get_unassigned_dac(codec, nid); | ||
2968 | if (dac) { | ||
2969 | if (!spec->multiout.hp_nid) | ||
2970 | spec->multiout.hp_nid = dac; | ||
2971 | else | ||
2972 | add_spec_extra_dacs(spec, dac); | ||
2973 | } | ||
2974 | spec->hp_dacs[i] = dac; | ||
2975 | } | ||
2976 | |||
2977 | for (i = 0; i < cfg->speaker_outs; i++) { | ||
2978 | nid = cfg->speaker_pins[i]; | ||
2979 | dac = get_unassigned_dac(codec, nid); | ||
2980 | if (dac) | ||
2981 | add_spec_extra_dacs(spec, dac); | ||
2982 | spec->speaker_dacs[i] = dac; | ||
2983 | } | ||
2984 | |||
2985 | snd_printd("stac92xx: dac_nids=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", | 2984 | snd_printd("stac92xx: dac_nids=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", |
2986 | spec->multiout.num_dacs, | 2985 | spec->multiout.num_dacs, |
2987 | spec->multiout.dac_nids[0], | 2986 | spec->multiout.dac_nids[0], |
@@ -2994,24 +2993,47 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec) | |||
2994 | } | 2993 | } |
2995 | 2994 | ||
2996 | /* create volume control/switch for the given prefx type */ | 2995 | /* create volume control/switch for the given prefx type */ |
2997 | static int create_controls(struct sigmatel_spec *spec, const char *pfx, hda_nid_t nid, int chs) | 2996 | static int create_controls_idx(struct hda_codec *codec, const char *pfx, |
2997 | int idx, hda_nid_t nid, int chs) | ||
2998 | { | 2998 | { |
2999 | struct sigmatel_spec *spec = codec->spec; | ||
2999 | char name[32]; | 3000 | char name[32]; |
3000 | int err; | 3001 | int err; |
3001 | 3002 | ||
3003 | if (!spec->check_volume_offset) { | ||
3004 | unsigned int caps, step, nums, db_scale; | ||
3005 | caps = query_amp_caps(codec, nid, HDA_OUTPUT); | ||
3006 | step = (caps & AC_AMPCAP_STEP_SIZE) >> | ||
3007 | AC_AMPCAP_STEP_SIZE_SHIFT; | ||
3008 | step = (step + 1) * 25; /* in .01dB unit */ | ||
3009 | nums = (caps & AC_AMPCAP_NUM_STEPS) >> | ||
3010 | AC_AMPCAP_NUM_STEPS_SHIFT; | ||
3011 | db_scale = nums * step; | ||
3012 | /* if dB scale is over -64dB, and finer enough, | ||
3013 | * let's reduce it to half | ||
3014 | */ | ||
3015 | if (db_scale > 6400 && nums >= 0x1f) | ||
3016 | spec->volume_offset = nums / 2; | ||
3017 | spec->check_volume_offset = 1; | ||
3018 | } | ||
3019 | |||
3002 | sprintf(name, "%s Playback Volume", pfx); | 3020 | sprintf(name, "%s Playback Volume", pfx); |
3003 | err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, name, | 3021 | err = stac92xx_add_control_idx(spec, STAC_CTL_WIDGET_VOL, idx, name, |
3004 | HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); | 3022 | HDA_COMPOSE_AMP_VAL_OFS(nid, chs, 0, HDA_OUTPUT, |
3023 | spec->volume_offset)); | ||
3005 | if (err < 0) | 3024 | if (err < 0) |
3006 | return err; | 3025 | return err; |
3007 | sprintf(name, "%s Playback Switch", pfx); | 3026 | sprintf(name, "%s Playback Switch", pfx); |
3008 | err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, name, | 3027 | err = stac92xx_add_control_idx(spec, STAC_CTL_WIDGET_MUTE, idx, name, |
3009 | HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); | 3028 | HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); |
3010 | if (err < 0) | 3029 | if (err < 0) |
3011 | return err; | 3030 | return err; |
3012 | return 0; | 3031 | return 0; |
3013 | } | 3032 | } |
3014 | 3033 | ||
3034 | #define create_controls(codec, pfx, nid, chs) \ | ||
3035 | create_controls_idx(codec, pfx, 0, nid, chs) | ||
3036 | |||
3015 | static int add_spec_dacs(struct sigmatel_spec *spec, hda_nid_t nid) | 3037 | static int add_spec_dacs(struct sigmatel_spec *spec, hda_nid_t nid) |
3016 | { | 3038 | { |
3017 | if (spec->multiout.num_dacs > 4) { | 3039 | if (spec->multiout.num_dacs > 4) { |
@@ -3037,40 +3059,32 @@ static int add_spec_extra_dacs(struct sigmatel_spec *spec, hda_nid_t nid) | |||
3037 | return 1; | 3059 | return 1; |
3038 | } | 3060 | } |
3039 | 3061 | ||
3040 | static int is_unique_dac(struct sigmatel_spec *spec, hda_nid_t nid) | 3062 | /* Create output controls |
3041 | { | 3063 | * The mixer elements are named depending on the given type (AUTO_PIN_XXX_OUT) |
3042 | int i; | 3064 | */ |
3043 | 3065 | static int create_multi_out_ctls(struct hda_codec *codec, int num_outs, | |
3044 | if (spec->autocfg.line_outs != 1) | 3066 | const hda_nid_t *pins, |
3045 | return 0; | 3067 | const hda_nid_t *dac_nids, |
3046 | if (spec->multiout.hp_nid == nid) | 3068 | int type) |
3047 | return 0; | ||
3048 | for (i = 0; i < ARRAY_SIZE(spec->multiout.extra_out_nid); i++) | ||
3049 | if (spec->multiout.extra_out_nid[i] == nid) | ||
3050 | return 0; | ||
3051 | return 1; | ||
3052 | } | ||
3053 | |||
3054 | /* add playback controls from the parsed DAC table */ | ||
3055 | static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec, | ||
3056 | const struct auto_pin_cfg *cfg) | ||
3057 | { | 3069 | { |
3058 | struct sigmatel_spec *spec = codec->spec; | 3070 | struct sigmatel_spec *spec = codec->spec; |
3059 | static const char *chname[4] = { | 3071 | static const char *chname[4] = { |
3060 | "Front", "Surround", NULL /*CLFE*/, "Side" | 3072 | "Front", "Surround", NULL /*CLFE*/, "Side" |
3061 | }; | 3073 | }; |
3062 | hda_nid_t nid = 0; | 3074 | hda_nid_t nid; |
3063 | int i, err; | 3075 | int i, err; |
3064 | unsigned int wid_caps; | 3076 | unsigned int wid_caps; |
3065 | 3077 | ||
3066 | for (i = 0; i < cfg->line_outs && spec->multiout.dac_nids[i]; i++) { | 3078 | for (i = 0; i < num_outs && i < ARRAY_SIZE(chname); i++) { |
3067 | nid = spec->multiout.dac_nids[i]; | 3079 | nid = dac_nids[i]; |
3068 | if (i == 2) { | 3080 | if (!nid) |
3081 | continue; | ||
3082 | if (type != AUTO_PIN_HP_OUT && i == 2) { | ||
3069 | /* Center/LFE */ | 3083 | /* Center/LFE */ |
3070 | err = create_controls(spec, "Center", nid, 1); | 3084 | err = create_controls(codec, "Center", nid, 1); |
3071 | if (err < 0) | 3085 | if (err < 0) |
3072 | return err; | 3086 | return err; |
3073 | err = create_controls(spec, "LFE", nid, 2); | 3087 | err = create_controls(codec, "LFE", nid, 2); |
3074 | if (err < 0) | 3088 | if (err < 0) |
3075 | return err; | 3089 | return err; |
3076 | 3090 | ||
@@ -3086,23 +3100,47 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec, | |||
3086 | } | 3100 | } |
3087 | 3101 | ||
3088 | } else { | 3102 | } else { |
3089 | const char *name = chname[i]; | 3103 | const char *name; |
3090 | /* if it's a single DAC, assign a better name */ | 3104 | int idx; |
3091 | if (!i && is_unique_dac(spec, nid)) { | 3105 | switch (type) { |
3092 | switch (cfg->line_out_type) { | 3106 | case AUTO_PIN_HP_OUT: |
3093 | case AUTO_PIN_HP_OUT: | 3107 | name = "Headphone"; |
3094 | name = "Headphone"; | 3108 | idx = i; |
3095 | break; | 3109 | break; |
3096 | case AUTO_PIN_SPEAKER_OUT: | 3110 | case AUTO_PIN_SPEAKER_OUT: |
3097 | name = "Speaker"; | 3111 | name = "Speaker"; |
3098 | break; | 3112 | idx = i; |
3099 | } | 3113 | break; |
3114 | default: | ||
3115 | name = chname[i]; | ||
3116 | idx = 0; | ||
3117 | break; | ||
3100 | } | 3118 | } |
3101 | err = create_controls(spec, name, nid, 3); | 3119 | err = create_controls_idx(codec, name, idx, nid, 3); |
3102 | if (err < 0) | 3120 | if (err < 0) |
3103 | return err; | 3121 | return err; |
3122 | if (type == AUTO_PIN_HP_OUT && !spec->hp_detect) { | ||
3123 | wid_caps = get_wcaps(codec, pins[i]); | ||
3124 | if (wid_caps & AC_WCAP_UNSOL_CAP) | ||
3125 | spec->hp_detect = 1; | ||
3126 | } | ||
3104 | } | 3127 | } |
3105 | } | 3128 | } |
3129 | return 0; | ||
3130 | } | ||
3131 | |||
3132 | /* add playback controls from the parsed DAC table */ | ||
3133 | static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec, | ||
3134 | const struct auto_pin_cfg *cfg) | ||
3135 | { | ||
3136 | struct sigmatel_spec *spec = codec->spec; | ||
3137 | int err; | ||
3138 | |||
3139 | err = create_multi_out_ctls(codec, cfg->line_outs, cfg->line_out_pins, | ||
3140 | spec->multiout.dac_nids, | ||
3141 | cfg->line_out_type); | ||
3142 | if (err < 0) | ||
3143 | return err; | ||
3106 | 3144 | ||
3107 | if (cfg->hp_outs > 1 && cfg->line_out_type == AUTO_PIN_LINE_OUT) { | 3145 | if (cfg->hp_outs > 1 && cfg->line_out_type == AUTO_PIN_LINE_OUT) { |
3108 | err = stac92xx_add_control(spec, | 3146 | err = stac92xx_add_control(spec, |
@@ -3137,40 +3175,18 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, | |||
3137 | struct auto_pin_cfg *cfg) | 3175 | struct auto_pin_cfg *cfg) |
3138 | { | 3176 | { |
3139 | struct sigmatel_spec *spec = codec->spec; | 3177 | struct sigmatel_spec *spec = codec->spec; |
3140 | hda_nid_t nid; | 3178 | int err; |
3141 | int i, err, nums; | 3179 | |
3180 | err = create_multi_out_ctls(codec, cfg->hp_outs, cfg->hp_pins, | ||
3181 | spec->hp_dacs, AUTO_PIN_HP_OUT); | ||
3182 | if (err < 0) | ||
3183 | return err; | ||
3184 | |||
3185 | err = create_multi_out_ctls(codec, cfg->speaker_outs, cfg->speaker_pins, | ||
3186 | spec->speaker_dacs, AUTO_PIN_SPEAKER_OUT); | ||
3187 | if (err < 0) | ||
3188 | return err; | ||
3142 | 3189 | ||
3143 | nums = 0; | ||
3144 | for (i = 0; i < cfg->hp_outs; i++) { | ||
3145 | static const char *pfxs[] = { | ||
3146 | "Headphone", "Headphone2", "Headphone3", | ||
3147 | }; | ||
3148 | unsigned int wid_caps = get_wcaps(codec, cfg->hp_pins[i]); | ||
3149 | if (wid_caps & AC_WCAP_UNSOL_CAP) | ||
3150 | spec->hp_detect = 1; | ||
3151 | if (nums >= ARRAY_SIZE(pfxs)) | ||
3152 | continue; | ||
3153 | nid = spec->hp_dacs[i]; | ||
3154 | if (!nid) | ||
3155 | continue; | ||
3156 | err = create_controls(spec, pfxs[nums++], nid, 3); | ||
3157 | if (err < 0) | ||
3158 | return err; | ||
3159 | } | ||
3160 | nums = 0; | ||
3161 | for (i = 0; i < cfg->speaker_outs; i++) { | ||
3162 | static const char *pfxs[] = { | ||
3163 | "Speaker", "External Speaker", "Speaker2", | ||
3164 | }; | ||
3165 | if (nums >= ARRAY_SIZE(pfxs)) | ||
3166 | continue; | ||
3167 | nid = spec->speaker_dacs[i]; | ||
3168 | if (!nid) | ||
3169 | continue; | ||
3170 | err = create_controls(spec, pfxs[nums++], nid, 3); | ||
3171 | if (err < 0) | ||
3172 | return err; | ||
3173 | } | ||
3174 | return 0; | 3190 | return 0; |
3175 | } | 3191 | } |
3176 | 3192 | ||
@@ -3379,11 +3395,7 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec, | |||
3379 | unsigned int wcaps; | 3395 | unsigned int wcaps; |
3380 | unsigned int def_conf; | 3396 | unsigned int def_conf; |
3381 | 3397 | ||
3382 | def_conf = snd_hda_codec_read(codec, | 3398 | def_conf = snd_hda_codec_get_pincfg(codec, spec->dmic_nids[i]); |
3383 | spec->dmic_nids[i], | ||
3384 | 0, | ||
3385 | AC_VERB_GET_CONFIG_DEFAULT, | ||
3386 | 0); | ||
3387 | if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE) | 3399 | if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE) |
3388 | continue; | 3400 | continue; |
3389 | 3401 | ||
@@ -3507,6 +3519,7 @@ static void stac92xx_auto_init_hp_out(struct hda_codec *codec) | |||
3507 | static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out, hda_nid_t dig_in) | 3519 | static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out, hda_nid_t dig_in) |
3508 | { | 3520 | { |
3509 | struct sigmatel_spec *spec = codec->spec; | 3521 | struct sigmatel_spec *spec = codec->spec; |
3522 | int hp_swap = 0; | ||
3510 | int err; | 3523 | int err; |
3511 | 3524 | ||
3512 | if ((err = snd_hda_parse_pin_def_config(codec, | 3525 | if ((err = snd_hda_parse_pin_def_config(codec, |
@@ -3516,7 +3529,6 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
3516 | if (! spec->autocfg.line_outs) | 3529 | if (! spec->autocfg.line_outs) |
3517 | return 0; /* can't find valid pin config */ | 3530 | return 0; /* can't find valid pin config */ |
3518 | 3531 | ||
3519 | #if 0 /* FIXME: temporarily disabled */ | ||
3520 | /* If we have no real line-out pin and multiple hp-outs, HPs should | 3532 | /* If we have no real line-out pin and multiple hp-outs, HPs should |
3521 | * be set up as multi-channel outputs. | 3533 | * be set up as multi-channel outputs. |
3522 | */ | 3534 | */ |
@@ -3535,8 +3547,8 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
3535 | spec->autocfg.line_outs = spec->autocfg.hp_outs; | 3547 | spec->autocfg.line_outs = spec->autocfg.hp_outs; |
3536 | spec->autocfg.line_out_type = AUTO_PIN_HP_OUT; | 3548 | spec->autocfg.line_out_type = AUTO_PIN_HP_OUT; |
3537 | spec->autocfg.hp_outs = 0; | 3549 | spec->autocfg.hp_outs = 0; |
3550 | hp_swap = 1; | ||
3538 | } | 3551 | } |
3539 | #endif /* FIXME: temporarily disabled */ | ||
3540 | if (spec->autocfg.mono_out_pin) { | 3552 | if (spec->autocfg.mono_out_pin) { |
3541 | int dir = get_wcaps(codec, spec->autocfg.mono_out_pin) & | 3553 | int dir = get_wcaps(codec, spec->autocfg.mono_out_pin) & |
3542 | (AC_WCAP_OUT_AMP | AC_WCAP_IN_AMP); | 3554 | (AC_WCAP_OUT_AMP | AC_WCAP_IN_AMP); |
@@ -3629,12 +3641,19 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
3629 | #endif | 3641 | #endif |
3630 | 3642 | ||
3631 | err = stac92xx_auto_create_hp_ctls(codec, &spec->autocfg); | 3643 | err = stac92xx_auto_create_hp_ctls(codec, &spec->autocfg); |
3632 | |||
3633 | if (err < 0) | 3644 | if (err < 0) |
3634 | return err; | 3645 | return err; |
3635 | 3646 | ||
3636 | err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg); | 3647 | /* All output parsing done, now restore the swapped hp pins */ |
3648 | if (hp_swap) { | ||
3649 | memcpy(spec->autocfg.hp_pins, spec->autocfg.line_out_pins, | ||
3650 | sizeof(spec->autocfg.hp_pins)); | ||
3651 | spec->autocfg.hp_outs = spec->autocfg.line_outs; | ||
3652 | spec->autocfg.line_out_type = AUTO_PIN_HP_OUT; | ||
3653 | spec->autocfg.line_outs = 0; | ||
3654 | } | ||
3637 | 3655 | ||
3656 | err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg); | ||
3638 | if (err < 0) | 3657 | if (err < 0) |
3639 | return err; | 3658 | return err; |
3640 | 3659 | ||
@@ -3663,11 +3682,15 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
3663 | return err; | 3682 | return err; |
3664 | } | 3683 | } |
3665 | 3684 | ||
3685 | err = stac92xx_add_input_source(spec); | ||
3686 | if (err < 0) | ||
3687 | return err; | ||
3688 | |||
3666 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 3689 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
3667 | if (spec->multiout.max_channels > 2) | 3690 | if (spec->multiout.max_channels > 2) |
3668 | spec->surr_switch = 1; | 3691 | spec->surr_switch = 1; |
3669 | 3692 | ||
3670 | if (spec->autocfg.dig_out_pin) | 3693 | if (spec->autocfg.dig_outs) |
3671 | spec->multiout.dig_out_nid = dig_out; | 3694 | spec->multiout.dig_out_nid = dig_out; |
3672 | if (dig_in && spec->autocfg.dig_in_pin) | 3695 | if (dig_in && spec->autocfg.dig_in_pin) |
3673 | spec->dig_in_nid = dig_in; | 3696 | spec->dig_in_nid = dig_in; |
@@ -3730,9 +3753,7 @@ static int stac9200_auto_create_lfe_ctls(struct hda_codec *codec, | |||
3730 | for (i = 0; i < spec->autocfg.line_outs && lfe_pin == 0x0; i++) { | 3753 | for (i = 0; i < spec->autocfg.line_outs && lfe_pin == 0x0; i++) { |
3731 | hda_nid_t pin = spec->autocfg.line_out_pins[i]; | 3754 | hda_nid_t pin = spec->autocfg.line_out_pins[i]; |
3732 | unsigned int defcfg; | 3755 | unsigned int defcfg; |
3733 | defcfg = snd_hda_codec_read(codec, pin, 0, | 3756 | defcfg = snd_hda_codec_get_pincfg(codec, pin); |
3734 | AC_VERB_GET_CONFIG_DEFAULT, | ||
3735 | 0x00); | ||
3736 | if (get_defcfg_device(defcfg) == AC_JACK_SPEAKER) { | 3757 | if (get_defcfg_device(defcfg) == AC_JACK_SPEAKER) { |
3737 | unsigned int wcaps = get_wcaps(codec, pin); | 3758 | unsigned int wcaps = get_wcaps(codec, pin); |
3738 | wcaps &= (AC_WCAP_STEREO | AC_WCAP_OUT_AMP); | 3759 | wcaps &= (AC_WCAP_STEREO | AC_WCAP_OUT_AMP); |
@@ -3745,7 +3766,7 @@ static int stac9200_auto_create_lfe_ctls(struct hda_codec *codec, | |||
3745 | } | 3766 | } |
3746 | 3767 | ||
3747 | if (lfe_pin) { | 3768 | if (lfe_pin) { |
3748 | err = create_controls(spec, "LFE", lfe_pin, 1); | 3769 | err = create_controls(codec, "LFE", lfe_pin, 1); |
3749 | if (err < 0) | 3770 | if (err < 0) |
3750 | return err; | 3771 | return err; |
3751 | } | 3772 | } |
@@ -3776,7 +3797,11 @@ static int stac9200_parse_auto_config(struct hda_codec *codec) | |||
3776 | return err; | 3797 | return err; |
3777 | } | 3798 | } |
3778 | 3799 | ||
3779 | if (spec->autocfg.dig_out_pin) | 3800 | err = stac92xx_add_input_source(spec); |
3801 | if (err < 0) | ||
3802 | return err; | ||
3803 | |||
3804 | if (spec->autocfg.dig_outs) | ||
3780 | spec->multiout.dig_out_nid = 0x05; | 3805 | spec->multiout.dig_out_nid = 0x05; |
3781 | if (spec->autocfg.dig_in_pin) | 3806 | if (spec->autocfg.dig_in_pin) |
3782 | spec->dig_in_nid = 0x04; | 3807 | spec->dig_in_nid = 0x04; |
@@ -3832,8 +3857,7 @@ static int stac92xx_add_jack(struct hda_codec *codec, | |||
3832 | #ifdef CONFIG_SND_JACK | 3857 | #ifdef CONFIG_SND_JACK |
3833 | struct sigmatel_spec *spec = codec->spec; | 3858 | struct sigmatel_spec *spec = codec->spec; |
3834 | struct sigmatel_jack *jack; | 3859 | struct sigmatel_jack *jack; |
3835 | int def_conf = snd_hda_codec_read(codec, nid, | 3860 | int def_conf = snd_hda_codec_get_pincfg(codec, nid); |
3836 | 0, AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
3837 | int connectivity = get_defcfg_connect(def_conf); | 3861 | int connectivity = get_defcfg_connect(def_conf); |
3838 | char name[32]; | 3862 | char name[32]; |
3839 | 3863 | ||
@@ -3948,6 +3972,36 @@ static void stac92xx_power_down(struct hda_codec *codec) | |||
3948 | static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid, | 3972 | static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid, |
3949 | int enable); | 3973 | int enable); |
3950 | 3974 | ||
3975 | /* override some hints from the hwdep entry */ | ||
3976 | static void stac_store_hints(struct hda_codec *codec) | ||
3977 | { | ||
3978 | struct sigmatel_spec *spec = codec->spec; | ||
3979 | const char *p; | ||
3980 | int val; | ||
3981 | |||
3982 | val = snd_hda_get_bool_hint(codec, "hp_detect"); | ||
3983 | if (val >= 0) | ||
3984 | spec->hp_detect = val; | ||
3985 | p = snd_hda_get_hint(codec, "gpio_mask"); | ||
3986 | if (p) { | ||
3987 | spec->gpio_mask = simple_strtoul(p, NULL, 0); | ||
3988 | spec->eapd_mask = spec->gpio_dir = spec->gpio_data = | ||
3989 | spec->gpio_mask; | ||
3990 | } | ||
3991 | p = snd_hda_get_hint(codec, "gpio_dir"); | ||
3992 | if (p) | ||
3993 | spec->gpio_dir = simple_strtoul(p, NULL, 0) & spec->gpio_mask; | ||
3994 | p = snd_hda_get_hint(codec, "gpio_data"); | ||
3995 | if (p) | ||
3996 | spec->gpio_data = simple_strtoul(p, NULL, 0) & spec->gpio_mask; | ||
3997 | p = snd_hda_get_hint(codec, "eapd_mask"); | ||
3998 | if (p) | ||
3999 | spec->eapd_mask = simple_strtoul(p, NULL, 0) & spec->gpio_mask; | ||
4000 | val = snd_hda_get_bool_hint(codec, "eapd_switch"); | ||
4001 | if (val >= 0) | ||
4002 | spec->eapd_switch = val; | ||
4003 | } | ||
4004 | |||
3951 | static int stac92xx_init(struct hda_codec *codec) | 4005 | static int stac92xx_init(struct hda_codec *codec) |
3952 | { | 4006 | { |
3953 | struct sigmatel_spec *spec = codec->spec; | 4007 | struct sigmatel_spec *spec = codec->spec; |
@@ -3964,6 +4018,9 @@ static int stac92xx_init(struct hda_codec *codec) | |||
3964 | spec->adc_nids[i], 0, | 4018 | spec->adc_nids[i], 0, |
3965 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); | 4019 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); |
3966 | 4020 | ||
4021 | /* override some hints */ | ||
4022 | stac_store_hints(codec); | ||
4023 | |||
3967 | /* set up GPIO */ | 4024 | /* set up GPIO */ |
3968 | gpio = spec->gpio_data; | 4025 | gpio = spec->gpio_data; |
3969 | /* turn on EAPD statically when spec->eapd_switch isn't set. | 4026 | /* turn on EAPD statically when spec->eapd_switch isn't set. |
@@ -4013,8 +4070,7 @@ static int stac92xx_init(struct hda_codec *codec) | |||
4013 | pinctl); | 4070 | pinctl); |
4014 | } | 4071 | } |
4015 | } | 4072 | } |
4016 | conf = snd_hda_codec_read(codec, nid, 0, | 4073 | conf = snd_hda_codec_get_pincfg(codec, nid); |
4017 | AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
4018 | if (get_defcfg_connect(conf) != AC_JACK_PORT_FIXED) { | 4074 | if (get_defcfg_connect(conf) != AC_JACK_PORT_FIXED) { |
4019 | enable_pin_detect(codec, nid, | 4075 | enable_pin_detect(codec, nid, |
4020 | STAC_INSERT_EVENT); | 4076 | STAC_INSERT_EVENT); |
@@ -4026,8 +4082,8 @@ static int stac92xx_init(struct hda_codec *codec) | |||
4026 | for (i = 0; i < spec->num_dmics; i++) | 4082 | for (i = 0; i < spec->num_dmics; i++) |
4027 | stac92xx_auto_set_pinctl(codec, spec->dmic_nids[i], | 4083 | stac92xx_auto_set_pinctl(codec, spec->dmic_nids[i], |
4028 | AC_PINCTL_IN_EN); | 4084 | AC_PINCTL_IN_EN); |
4029 | if (cfg->dig_out_pin) | 4085 | if (cfg->dig_out_pins[0]) |
4030 | stac92xx_auto_set_pinctl(codec, cfg->dig_out_pin, | 4086 | stac92xx_auto_set_pinctl(codec, cfg->dig_out_pins[0], |
4031 | AC_PINCTL_OUT_EN); | 4087 | AC_PINCTL_OUT_EN); |
4032 | if (cfg->dig_in_pin) | 4088 | if (cfg->dig_in_pin) |
4033 | stac92xx_auto_set_pinctl(codec, cfg->dig_in_pin, | 4089 | stac92xx_auto_set_pinctl(codec, cfg->dig_in_pin, |
@@ -4055,8 +4111,7 @@ static int stac92xx_init(struct hda_codec *codec) | |||
4055 | stac_toggle_power_map(codec, nid, 1); | 4111 | stac_toggle_power_map(codec, nid, 1); |
4056 | continue; | 4112 | continue; |
4057 | } | 4113 | } |
4058 | def_conf = snd_hda_codec_read(codec, nid, 0, | 4114 | def_conf = snd_hda_codec_get_pincfg(codec, nid); |
4059 | AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
4060 | def_conf = get_defcfg_connect(def_conf); | 4115 | def_conf = get_defcfg_connect(def_conf); |
4061 | /* skip any ports that don't have jacks since presence | 4116 | /* skip any ports that don't have jacks since presence |
4062 | * detection is useless */ | 4117 | * detection is useless */ |
@@ -4110,7 +4165,6 @@ static void stac92xx_free(struct hda_codec *codec) | |||
4110 | if (! spec) | 4165 | if (! spec) |
4111 | return; | 4166 | return; |
4112 | 4167 | ||
4113 | kfree(spec->pin_configs); | ||
4114 | stac92xx_free_jacks(codec); | 4168 | stac92xx_free_jacks(codec); |
4115 | snd_array_free(&spec->events); | 4169 | snd_array_free(&spec->events); |
4116 | 4170 | ||
@@ -4121,7 +4175,9 @@ static void stac92xx_free(struct hda_codec *codec) | |||
4121 | static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid, | 4175 | static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid, |
4122 | unsigned int flag) | 4176 | unsigned int flag) |
4123 | { | 4177 | { |
4124 | unsigned int pin_ctl = snd_hda_codec_read(codec, nid, | 4178 | unsigned int old_ctl, pin_ctl; |
4179 | |||
4180 | pin_ctl = snd_hda_codec_read(codec, nid, | ||
4125 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); | 4181 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); |
4126 | 4182 | ||
4127 | if (pin_ctl & AC_PINCTL_IN_EN) { | 4183 | if (pin_ctl & AC_PINCTL_IN_EN) { |
@@ -4135,14 +4191,17 @@ static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid, | |||
4135 | return; | 4191 | return; |
4136 | } | 4192 | } |
4137 | 4193 | ||
4194 | old_ctl = pin_ctl; | ||
4138 | /* if setting pin direction bits, clear the current | 4195 | /* if setting pin direction bits, clear the current |
4139 | direction bits first */ | 4196 | direction bits first */ |
4140 | if (flag & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN)) | 4197 | if (flag & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN)) |
4141 | pin_ctl &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN); | 4198 | pin_ctl &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN); |
4142 | 4199 | ||
4143 | snd_hda_codec_write_cache(codec, nid, 0, | 4200 | pin_ctl |= flag; |
4144 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 4201 | if (old_ctl != pin_ctl) |
4145 | pin_ctl | flag); | 4202 | snd_hda_codec_write_cache(codec, nid, 0, |
4203 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
4204 | pin_ctl); | ||
4146 | } | 4205 | } |
4147 | 4206 | ||
4148 | static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid, | 4207 | static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid, |
@@ -4150,9 +4209,10 @@ static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid, | |||
4150 | { | 4209 | { |
4151 | unsigned int pin_ctl = snd_hda_codec_read(codec, nid, | 4210 | unsigned int pin_ctl = snd_hda_codec_read(codec, nid, |
4152 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); | 4211 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); |
4153 | snd_hda_codec_write_cache(codec, nid, 0, | 4212 | if (pin_ctl & flag) |
4154 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 4213 | snd_hda_codec_write_cache(codec, nid, 0, |
4155 | pin_ctl & ~flag); | 4214 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
4215 | pin_ctl & ~flag); | ||
4156 | } | 4216 | } |
4157 | 4217 | ||
4158 | static int get_pin_presence(struct hda_codec *codec, hda_nid_t nid) | 4218 | static int get_pin_presence(struct hda_codec *codec, hda_nid_t nid) |
@@ -4415,7 +4475,6 @@ static int stac92xx_resume(struct hda_codec *codec) | |||
4415 | { | 4475 | { |
4416 | struct sigmatel_spec *spec = codec->spec; | 4476 | struct sigmatel_spec *spec = codec->spec; |
4417 | 4477 | ||
4418 | stac92xx_set_config_regs(codec); | ||
4419 | stac92xx_init(codec); | 4478 | stac92xx_init(codec); |
4420 | snd_hda_codec_resume_amp(codec); | 4479 | snd_hda_codec_resume_amp(codec); |
4421 | snd_hda_codec_resume_cache(codec); | 4480 | snd_hda_codec_resume_cache(codec); |
@@ -4426,6 +4485,37 @@ static int stac92xx_resume(struct hda_codec *codec) | |||
4426 | return 0; | 4485 | return 0; |
4427 | } | 4486 | } |
4428 | 4487 | ||
4488 | |||
4489 | /* | ||
4490 | * using power check for controlling mute led of HP HDX notebooks | ||
4491 | * check for mute state only on Speakers (nid = 0x10) | ||
4492 | * | ||
4493 | * For this feature CONFIG_SND_HDA_POWER_SAVE is needed, otherwise | ||
4494 | * the LED is NOT working properly ! | ||
4495 | */ | ||
4496 | |||
4497 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
4498 | static int stac92xx_hp_hdx_check_power_status(struct hda_codec *codec, | ||
4499 | hda_nid_t nid) | ||
4500 | { | ||
4501 | struct sigmatel_spec *spec = codec->spec; | ||
4502 | |||
4503 | if (nid == 0x10) { | ||
4504 | if (snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) & | ||
4505 | HDA_AMP_MUTE) | ||
4506 | spec->gpio_data &= ~0x08; /* orange */ | ||
4507 | else | ||
4508 | spec->gpio_data |= 0x08; /* white */ | ||
4509 | |||
4510 | stac_gpio_set(codec, spec->gpio_mask, | ||
4511 | spec->gpio_dir, | ||
4512 | spec->gpio_data); | ||
4513 | } | ||
4514 | |||
4515 | return 0; | ||
4516 | } | ||
4517 | #endif | ||
4518 | |||
4429 | static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state) | 4519 | static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state) |
4430 | { | 4520 | { |
4431 | struct sigmatel_spec *spec = codec->spec; | 4521 | struct sigmatel_spec *spec = codec->spec; |
@@ -4464,16 +4554,11 @@ static int patch_stac9200(struct hda_codec *codec) | |||
4464 | spec->board_config = snd_hda_check_board_config(codec, STAC_9200_MODELS, | 4554 | spec->board_config = snd_hda_check_board_config(codec, STAC_9200_MODELS, |
4465 | stac9200_models, | 4555 | stac9200_models, |
4466 | stac9200_cfg_tbl); | 4556 | stac9200_cfg_tbl); |
4467 | if (spec->board_config < 0) { | 4557 | if (spec->board_config < 0) |
4468 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9200, using BIOS defaults\n"); | 4558 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9200, using BIOS defaults\n"); |
4469 | err = stac92xx_save_bios_config_regs(codec); | 4559 | else |
4470 | } else | 4560 | stac92xx_set_config_regs(codec, |
4471 | err = stac_save_pin_cfgs(codec, | ||
4472 | stac9200_brd_tbl[spec->board_config]); | 4561 | stac9200_brd_tbl[spec->board_config]); |
4473 | if (err < 0) { | ||
4474 | stac92xx_free(codec); | ||
4475 | return err; | ||
4476 | } | ||
4477 | 4562 | ||
4478 | spec->multiout.max_channels = 2; | 4563 | spec->multiout.max_channels = 2; |
4479 | spec->multiout.num_dacs = 1; | 4564 | spec->multiout.num_dacs = 1; |
@@ -4541,17 +4626,12 @@ static int patch_stac925x(struct hda_codec *codec) | |||
4541 | stac925x_models, | 4626 | stac925x_models, |
4542 | stac925x_cfg_tbl); | 4627 | stac925x_cfg_tbl); |
4543 | again: | 4628 | again: |
4544 | if (spec->board_config < 0) { | 4629 | if (spec->board_config < 0) |
4545 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC925x," | 4630 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC925x," |
4546 | "using BIOS defaults\n"); | 4631 | "using BIOS defaults\n"); |
4547 | err = stac92xx_save_bios_config_regs(codec); | 4632 | else |
4548 | } else | 4633 | stac92xx_set_config_regs(codec, |
4549 | err = stac_save_pin_cfgs(codec, | ||
4550 | stac925x_brd_tbl[spec->board_config]); | 4634 | stac925x_brd_tbl[spec->board_config]); |
4551 | if (err < 0) { | ||
4552 | stac92xx_free(codec); | ||
4553 | return err; | ||
4554 | } | ||
4555 | 4635 | ||
4556 | spec->multiout.max_channels = 2; | 4636 | spec->multiout.max_channels = 2; |
4557 | spec->multiout.num_dacs = 1; | 4637 | spec->multiout.num_dacs = 1; |
@@ -4629,17 +4709,12 @@ static int patch_stac92hd73xx(struct hda_codec *codec) | |||
4629 | stac92hd73xx_models, | 4709 | stac92hd73xx_models, |
4630 | stac92hd73xx_cfg_tbl); | 4710 | stac92hd73xx_cfg_tbl); |
4631 | again: | 4711 | again: |
4632 | if (spec->board_config < 0) { | 4712 | if (spec->board_config < 0) |
4633 | snd_printdd(KERN_INFO "hda_codec: Unknown model for" | 4713 | snd_printdd(KERN_INFO "hda_codec: Unknown model for" |
4634 | " STAC92HD73XX, using BIOS defaults\n"); | 4714 | " STAC92HD73XX, using BIOS defaults\n"); |
4635 | err = stac92xx_save_bios_config_regs(codec); | 4715 | else |
4636 | } else | 4716 | stac92xx_set_config_regs(codec, |
4637 | err = stac_save_pin_cfgs(codec, | ||
4638 | stac92hd73xx_brd_tbl[spec->board_config]); | 4717 | stac92hd73xx_brd_tbl[spec->board_config]); |
4639 | if (err < 0) { | ||
4640 | stac92xx_free(codec); | ||
4641 | return err; | ||
4642 | } | ||
4643 | 4718 | ||
4644 | num_dacs = snd_hda_get_connections(codec, 0x0a, | 4719 | num_dacs = snd_hda_get_connections(codec, 0x0a, |
4645 | conn, STAC92HD73_DAC_COUNT + 2) - 1; | 4720 | conn, STAC92HD73_DAC_COUNT + 2) - 1; |
@@ -4653,14 +4728,18 @@ again: | |||
4653 | case 0x3: /* 6 Channel */ | 4728 | case 0x3: /* 6 Channel */ |
4654 | spec->mixer = stac92hd73xx_6ch_mixer; | 4729 | spec->mixer = stac92hd73xx_6ch_mixer; |
4655 | spec->init = stac92hd73xx_6ch_core_init; | 4730 | spec->init = stac92hd73xx_6ch_core_init; |
4731 | spec->aloopback_ctl = stac92hd73xx_6ch_loopback; | ||
4656 | break; | 4732 | break; |
4657 | case 0x4: /* 8 Channel */ | 4733 | case 0x4: /* 8 Channel */ |
4658 | spec->mixer = stac92hd73xx_8ch_mixer; | 4734 | spec->mixer = stac92hd73xx_8ch_mixer; |
4659 | spec->init = stac92hd73xx_8ch_core_init; | 4735 | spec->init = stac92hd73xx_8ch_core_init; |
4736 | spec->aloopback_ctl = stac92hd73xx_8ch_loopback; | ||
4660 | break; | 4737 | break; |
4661 | case 0x5: /* 10 Channel */ | 4738 | case 0x5: /* 10 Channel */ |
4662 | spec->mixer = stac92hd73xx_10ch_mixer; | 4739 | spec->mixer = stac92hd73xx_10ch_mixer; |
4663 | spec->init = stac92hd73xx_10ch_core_init; | 4740 | spec->init = stac92hd73xx_10ch_core_init; |
4741 | spec->aloopback_ctl = stac92hd73xx_10ch_loopback; | ||
4742 | break; | ||
4664 | } | 4743 | } |
4665 | spec->multiout.dac_nids = spec->dac_nids; | 4744 | spec->multiout.dac_nids = spec->dac_nids; |
4666 | 4745 | ||
@@ -4699,18 +4778,18 @@ again: | |||
4699 | spec->init = dell_m6_core_init; | 4778 | spec->init = dell_m6_core_init; |
4700 | switch (spec->board_config) { | 4779 | switch (spec->board_config) { |
4701 | case STAC_DELL_M6_AMIC: /* Analog Mics */ | 4780 | case STAC_DELL_M6_AMIC: /* Analog Mics */ |
4702 | stac92xx_set_config_reg(codec, 0x0b, 0x90A70170); | 4781 | snd_hda_codec_set_pincfg(codec, 0x0b, 0x90A70170); |
4703 | spec->num_dmics = 0; | 4782 | spec->num_dmics = 0; |
4704 | spec->private_dimux.num_items = 1; | 4783 | spec->private_dimux.num_items = 1; |
4705 | break; | 4784 | break; |
4706 | case STAC_DELL_M6_DMIC: /* Digital Mics */ | 4785 | case STAC_DELL_M6_DMIC: /* Digital Mics */ |
4707 | stac92xx_set_config_reg(codec, 0x13, 0x90A60160); | 4786 | snd_hda_codec_set_pincfg(codec, 0x13, 0x90A60160); |
4708 | spec->num_dmics = 1; | 4787 | spec->num_dmics = 1; |
4709 | spec->private_dimux.num_items = 2; | 4788 | spec->private_dimux.num_items = 2; |
4710 | break; | 4789 | break; |
4711 | case STAC_DELL_M6_BOTH: /* Both */ | 4790 | case STAC_DELL_M6_BOTH: /* Both */ |
4712 | stac92xx_set_config_reg(codec, 0x0b, 0x90A70170); | 4791 | snd_hda_codec_set_pincfg(codec, 0x0b, 0x90A70170); |
4713 | stac92xx_set_config_reg(codec, 0x13, 0x90A60160); | 4792 | snd_hda_codec_set_pincfg(codec, 0x13, 0x90A60160); |
4714 | spec->num_dmics = 1; | 4793 | spec->num_dmics = 1; |
4715 | spec->private_dimux.num_items = 2; | 4794 | spec->private_dimux.num_items = 2; |
4716 | break; | 4795 | break; |
@@ -4773,6 +4852,7 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) | |||
4773 | hda_nid_t conn[STAC92HD83_DAC_COUNT + 1]; | 4852 | hda_nid_t conn[STAC92HD83_DAC_COUNT + 1]; |
4774 | int err; | 4853 | int err; |
4775 | int num_dacs; | 4854 | int num_dacs; |
4855 | hda_nid_t nid; | ||
4776 | 4856 | ||
4777 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 4857 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
4778 | if (spec == NULL) | 4858 | if (spec == NULL) |
@@ -4791,15 +4871,6 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) | |||
4791 | spec->num_pwrs = ARRAY_SIZE(stac92hd83xxx_pwr_nids); | 4871 | spec->num_pwrs = ARRAY_SIZE(stac92hd83xxx_pwr_nids); |
4792 | spec->multiout.dac_nids = spec->dac_nids; | 4872 | spec->multiout.dac_nids = spec->dac_nids; |
4793 | 4873 | ||
4794 | |||
4795 | /* set port 0xe to select the last DAC | ||
4796 | */ | ||
4797 | num_dacs = snd_hda_get_connections(codec, 0x0e, | ||
4798 | conn, STAC92HD83_DAC_COUNT + 1) - 1; | ||
4799 | |||
4800 | snd_hda_codec_write_cache(codec, 0xe, 0, | ||
4801 | AC_VERB_SET_CONNECT_SEL, num_dacs); | ||
4802 | |||
4803 | spec->init = stac92hd83xxx_core_init; | 4874 | spec->init = stac92hd83xxx_core_init; |
4804 | spec->mixer = stac92hd83xxx_mixer; | 4875 | spec->mixer = stac92hd83xxx_mixer; |
4805 | spec->num_pins = ARRAY_SIZE(stac92hd83xxx_pin_nids); | 4876 | spec->num_pins = ARRAY_SIZE(stac92hd83xxx_pin_nids); |
@@ -4814,17 +4885,12 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) | |||
4814 | stac92hd83xxx_models, | 4885 | stac92hd83xxx_models, |
4815 | stac92hd83xxx_cfg_tbl); | 4886 | stac92hd83xxx_cfg_tbl); |
4816 | again: | 4887 | again: |
4817 | if (spec->board_config < 0) { | 4888 | if (spec->board_config < 0) |
4818 | snd_printdd(KERN_INFO "hda_codec: Unknown model for" | 4889 | snd_printdd(KERN_INFO "hda_codec: Unknown model for" |
4819 | " STAC92HD83XXX, using BIOS defaults\n"); | 4890 | " STAC92HD83XXX, using BIOS defaults\n"); |
4820 | err = stac92xx_save_bios_config_regs(codec); | 4891 | else |
4821 | } else | 4892 | stac92xx_set_config_regs(codec, |
4822 | err = stac_save_pin_cfgs(codec, | ||
4823 | stac92hd83xxx_brd_tbl[spec->board_config]); | 4893 | stac92hd83xxx_brd_tbl[spec->board_config]); |
4824 | if (err < 0) { | ||
4825 | stac92xx_free(codec); | ||
4826 | return err; | ||
4827 | } | ||
4828 | 4894 | ||
4829 | switch (codec->vendor_id) { | 4895 | switch (codec->vendor_id) { |
4830 | case 0x111d7604: | 4896 | case 0x111d7604: |
@@ -4851,6 +4917,23 @@ again: | |||
4851 | return err; | 4917 | return err; |
4852 | } | 4918 | } |
4853 | 4919 | ||
4920 | switch (spec->board_config) { | ||
4921 | case STAC_DELL_S14: | ||
4922 | nid = 0xf; | ||
4923 | break; | ||
4924 | default: | ||
4925 | nid = 0xe; | ||
4926 | break; | ||
4927 | } | ||
4928 | |||
4929 | num_dacs = snd_hda_get_connections(codec, nid, | ||
4930 | conn, STAC92HD83_DAC_COUNT + 1) - 1; | ||
4931 | |||
4932 | /* set port X to select the last DAC | ||
4933 | */ | ||
4934 | snd_hda_codec_write_cache(codec, nid, 0, | ||
4935 | AC_VERB_SET_CONNECT_SEL, num_dacs); | ||
4936 | |||
4854 | codec->patch_ops = stac92xx_patch_ops; | 4937 | codec->patch_ops = stac92xx_patch_ops; |
4855 | 4938 | ||
4856 | codec->proc_widget_hook = stac92hd_proc_hook; | 4939 | codec->proc_widget_hook = stac92hd_proc_hook; |
@@ -4858,7 +4941,16 @@ again: | |||
4858 | return 0; | 4941 | return 0; |
4859 | } | 4942 | } |
4860 | 4943 | ||
4861 | static struct hda_input_mux stac92hd71bxx_dmux = { | 4944 | static struct hda_input_mux stac92hd71bxx_dmux_nomixer = { |
4945 | .num_items = 3, | ||
4946 | .items = { | ||
4947 | { "Analog Inputs", 0x00 }, | ||
4948 | { "Digital Mic 1", 0x02 }, | ||
4949 | { "Digital Mic 2", 0x03 }, | ||
4950 | } | ||
4951 | }; | ||
4952 | |||
4953 | static struct hda_input_mux stac92hd71bxx_dmux_amixer = { | ||
4862 | .num_items = 4, | 4954 | .num_items = 4, |
4863 | .items = { | 4955 | .items = { |
4864 | { "Analog Inputs", 0x00 }, | 4956 | { "Analog Inputs", 0x00 }, |
@@ -4868,10 +4960,67 @@ static struct hda_input_mux stac92hd71bxx_dmux = { | |||
4868 | } | 4960 | } |
4869 | }; | 4961 | }; |
4870 | 4962 | ||
4963 | /* get the pin connection (fixed, none, etc) */ | ||
4964 | static unsigned int stac_get_defcfg_connect(struct hda_codec *codec, int idx) | ||
4965 | { | ||
4966 | struct sigmatel_spec *spec = codec->spec; | ||
4967 | unsigned int cfg; | ||
4968 | |||
4969 | cfg = snd_hda_codec_get_pincfg(codec, spec->pin_nids[idx]); | ||
4970 | return get_defcfg_connect(cfg); | ||
4971 | } | ||
4972 | |||
4973 | static int stac92hd71bxx_connected_ports(struct hda_codec *codec, | ||
4974 | hda_nid_t *nids, int num_nids) | ||
4975 | { | ||
4976 | struct sigmatel_spec *spec = codec->spec; | ||
4977 | int idx, num; | ||
4978 | unsigned int def_conf; | ||
4979 | |||
4980 | for (num = 0; num < num_nids; num++) { | ||
4981 | for (idx = 0; idx < spec->num_pins; idx++) | ||
4982 | if (spec->pin_nids[idx] == nids[num]) | ||
4983 | break; | ||
4984 | if (idx >= spec->num_pins) | ||
4985 | break; | ||
4986 | def_conf = stac_get_defcfg_connect(codec, idx); | ||
4987 | if (def_conf == AC_JACK_PORT_NONE) | ||
4988 | break; | ||
4989 | } | ||
4990 | return num; | ||
4991 | } | ||
4992 | |||
4993 | static int stac92hd71bxx_connected_smuxes(struct hda_codec *codec, | ||
4994 | hda_nid_t dig0pin) | ||
4995 | { | ||
4996 | struct sigmatel_spec *spec = codec->spec; | ||
4997 | int idx; | ||
4998 | |||
4999 | for (idx = 0; idx < spec->num_pins; idx++) | ||
5000 | if (spec->pin_nids[idx] == dig0pin) | ||
5001 | break; | ||
5002 | if ((idx + 2) >= spec->num_pins) | ||
5003 | return 0; | ||
5004 | |||
5005 | /* dig1pin case */ | ||
5006 | if (stac_get_defcfg_connect(codec, idx + 1) != AC_JACK_PORT_NONE) | ||
5007 | return 2; | ||
5008 | |||
5009 | /* dig0pin + dig2pin case */ | ||
5010 | if (stac_get_defcfg_connect(codec, idx + 2) != AC_JACK_PORT_NONE) | ||
5011 | return 2; | ||
5012 | if (stac_get_defcfg_connect(codec, idx) != AC_JACK_PORT_NONE) | ||
5013 | return 1; | ||
5014 | else | ||
5015 | return 0; | ||
5016 | } | ||
5017 | |||
4871 | static int patch_stac92hd71bxx(struct hda_codec *codec) | 5018 | static int patch_stac92hd71bxx(struct hda_codec *codec) |
4872 | { | 5019 | { |
4873 | struct sigmatel_spec *spec; | 5020 | struct sigmatel_spec *spec; |
5021 | struct hda_verb *unmute_init = stac92hd71bxx_unmute_core_init; | ||
4874 | int err = 0; | 5022 | int err = 0; |
5023 | unsigned int ndmic_nids = 0; | ||
4875 | 5024 | ||
4876 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 5025 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
4877 | if (spec == NULL) | 5026 | if (spec == NULL) |
@@ -4879,27 +5028,32 @@ static int patch_stac92hd71bxx(struct hda_codec *codec) | |||
4879 | 5028 | ||
4880 | codec->spec = spec; | 5029 | codec->spec = spec; |
4881 | codec->patch_ops = stac92xx_patch_ops; | 5030 | codec->patch_ops = stac92xx_patch_ops; |
4882 | spec->num_pins = ARRAY_SIZE(stac92hd71bxx_pin_nids); | 5031 | spec->num_pins = STAC92HD71BXX_NUM_PINS; |
5032 | switch (codec->vendor_id) { | ||
5033 | case 0x111d76b6: | ||
5034 | case 0x111d76b7: | ||
5035 | spec->pin_nids = stac92hd71bxx_pin_nids_4port; | ||
5036 | break; | ||
5037 | case 0x111d7603: | ||
5038 | case 0x111d7608: | ||
5039 | /* On 92HD75Bx 0x27 isn't a pin nid */ | ||
5040 | spec->num_pins--; | ||
5041 | /* fallthrough */ | ||
5042 | default: | ||
5043 | spec->pin_nids = stac92hd71bxx_pin_nids_6port; | ||
5044 | } | ||
4883 | spec->num_pwrs = ARRAY_SIZE(stac92hd71bxx_pwr_nids); | 5045 | spec->num_pwrs = ARRAY_SIZE(stac92hd71bxx_pwr_nids); |
4884 | spec->pin_nids = stac92hd71bxx_pin_nids; | ||
4885 | memcpy(&spec->private_dimux, &stac92hd71bxx_dmux, | ||
4886 | sizeof(stac92hd71bxx_dmux)); | ||
4887 | spec->board_config = snd_hda_check_board_config(codec, | 5046 | spec->board_config = snd_hda_check_board_config(codec, |
4888 | STAC_92HD71BXX_MODELS, | 5047 | STAC_92HD71BXX_MODELS, |
4889 | stac92hd71bxx_models, | 5048 | stac92hd71bxx_models, |
4890 | stac92hd71bxx_cfg_tbl); | 5049 | stac92hd71bxx_cfg_tbl); |
4891 | again: | 5050 | again: |
4892 | if (spec->board_config < 0) { | 5051 | if (spec->board_config < 0) |
4893 | snd_printdd(KERN_INFO "hda_codec: Unknown model for" | 5052 | snd_printdd(KERN_INFO "hda_codec: Unknown model for" |
4894 | " STAC92HD71BXX, using BIOS defaults\n"); | 5053 | " STAC92HD71BXX, using BIOS defaults\n"); |
4895 | err = stac92xx_save_bios_config_regs(codec); | 5054 | else |
4896 | } else | 5055 | stac92xx_set_config_regs(codec, |
4897 | err = stac_save_pin_cfgs(codec, | ||
4898 | stac92hd71bxx_brd_tbl[spec->board_config]); | 5056 | stac92hd71bxx_brd_tbl[spec->board_config]); |
4899 | if (err < 0) { | ||
4900 | stac92xx_free(codec); | ||
4901 | return err; | ||
4902 | } | ||
4903 | 5057 | ||
4904 | if (spec->board_config > STAC_92HD71BXX_REF) { | 5058 | if (spec->board_config > STAC_92HD71BXX_REF) { |
4905 | /* GPIO0 = EAPD */ | 5059 | /* GPIO0 = EAPD */ |
@@ -4908,16 +5062,34 @@ again: | |||
4908 | spec->gpio_data = 0x01; | 5062 | spec->gpio_data = 0x01; |
4909 | } | 5063 | } |
4910 | 5064 | ||
5065 | spec->dmic_nids = stac92hd71bxx_dmic_nids; | ||
5066 | spec->dmux_nids = stac92hd71bxx_dmux_nids; | ||
5067 | |||
4911 | switch (codec->vendor_id) { | 5068 | switch (codec->vendor_id) { |
4912 | case 0x111d76b6: /* 4 Port without Analog Mixer */ | 5069 | case 0x111d76b6: /* 4 Port without Analog Mixer */ |
4913 | case 0x111d76b7: | 5070 | case 0x111d76b7: |
5071 | unmute_init++; | ||
5072 | /* fallthru */ | ||
4914 | case 0x111d76b4: /* 6 Port without Analog Mixer */ | 5073 | case 0x111d76b4: /* 6 Port without Analog Mixer */ |
4915 | case 0x111d76b5: | 5074 | case 0x111d76b5: |
5075 | memcpy(&spec->private_dimux, &stac92hd71bxx_dmux_nomixer, | ||
5076 | sizeof(stac92hd71bxx_dmux_nomixer)); | ||
4916 | spec->mixer = stac92hd71bxx_mixer; | 5077 | spec->mixer = stac92hd71bxx_mixer; |
4917 | spec->init = stac92hd71bxx_core_init; | 5078 | spec->init = stac92hd71bxx_core_init; |
4918 | codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; | 5079 | codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; |
5080 | spec->num_dmics = stac92hd71bxx_connected_ports(codec, | ||
5081 | stac92hd71bxx_dmic_nids, | ||
5082 | STAC92HD71BXX_NUM_DMICS); | ||
5083 | if (spec->num_dmics) { | ||
5084 | spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids); | ||
5085 | spec->dinput_mux = &spec->private_dimux; | ||
5086 | ndmic_nids = ARRAY_SIZE(stac92hd71bxx_dmic_nids) - 1; | ||
5087 | } | ||
4919 | break; | 5088 | break; |
4920 | case 0x111d7608: /* 5 Port with Analog Mixer */ | 5089 | case 0x111d7608: /* 5 Port with Analog Mixer */ |
5090 | memcpy(&spec->private_dimux, &stac92hd71bxx_dmux_amixer, | ||
5091 | sizeof(stac92hd71bxx_dmux_amixer)); | ||
5092 | spec->private_dimux.num_items--; | ||
4921 | switch (spec->board_config) { | 5093 | switch (spec->board_config) { |
4922 | case STAC_HP_M4: | 5094 | case STAC_HP_M4: |
4923 | /* Enable VREF power saving on GPIO1 detect */ | 5095 | /* Enable VREF power saving on GPIO1 detect */ |
@@ -4944,7 +5116,15 @@ again: | |||
4944 | 5116 | ||
4945 | /* disable VSW */ | 5117 | /* disable VSW */ |
4946 | spec->init = &stac92hd71bxx_analog_core_init[HD_DISABLE_PORTF]; | 5118 | spec->init = &stac92hd71bxx_analog_core_init[HD_DISABLE_PORTF]; |
4947 | stac_change_pin_config(codec, 0xf, 0x40f000f0); | 5119 | unmute_init++; |
5120 | snd_hda_codec_set_pincfg(codec, 0x0f, 0x40f000f0); | ||
5121 | snd_hda_codec_set_pincfg(codec, 0x19, 0x40f000f3); | ||
5122 | stac92hd71bxx_dmic_nids[STAC92HD71BXX_NUM_DMICS - 1] = 0; | ||
5123 | spec->num_dmics = stac92hd71bxx_connected_ports(codec, | ||
5124 | stac92hd71bxx_dmic_nids, | ||
5125 | STAC92HD71BXX_NUM_DMICS - 1); | ||
5126 | spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids); | ||
5127 | ndmic_nids = ARRAY_SIZE(stac92hd71bxx_dmic_nids) - 2; | ||
4948 | break; | 5128 | break; |
4949 | case 0x111d7603: /* 6 Port with Analog Mixer */ | 5129 | case 0x111d7603: /* 6 Port with Analog Mixer */ |
4950 | if ((codec->revision_id & 0xf) == 1) | 5130 | if ((codec->revision_id & 0xf) == 1) |
@@ -4954,12 +5134,23 @@ again: | |||
4954 | spec->num_pwrs = 0; | 5134 | spec->num_pwrs = 0; |
4955 | /* fallthru */ | 5135 | /* fallthru */ |
4956 | default: | 5136 | default: |
5137 | memcpy(&spec->private_dimux, &stac92hd71bxx_dmux_amixer, | ||
5138 | sizeof(stac92hd71bxx_dmux_amixer)); | ||
4957 | spec->dinput_mux = &spec->private_dimux; | 5139 | spec->dinput_mux = &spec->private_dimux; |
4958 | spec->mixer = stac92hd71bxx_analog_mixer; | 5140 | spec->mixer = stac92hd71bxx_analog_mixer; |
4959 | spec->init = stac92hd71bxx_analog_core_init; | 5141 | spec->init = stac92hd71bxx_analog_core_init; |
4960 | codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; | 5142 | codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; |
5143 | spec->num_dmics = stac92hd71bxx_connected_ports(codec, | ||
5144 | stac92hd71bxx_dmic_nids, | ||
5145 | STAC92HD71BXX_NUM_DMICS); | ||
5146 | spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids); | ||
5147 | ndmic_nids = ARRAY_SIZE(stac92hd71bxx_dmic_nids) - 1; | ||
4961 | } | 5148 | } |
4962 | 5149 | ||
5150 | if (get_wcaps(codec, 0xa) & AC_WCAP_IN_AMP) | ||
5151 | snd_hda_sequence_write_cache(codec, unmute_init); | ||
5152 | |||
5153 | spec->aloopback_ctl = stac92hd71bxx_loopback; | ||
4963 | spec->aloopback_mask = 0x50; | 5154 | spec->aloopback_mask = 0x50; |
4964 | spec->aloopback_shift = 0; | 5155 | spec->aloopback_shift = 0; |
4965 | 5156 | ||
@@ -4967,18 +5158,17 @@ again: | |||
4967 | spec->digbeep_nid = 0x26; | 5158 | spec->digbeep_nid = 0x26; |
4968 | spec->mux_nids = stac92hd71bxx_mux_nids; | 5159 | spec->mux_nids = stac92hd71bxx_mux_nids; |
4969 | spec->adc_nids = stac92hd71bxx_adc_nids; | 5160 | spec->adc_nids = stac92hd71bxx_adc_nids; |
4970 | spec->dmic_nids = stac92hd71bxx_dmic_nids; | ||
4971 | spec->dmux_nids = stac92hd71bxx_dmux_nids; | ||
4972 | spec->smux_nids = stac92hd71bxx_smux_nids; | 5161 | spec->smux_nids = stac92hd71bxx_smux_nids; |
4973 | spec->pwr_nids = stac92hd71bxx_pwr_nids; | 5162 | spec->pwr_nids = stac92hd71bxx_pwr_nids; |
4974 | 5163 | ||
4975 | spec->num_muxes = ARRAY_SIZE(stac92hd71bxx_mux_nids); | 5164 | spec->num_muxes = ARRAY_SIZE(stac92hd71bxx_mux_nids); |
4976 | spec->num_adcs = ARRAY_SIZE(stac92hd71bxx_adc_nids); | 5165 | spec->num_adcs = ARRAY_SIZE(stac92hd71bxx_adc_nids); |
5166 | spec->num_smuxes = stac92hd71bxx_connected_smuxes(codec, 0x1e); | ||
4977 | 5167 | ||
4978 | switch (spec->board_config) { | 5168 | switch (spec->board_config) { |
4979 | case STAC_HP_M4: | 5169 | case STAC_HP_M4: |
4980 | /* enable internal microphone */ | 5170 | /* enable internal microphone */ |
4981 | stac_change_pin_config(codec, 0x0e, 0x01813040); | 5171 | snd_hda_codec_set_pincfg(codec, 0x0e, 0x01813040); |
4982 | stac92xx_auto_set_pinctl(codec, 0x0e, | 5172 | stac92xx_auto_set_pinctl(codec, 0x0e, |
4983 | AC_PINCTL_IN_EN | AC_PINCTL_VREF_80); | 5173 | AC_PINCTL_IN_EN | AC_PINCTL_VREF_80); |
4984 | /* fallthru */ | 5174 | /* fallthru */ |
@@ -4993,19 +5183,36 @@ again: | |||
4993 | spec->num_smuxes = 0; | 5183 | spec->num_smuxes = 0; |
4994 | spec->num_dmuxes = 1; | 5184 | spec->num_dmuxes = 1; |
4995 | break; | 5185 | break; |
4996 | default: | 5186 | case STAC_HP_DV5: |
4997 | spec->num_dmics = STAC92HD71BXX_NUM_DMICS; | 5187 | snd_hda_codec_set_pincfg(codec, 0x0d, 0x90170010); |
4998 | spec->num_smuxes = ARRAY_SIZE(stac92hd71bxx_smux_nids); | 5188 | stac92xx_auto_set_pinctl(codec, 0x0d, AC_PINCTL_OUT_EN); |
4999 | spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids); | 5189 | break; |
5190 | case STAC_HP_HDX: | ||
5191 | spec->num_dmics = 1; | ||
5192 | spec->num_dmuxes = 1; | ||
5193 | spec->num_smuxes = 1; | ||
5194 | /* | ||
5195 | * For controlling MUTE LED on HP HDX16/HDX18 notebooks, | ||
5196 | * the CONFIG_SND_HDA_POWER_SAVE is needed to be set. | ||
5197 | */ | ||
5198 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
5199 | /* orange/white mute led on GPIO3, orange=0, white=1 */ | ||
5200 | spec->gpio_mask |= 0x08; | ||
5201 | spec->gpio_dir |= 0x08; | ||
5202 | spec->gpio_data |= 0x08; /* set to white */ | ||
5203 | |||
5204 | /* register check_power_status callback. */ | ||
5205 | codec->patch_ops.check_power_status = | ||
5206 | stac92xx_hp_hdx_check_power_status; | ||
5207 | #endif | ||
5208 | break; | ||
5000 | }; | 5209 | }; |
5001 | 5210 | ||
5002 | spec->multiout.dac_nids = spec->dac_nids; | 5211 | spec->multiout.dac_nids = spec->dac_nids; |
5003 | if (spec->dinput_mux) | 5212 | if (spec->dinput_mux) |
5004 | spec->private_dimux.num_items += | 5213 | spec->private_dimux.num_items += spec->num_dmics - ndmic_nids; |
5005 | spec->num_dmics - | ||
5006 | (ARRAY_SIZE(stac92hd71bxx_dmic_nids) - 1); | ||
5007 | 5214 | ||
5008 | err = stac92xx_parse_auto_config(codec, 0x21, 0x23); | 5215 | err = stac92xx_parse_auto_config(codec, 0x21, 0); |
5009 | if (!err) { | 5216 | if (!err) { |
5010 | if (spec->board_config < 0) { | 5217 | if (spec->board_config < 0) { |
5011 | printk(KERN_WARNING "hda_codec: No auto-config is " | 5218 | printk(KERN_WARNING "hda_codec: No auto-config is " |
@@ -5080,17 +5287,12 @@ static int patch_stac922x(struct hda_codec *codec) | |||
5080 | } | 5287 | } |
5081 | 5288 | ||
5082 | again: | 5289 | again: |
5083 | if (spec->board_config < 0) { | 5290 | if (spec->board_config < 0) |
5084 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, " | 5291 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, " |
5085 | "using BIOS defaults\n"); | 5292 | "using BIOS defaults\n"); |
5086 | err = stac92xx_save_bios_config_regs(codec); | 5293 | else |
5087 | } else | 5294 | stac92xx_set_config_regs(codec, |
5088 | err = stac_save_pin_cfgs(codec, | ||
5089 | stac922x_brd_tbl[spec->board_config]); | 5295 | stac922x_brd_tbl[spec->board_config]); |
5090 | if (err < 0) { | ||
5091 | stac92xx_free(codec); | ||
5092 | return err; | ||
5093 | } | ||
5094 | 5296 | ||
5095 | spec->adc_nids = stac922x_adc_nids; | 5297 | spec->adc_nids = stac922x_adc_nids; |
5096 | spec->mux_nids = stac922x_mux_nids; | 5298 | spec->mux_nids = stac922x_mux_nids; |
@@ -5141,24 +5343,19 @@ static int patch_stac927x(struct hda_codec *codec) | |||
5141 | return -ENOMEM; | 5343 | return -ENOMEM; |
5142 | 5344 | ||
5143 | codec->spec = spec; | 5345 | codec->spec = spec; |
5346 | codec->slave_dig_outs = stac927x_slave_dig_outs; | ||
5144 | spec->num_pins = ARRAY_SIZE(stac927x_pin_nids); | 5347 | spec->num_pins = ARRAY_SIZE(stac927x_pin_nids); |
5145 | spec->pin_nids = stac927x_pin_nids; | 5348 | spec->pin_nids = stac927x_pin_nids; |
5146 | spec->board_config = snd_hda_check_board_config(codec, STAC_927X_MODELS, | 5349 | spec->board_config = snd_hda_check_board_config(codec, STAC_927X_MODELS, |
5147 | stac927x_models, | 5350 | stac927x_models, |
5148 | stac927x_cfg_tbl); | 5351 | stac927x_cfg_tbl); |
5149 | again: | 5352 | again: |
5150 | if (spec->board_config < 0 || !stac927x_brd_tbl[spec->board_config]) { | 5353 | if (spec->board_config < 0) |
5151 | if (spec->board_config < 0) | 5354 | snd_printdd(KERN_INFO "hda_codec: Unknown model for" |
5152 | snd_printdd(KERN_INFO "hda_codec: Unknown model for" | 5355 | "STAC927x, using BIOS defaults\n"); |
5153 | "STAC927x, using BIOS defaults\n"); | 5356 | else |
5154 | err = stac92xx_save_bios_config_regs(codec); | 5357 | stac92xx_set_config_regs(codec, |
5155 | } else | ||
5156 | err = stac_save_pin_cfgs(codec, | ||
5157 | stac927x_brd_tbl[spec->board_config]); | 5358 | stac927x_brd_tbl[spec->board_config]); |
5158 | if (err < 0) { | ||
5159 | stac92xx_free(codec); | ||
5160 | return err; | ||
5161 | } | ||
5162 | 5359 | ||
5163 | spec->digbeep_nid = 0x23; | 5360 | spec->digbeep_nid = 0x23; |
5164 | spec->adc_nids = stac927x_adc_nids; | 5361 | spec->adc_nids = stac927x_adc_nids; |
@@ -5187,15 +5384,15 @@ static int patch_stac927x(struct hda_codec *codec) | |||
5187 | case 0x10280209: | 5384 | case 0x10280209: |
5188 | case 0x1028022e: | 5385 | case 0x1028022e: |
5189 | /* correct the device field to SPDIF out */ | 5386 | /* correct the device field to SPDIF out */ |
5190 | stac_change_pin_config(codec, 0x21, 0x01442070); | 5387 | snd_hda_codec_set_pincfg(codec, 0x21, 0x01442070); |
5191 | break; | 5388 | break; |
5192 | }; | 5389 | }; |
5193 | /* configure the analog microphone on some laptops */ | 5390 | /* configure the analog microphone on some laptops */ |
5194 | stac_change_pin_config(codec, 0x0c, 0x90a79130); | 5391 | snd_hda_codec_set_pincfg(codec, 0x0c, 0x90a79130); |
5195 | /* correct the front output jack as a hp out */ | 5392 | /* correct the front output jack as a hp out */ |
5196 | stac_change_pin_config(codec, 0x0f, 0x0227011f); | 5393 | snd_hda_codec_set_pincfg(codec, 0x0f, 0x0227011f); |
5197 | /* correct the front input jack as a mic */ | 5394 | /* correct the front input jack as a mic */ |
5198 | stac_change_pin_config(codec, 0x0e, 0x02a79130); | 5395 | snd_hda_codec_set_pincfg(codec, 0x0e, 0x02a79130); |
5199 | /* fallthru */ | 5396 | /* fallthru */ |
5200 | case STAC_DELL_3ST: | 5397 | case STAC_DELL_3ST: |
5201 | /* GPIO2 High = Enable EAPD */ | 5398 | /* GPIO2 High = Enable EAPD */ |
@@ -5222,6 +5419,7 @@ static int patch_stac927x(struct hda_codec *codec) | |||
5222 | } | 5419 | } |
5223 | 5420 | ||
5224 | spec->num_pwrs = 0; | 5421 | spec->num_pwrs = 0; |
5422 | spec->aloopback_ctl = stac927x_loopback; | ||
5225 | spec->aloopback_mask = 0x40; | 5423 | spec->aloopback_mask = 0x40; |
5226 | spec->aloopback_shift = 0; | 5424 | spec->aloopback_shift = 0; |
5227 | spec->eapd_switch = 1; | 5425 | spec->eapd_switch = 1; |
@@ -5280,16 +5478,11 @@ static int patch_stac9205(struct hda_codec *codec) | |||
5280 | stac9205_models, | 5478 | stac9205_models, |
5281 | stac9205_cfg_tbl); | 5479 | stac9205_cfg_tbl); |
5282 | again: | 5480 | again: |
5283 | if (spec->board_config < 0) { | 5481 | if (spec->board_config < 0) |
5284 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9205, using BIOS defaults\n"); | 5482 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9205, using BIOS defaults\n"); |
5285 | err = stac92xx_save_bios_config_regs(codec); | 5483 | else |
5286 | } else | 5484 | stac92xx_set_config_regs(codec, |
5287 | err = stac_save_pin_cfgs(codec, | ||
5288 | stac9205_brd_tbl[spec->board_config]); | 5485 | stac9205_brd_tbl[spec->board_config]); |
5289 | if (err < 0) { | ||
5290 | stac92xx_free(codec); | ||
5291 | return err; | ||
5292 | } | ||
5293 | 5486 | ||
5294 | spec->digbeep_nid = 0x23; | 5487 | spec->digbeep_nid = 0x23; |
5295 | spec->adc_nids = stac9205_adc_nids; | 5488 | spec->adc_nids = stac9205_adc_nids; |
@@ -5306,17 +5499,20 @@ static int patch_stac9205(struct hda_codec *codec) | |||
5306 | 5499 | ||
5307 | spec->init = stac9205_core_init; | 5500 | spec->init = stac9205_core_init; |
5308 | spec->mixer = stac9205_mixer; | 5501 | spec->mixer = stac9205_mixer; |
5502 | spec->aloopback_ctl = stac9205_loopback; | ||
5309 | 5503 | ||
5310 | spec->aloopback_mask = 0x40; | 5504 | spec->aloopback_mask = 0x40; |
5311 | spec->aloopback_shift = 0; | 5505 | spec->aloopback_shift = 0; |
5312 | spec->eapd_switch = 1; | 5506 | /* Turn on/off EAPD per HP plugging */ |
5507 | if (spec->board_config != STAC_9205_EAPD) | ||
5508 | spec->eapd_switch = 1; | ||
5313 | spec->multiout.dac_nids = spec->dac_nids; | 5509 | spec->multiout.dac_nids = spec->dac_nids; |
5314 | 5510 | ||
5315 | switch (spec->board_config){ | 5511 | switch (spec->board_config){ |
5316 | case STAC_9205_DELL_M43: | 5512 | case STAC_9205_DELL_M43: |
5317 | /* Enable SPDIF in/out */ | 5513 | /* Enable SPDIF in/out */ |
5318 | stac_change_pin_config(codec, 0x1f, 0x01441030); | 5514 | snd_hda_codec_set_pincfg(codec, 0x1f, 0x01441030); |
5319 | stac_change_pin_config(codec, 0x20, 0x1c410030); | 5515 | snd_hda_codec_set_pincfg(codec, 0x20, 0x1c410030); |
5320 | 5516 | ||
5321 | /* Enable unsol response for GPIO4/Dock HP connection */ | 5517 | /* Enable unsol response for GPIO4/Dock HP connection */ |
5322 | err = stac_add_event(spec, codec->afg, STAC_VREF_EVENT, 0x01); | 5518 | err = stac_add_event(spec, codec->afg, STAC_VREF_EVENT, 0x01); |
@@ -5373,223 +5569,87 @@ static int patch_stac9205(struct hda_codec *codec) | |||
5373 | * STAC9872 hack | 5569 | * STAC9872 hack |
5374 | */ | 5570 | */ |
5375 | 5571 | ||
5376 | /* static config for Sony VAIO FE550G and Sony VAIO AR */ | 5572 | static struct hda_verb stac9872_core_init[] = { |
5377 | static hda_nid_t vaio_dacs[] = { 0x2 }; | ||
5378 | #define VAIO_HP_DAC 0x5 | ||
5379 | static hda_nid_t vaio_adcs[] = { 0x8 /*,0x6*/ }; | ||
5380 | static hda_nid_t vaio_mux_nids[] = { 0x15 }; | ||
5381 | |||
5382 | static struct hda_input_mux vaio_mux = { | ||
5383 | .num_items = 3, | ||
5384 | .items = { | ||
5385 | /* { "HP", 0x0 }, */ | ||
5386 | { "Mic Jack", 0x1 }, | ||
5387 | { "Internal Mic", 0x2 }, | ||
5388 | { "PCM", 0x3 }, | ||
5389 | } | ||
5390 | }; | ||
5391 | |||
5392 | static struct hda_verb vaio_init[] = { | ||
5393 | {0x0a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP <- 0x2 */ | ||
5394 | {0x0a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | STAC_HP_EVENT}, | ||
5395 | {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Speaker <- 0x5 */ | ||
5396 | {0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? (<- 0x2) */ | ||
5397 | {0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD */ | ||
5398 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? */ | ||
5399 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mic-sel: 0a,0d,14,02 */ | 5573 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mic-sel: 0a,0d,14,02 */ |
5400 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* HP */ | ||
5401 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Speaker */ | ||
5402 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* capture sw/vol -> 0x8 */ | ||
5403 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* CD-in -> 0x6 */ | ||
5404 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Mic-in -> 0x9 */ | 5574 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Mic-in -> 0x9 */ |
5405 | {} | 5575 | {} |
5406 | }; | 5576 | }; |
5407 | 5577 | ||
5408 | static struct hda_verb vaio_ar_init[] = { | 5578 | static struct snd_kcontrol_new stac9872_mixer[] = { |
5409 | {0x0a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP <- 0x2 */ | ||
5410 | {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Speaker <- 0x5 */ | ||
5411 | {0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? (<- 0x2) */ | ||
5412 | {0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD */ | ||
5413 | /* {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },*/ /* Optical Out */ | ||
5414 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? */ | ||
5415 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mic-sel: 0a,0d,14,02 */ | ||
5416 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* HP */ | ||
5417 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Speaker */ | ||
5418 | /* {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},*/ /* Optical Out */ | ||
5419 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* capture sw/vol -> 0x8 */ | ||
5420 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* CD-in -> 0x6 */ | ||
5421 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Mic-in -> 0x9 */ | ||
5422 | {} | ||
5423 | }; | ||
5424 | |||
5425 | static struct snd_kcontrol_new vaio_mixer[] = { | ||
5426 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x02, 0, HDA_OUTPUT), | ||
5427 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x02, 0, HDA_OUTPUT), | ||
5428 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x05, 0, HDA_OUTPUT), | ||
5429 | HDA_CODEC_MUTE("Speaker Playback Switch", 0x05, 0, HDA_OUTPUT), | ||
5430 | /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */ | ||
5431 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), | 5579 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), |
5432 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), | 5580 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), |
5433 | { | 5581 | { } /* end */ |
5434 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
5435 | .name = "Capture Source", | ||
5436 | .count = 1, | ||
5437 | .info = stac92xx_mux_enum_info, | ||
5438 | .get = stac92xx_mux_enum_get, | ||
5439 | .put = stac92xx_mux_enum_put, | ||
5440 | }, | ||
5441 | {} | ||
5442 | }; | 5582 | }; |
5443 | 5583 | ||
5444 | static struct snd_kcontrol_new vaio_ar_mixer[] = { | 5584 | static hda_nid_t stac9872_pin_nids[] = { |
5445 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x02, 0, HDA_OUTPUT), | 5585 | 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, |
5446 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x02, 0, HDA_OUTPUT), | 5586 | 0x11, 0x13, 0x14, |
5447 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x05, 0, HDA_OUTPUT), | ||
5448 | HDA_CODEC_MUTE("Speaker Playback Switch", 0x05, 0, HDA_OUTPUT), | ||
5449 | /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */ | ||
5450 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), | ||
5451 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), | ||
5452 | /*HDA_CODEC_MUTE("Optical Out Switch", 0x10, 0, HDA_OUTPUT), | ||
5453 | HDA_CODEC_VOLUME("Optical Out Volume", 0x10, 0, HDA_OUTPUT),*/ | ||
5454 | { | ||
5455 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
5456 | .name = "Capture Source", | ||
5457 | .count = 1, | ||
5458 | .info = stac92xx_mux_enum_info, | ||
5459 | .get = stac92xx_mux_enum_get, | ||
5460 | .put = stac92xx_mux_enum_put, | ||
5461 | }, | ||
5462 | {} | ||
5463 | }; | 5587 | }; |
5464 | 5588 | ||
5465 | static struct hda_codec_ops stac9872_patch_ops = { | 5589 | static hda_nid_t stac9872_adc_nids[] = { |
5466 | .build_controls = stac92xx_build_controls, | 5590 | 0x8 /*,0x6*/ |
5467 | .build_pcms = stac92xx_build_pcms, | ||
5468 | .init = stac92xx_init, | ||
5469 | .free = stac92xx_free, | ||
5470 | #ifdef SND_HDA_NEEDS_RESUME | ||
5471 | .resume = stac92xx_resume, | ||
5472 | #endif | ||
5473 | }; | 5591 | }; |
5474 | 5592 | ||
5475 | static int stac9872_vaio_init(struct hda_codec *codec) | 5593 | static hda_nid_t stac9872_mux_nids[] = { |
5476 | { | 5594 | 0x15 |
5477 | int err; | ||
5478 | |||
5479 | err = stac92xx_init(codec); | ||
5480 | if (err < 0) | ||
5481 | return err; | ||
5482 | if (codec->patch_ops.unsol_event) | ||
5483 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); | ||
5484 | return 0; | ||
5485 | } | ||
5486 | |||
5487 | static void stac9872_vaio_hp_detect(struct hda_codec *codec, unsigned int res) | ||
5488 | { | ||
5489 | if (get_pin_presence(codec, 0x0a)) { | ||
5490 | stac92xx_reset_pinctl(codec, 0x0f, AC_PINCTL_OUT_EN); | ||
5491 | stac92xx_set_pinctl(codec, 0x0a, AC_PINCTL_OUT_EN); | ||
5492 | } else { | ||
5493 | stac92xx_reset_pinctl(codec, 0x0a, AC_PINCTL_OUT_EN); | ||
5494 | stac92xx_set_pinctl(codec, 0x0f, AC_PINCTL_OUT_EN); | ||
5495 | } | ||
5496 | } | ||
5497 | |||
5498 | static void stac9872_vaio_unsol_event(struct hda_codec *codec, unsigned int res) | ||
5499 | { | ||
5500 | switch (res >> 26) { | ||
5501 | case STAC_HP_EVENT: | ||
5502 | stac9872_vaio_hp_detect(codec, res); | ||
5503 | break; | ||
5504 | } | ||
5505 | } | ||
5506 | |||
5507 | static struct hda_codec_ops stac9872_vaio_patch_ops = { | ||
5508 | .build_controls = stac92xx_build_controls, | ||
5509 | .build_pcms = stac92xx_build_pcms, | ||
5510 | .init = stac9872_vaio_init, | ||
5511 | .free = stac92xx_free, | ||
5512 | .unsol_event = stac9872_vaio_unsol_event, | ||
5513 | #ifdef CONFIG_PM | ||
5514 | .resume = stac92xx_resume, | ||
5515 | #endif | ||
5516 | }; | 5595 | }; |
5517 | 5596 | ||
5518 | enum { /* FE and SZ series. id=0x83847661 and subsys=0x104D0700 or 104D1000. */ | 5597 | static unsigned int stac9872_vaio_pin_configs[9] = { |
5519 | CXD9872RD_VAIO, | 5598 | 0x03211020, 0x411111f0, 0x411111f0, 0x03a15030, |
5520 | /* Unknown. id=0x83847662 and subsys=0x104D1200 or 104D1000. */ | 5599 | 0x411111f0, 0x90170110, 0x411111f0, 0x411111f0, |
5521 | STAC9872AK_VAIO, | 5600 | 0x90a7013e |
5522 | /* Unknown. id=0x83847661 and subsys=0x104D1200. */ | ||
5523 | STAC9872K_VAIO, | ||
5524 | /* AR Series. id=0x83847664 and subsys=104D1300 */ | ||
5525 | CXD9872AKD_VAIO, | ||
5526 | STAC_9872_MODELS, | ||
5527 | }; | 5601 | }; |
5528 | 5602 | ||
5529 | static const char *stac9872_models[STAC_9872_MODELS] = { | 5603 | static const char *stac9872_models[STAC_9872_MODELS] = { |
5530 | [CXD9872RD_VAIO] = "vaio", | 5604 | [STAC_9872_AUTO] = "auto", |
5531 | [CXD9872AKD_VAIO] = "vaio-ar", | 5605 | [STAC_9872_VAIO] = "vaio", |
5606 | }; | ||
5607 | |||
5608 | static unsigned int *stac9872_brd_tbl[STAC_9872_MODELS] = { | ||
5609 | [STAC_9872_VAIO] = stac9872_vaio_pin_configs, | ||
5532 | }; | 5610 | }; |
5533 | 5611 | ||
5534 | static struct snd_pci_quirk stac9872_cfg_tbl[] = { | 5612 | static struct snd_pci_quirk stac9872_cfg_tbl[] = { |
5535 | SND_PCI_QUIRK(0x104d, 0x81e6, "Sony VAIO F/S", CXD9872RD_VAIO), | 5613 | {} /* terminator */ |
5536 | SND_PCI_QUIRK(0x104d, 0x81ef, "Sony VAIO F/S", CXD9872RD_VAIO), | ||
5537 | SND_PCI_QUIRK(0x104d, 0x81fd, "Sony VAIO AR", CXD9872AKD_VAIO), | ||
5538 | SND_PCI_QUIRK(0x104d, 0x8205, "Sony VAIO AR", CXD9872AKD_VAIO), | ||
5539 | {} | ||
5540 | }; | 5614 | }; |
5541 | 5615 | ||
5542 | static int patch_stac9872(struct hda_codec *codec) | 5616 | static int patch_stac9872(struct hda_codec *codec) |
5543 | { | 5617 | { |
5544 | struct sigmatel_spec *spec; | 5618 | struct sigmatel_spec *spec; |
5545 | int board_config; | 5619 | int err; |
5546 | 5620 | ||
5547 | board_config = snd_hda_check_board_config(codec, STAC_9872_MODELS, | ||
5548 | stac9872_models, | ||
5549 | stac9872_cfg_tbl); | ||
5550 | if (board_config < 0) | ||
5551 | /* unknown config, let generic-parser do its job... */ | ||
5552 | return snd_hda_parse_generic_codec(codec); | ||
5553 | |||
5554 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 5621 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
5555 | if (spec == NULL) | 5622 | if (spec == NULL) |
5556 | return -ENOMEM; | 5623 | return -ENOMEM; |
5557 | |||
5558 | codec->spec = spec; | 5624 | codec->spec = spec; |
5559 | switch (board_config) { | ||
5560 | case CXD9872RD_VAIO: | ||
5561 | case STAC9872AK_VAIO: | ||
5562 | case STAC9872K_VAIO: | ||
5563 | spec->mixer = vaio_mixer; | ||
5564 | spec->init = vaio_init; | ||
5565 | spec->multiout.max_channels = 2; | ||
5566 | spec->multiout.num_dacs = ARRAY_SIZE(vaio_dacs); | ||
5567 | spec->multiout.dac_nids = vaio_dacs; | ||
5568 | spec->multiout.hp_nid = VAIO_HP_DAC; | ||
5569 | spec->num_adcs = ARRAY_SIZE(vaio_adcs); | ||
5570 | spec->adc_nids = vaio_adcs; | ||
5571 | spec->num_pwrs = 0; | ||
5572 | spec->input_mux = &vaio_mux; | ||
5573 | spec->mux_nids = vaio_mux_nids; | ||
5574 | codec->patch_ops = stac9872_vaio_patch_ops; | ||
5575 | break; | ||
5576 | |||
5577 | case CXD9872AKD_VAIO: | ||
5578 | spec->mixer = vaio_ar_mixer; | ||
5579 | spec->init = vaio_ar_init; | ||
5580 | spec->multiout.max_channels = 2; | ||
5581 | spec->multiout.num_dacs = ARRAY_SIZE(vaio_dacs); | ||
5582 | spec->multiout.dac_nids = vaio_dacs; | ||
5583 | spec->multiout.hp_nid = VAIO_HP_DAC; | ||
5584 | spec->num_adcs = ARRAY_SIZE(vaio_adcs); | ||
5585 | spec->num_pwrs = 0; | ||
5586 | spec->adc_nids = vaio_adcs; | ||
5587 | spec->input_mux = &vaio_mux; | ||
5588 | spec->mux_nids = vaio_mux_nids; | ||
5589 | codec->patch_ops = stac9872_patch_ops; | ||
5590 | break; | ||
5591 | } | ||
5592 | 5625 | ||
5626 | spec->board_config = snd_hda_check_board_config(codec, STAC_9872_MODELS, | ||
5627 | stac9872_models, | ||
5628 | stac9872_cfg_tbl); | ||
5629 | if (spec->board_config < 0) | ||
5630 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9872, " | ||
5631 | "using BIOS defaults\n"); | ||
5632 | else | ||
5633 | stac92xx_set_config_regs(codec, | ||
5634 | stac9872_brd_tbl[spec->board_config]); | ||
5635 | |||
5636 | spec->num_pins = ARRAY_SIZE(stac9872_pin_nids); | ||
5637 | spec->pin_nids = stac9872_pin_nids; | ||
5638 | spec->multiout.dac_nids = spec->dac_nids; | ||
5639 | spec->num_adcs = ARRAY_SIZE(stac9872_adc_nids); | ||
5640 | spec->adc_nids = stac9872_adc_nids; | ||
5641 | spec->num_muxes = ARRAY_SIZE(stac9872_mux_nids); | ||
5642 | spec->mux_nids = stac9872_mux_nids; | ||
5643 | spec->mixer = stac9872_mixer; | ||
5644 | spec->init = stac9872_core_init; | ||
5645 | |||
5646 | err = stac92xx_parse_auto_config(codec, 0x10, 0x12); | ||
5647 | if (err < 0) { | ||
5648 | stac92xx_free(codec); | ||
5649 | return -EINVAL; | ||
5650 | } | ||
5651 | spec->input_mux = &spec->private_imux; | ||
5652 | codec->patch_ops = stac92xx_patch_ops; | ||
5593 | return 0; | 5653 | return 0; |
5594 | } | 5654 | } |
5595 | 5655 | ||
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index c761394cbe84..b25a5cc637d6 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c | |||
@@ -1308,16 +1308,13 @@ static void vt1708_set_pinconfig_connect(struct hda_codec *codec, hda_nid_t nid) | |||
1308 | unsigned int def_conf; | 1308 | unsigned int def_conf; |
1309 | unsigned char seqassoc; | 1309 | unsigned char seqassoc; |
1310 | 1310 | ||
1311 | def_conf = snd_hda_codec_read(codec, nid, 0, | 1311 | def_conf = snd_hda_codec_get_pincfg(codec, nid); |
1312 | AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
1313 | seqassoc = (unsigned char) get_defcfg_association(def_conf); | 1312 | seqassoc = (unsigned char) get_defcfg_association(def_conf); |
1314 | seqassoc = (seqassoc << 4) | get_defcfg_sequence(def_conf); | 1313 | seqassoc = (seqassoc << 4) | get_defcfg_sequence(def_conf); |
1315 | if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE) { | 1314 | if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE) { |
1316 | if (seqassoc == 0xff) { | 1315 | if (seqassoc == 0xff) { |
1317 | def_conf = def_conf & (~(AC_JACK_PORT_BOTH << 30)); | 1316 | def_conf = def_conf & (~(AC_JACK_PORT_BOTH << 30)); |
1318 | snd_hda_codec_write(codec, nid, 0, | 1317 | snd_hda_codec_set_pincfg(codec, nid, def_conf); |
1319 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, | ||
1320 | def_conf >> 24); | ||
1321 | } | 1318 | } |
1322 | } | 1319 | } |
1323 | 1320 | ||
@@ -1354,7 +1351,7 @@ static int vt1708_parse_auto_config(struct hda_codec *codec) | |||
1354 | 1351 | ||
1355 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 1352 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
1356 | 1353 | ||
1357 | if (spec->autocfg.dig_out_pin) | 1354 | if (spec->autocfg.dig_outs) |
1358 | spec->multiout.dig_out_nid = VT1708_DIGOUT_NID; | 1355 | spec->multiout.dig_out_nid = VT1708_DIGOUT_NID; |
1359 | if (spec->autocfg.dig_in_pin) | 1356 | if (spec->autocfg.dig_in_pin) |
1360 | spec->dig_in_nid = VT1708_DIGIN_NID; | 1357 | spec->dig_in_nid = VT1708_DIGIN_NID; |
@@ -1827,7 +1824,7 @@ static int vt1709_parse_auto_config(struct hda_codec *codec) | |||
1827 | 1824 | ||
1828 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 1825 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
1829 | 1826 | ||
1830 | if (spec->autocfg.dig_out_pin) | 1827 | if (spec->autocfg.dig_outs) |
1831 | spec->multiout.dig_out_nid = VT1709_DIGOUT_NID; | 1828 | spec->multiout.dig_out_nid = VT1709_DIGOUT_NID; |
1832 | if (spec->autocfg.dig_in_pin) | 1829 | if (spec->autocfg.dig_in_pin) |
1833 | spec->dig_in_nid = VT1709_DIGIN_NID; | 1830 | spec->dig_in_nid = VT1709_DIGIN_NID; |
@@ -2371,7 +2368,7 @@ static int vt1708B_parse_auto_config(struct hda_codec *codec) | |||
2371 | 2368 | ||
2372 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 2369 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
2373 | 2370 | ||
2374 | if (spec->autocfg.dig_out_pin) | 2371 | if (spec->autocfg.dig_outs) |
2375 | spec->multiout.dig_out_nid = VT1708B_DIGOUT_NID; | 2372 | spec->multiout.dig_out_nid = VT1708B_DIGOUT_NID; |
2376 | if (spec->autocfg.dig_in_pin) | 2373 | if (spec->autocfg.dig_in_pin) |
2377 | spec->dig_in_nid = VT1708B_DIGIN_NID; | 2374 | spec->dig_in_nid = VT1708B_DIGIN_NID; |
@@ -2836,7 +2833,7 @@ static int vt1708S_parse_auto_config(struct hda_codec *codec) | |||
2836 | 2833 | ||
2837 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 2834 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
2838 | 2835 | ||
2839 | if (spec->autocfg.dig_out_pin) | 2836 | if (spec->autocfg.dig_outs) |
2840 | spec->multiout.dig_out_nid = VT1708S_DIGOUT_NID; | 2837 | spec->multiout.dig_out_nid = VT1708S_DIGOUT_NID; |
2841 | 2838 | ||
2842 | spec->extra_dig_out_nid = 0x15; | 2839 | spec->extra_dig_out_nid = 0x15; |
@@ -3155,7 +3152,7 @@ static int vt1702_parse_auto_config(struct hda_codec *codec) | |||
3155 | 3152 | ||
3156 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 3153 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
3157 | 3154 | ||
3158 | if (spec->autocfg.dig_out_pin) | 3155 | if (spec->autocfg.dig_outs) |
3159 | spec->multiout.dig_out_nid = VT1702_DIGOUT_NID; | 3156 | spec->multiout.dig_out_nid = VT1702_DIGOUT_NID; |
3160 | 3157 | ||
3161 | spec->extra_dig_out_nid = 0x1B; | 3158 | spec->extra_dig_out_nid = 0x1B; |
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index 58d7cda03de5..3dd63f1cda53 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c | |||
@@ -458,7 +458,7 @@ static irqreturn_t snd_ice1712_interrupt(int irq, void *dev_id) | |||
458 | u16 pbkstatus; | 458 | u16 pbkstatus; |
459 | struct snd_pcm_substream *substream; | 459 | struct snd_pcm_substream *substream; |
460 | pbkstatus = inw(ICEDS(ice, INTSTAT)); | 460 | pbkstatus = inw(ICEDS(ice, INTSTAT)); |
461 | /* printk("pbkstatus = 0x%x\n", pbkstatus); */ | 461 | /* printk(KERN_DEBUG "pbkstatus = 0x%x\n", pbkstatus); */ |
462 | for (idx = 0; idx < 6; idx++) { | 462 | for (idx = 0; idx < 6; idx++) { |
463 | if ((pbkstatus & (3 << (idx * 2))) == 0) | 463 | if ((pbkstatus & (3 << (idx * 2))) == 0) |
464 | continue; | 464 | continue; |
@@ -2648,9 +2648,9 @@ static int __devinit snd_ice1712_probe(struct pci_dev *pci, | |||
2648 | return -ENOENT; | 2648 | return -ENOENT; |
2649 | } | 2649 | } |
2650 | 2650 | ||
2651 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 2651 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); |
2652 | if (card == NULL) | 2652 | if (err < 0) |
2653 | return -ENOMEM; | 2653 | return err; |
2654 | 2654 | ||
2655 | strcpy(card->driver, "ICE1712"); | 2655 | strcpy(card->driver, "ICE1712"); |
2656 | strcpy(card->shortname, "ICEnsemble ICE1712"); | 2656 | strcpy(card->shortname, "ICEnsemble ICE1712"); |
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index bb8d8c766b9d..128510e77a78 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c | |||
@@ -241,6 +241,8 @@ get_rawmidi_substream(struct snd_ice1712 *ice, unsigned int stream) | |||
241 | struct snd_rawmidi_substream, list); | 241 | struct snd_rawmidi_substream, list); |
242 | } | 242 | } |
243 | 243 | ||
244 | static void enable_midi_irq(struct snd_ice1712 *ice, u8 flag, int enable); | ||
245 | |||
244 | static void vt1724_midi_write(struct snd_ice1712 *ice) | 246 | static void vt1724_midi_write(struct snd_ice1712 *ice) |
245 | { | 247 | { |
246 | struct snd_rawmidi_substream *s; | 248 | struct snd_rawmidi_substream *s; |
@@ -254,6 +256,11 @@ static void vt1724_midi_write(struct snd_ice1712 *ice) | |||
254 | for (i = 0; i < count; ++i) | 256 | for (i = 0; i < count; ++i) |
255 | outb(buffer[i], ICEREG1724(ice, MPU_DATA)); | 257 | outb(buffer[i], ICEREG1724(ice, MPU_DATA)); |
256 | } | 258 | } |
259 | /* mask irq when all bytes have been transmitted. | ||
260 | * enabled again in output_trigger when the new data comes in. | ||
261 | */ | ||
262 | enable_midi_irq(ice, VT1724_IRQ_MPU_TX, | ||
263 | !snd_rawmidi_transmit_empty(s)); | ||
257 | } | 264 | } |
258 | 265 | ||
259 | static void vt1724_midi_read(struct snd_ice1712 *ice) | 266 | static void vt1724_midi_read(struct snd_ice1712 *ice) |
@@ -272,31 +279,34 @@ static void vt1724_midi_read(struct snd_ice1712 *ice) | |||
272 | } | 279 | } |
273 | } | 280 | } |
274 | 281 | ||
275 | static void vt1724_enable_midi_irq(struct snd_rawmidi_substream *substream, | 282 | /* call with ice->reg_lock */ |
276 | u8 flag, int enable) | 283 | static void enable_midi_irq(struct snd_ice1712 *ice, u8 flag, int enable) |
277 | { | 284 | { |
278 | struct snd_ice1712 *ice = substream->rmidi->private_data; | 285 | u8 mask = inb(ICEREG1724(ice, IRQMASK)); |
279 | u8 mask; | ||
280 | |||
281 | spin_lock_irq(&ice->reg_lock); | ||
282 | mask = inb(ICEREG1724(ice, IRQMASK)); | ||
283 | if (enable) | 286 | if (enable) |
284 | mask &= ~flag; | 287 | mask &= ~flag; |
285 | else | 288 | else |
286 | mask |= flag; | 289 | mask |= flag; |
287 | outb(mask, ICEREG1724(ice, IRQMASK)); | 290 | outb(mask, ICEREG1724(ice, IRQMASK)); |
291 | } | ||
292 | |||
293 | static void vt1724_enable_midi_irq(struct snd_rawmidi_substream *substream, | ||
294 | u8 flag, int enable) | ||
295 | { | ||
296 | struct snd_ice1712 *ice = substream->rmidi->private_data; | ||
297 | |||
298 | spin_lock_irq(&ice->reg_lock); | ||
299 | enable_midi_irq(ice, flag, enable); | ||
288 | spin_unlock_irq(&ice->reg_lock); | 300 | spin_unlock_irq(&ice->reg_lock); |
289 | } | 301 | } |
290 | 302 | ||
291 | static int vt1724_midi_output_open(struct snd_rawmidi_substream *s) | 303 | static int vt1724_midi_output_open(struct snd_rawmidi_substream *s) |
292 | { | 304 | { |
293 | vt1724_enable_midi_irq(s, VT1724_IRQ_MPU_TX, 1); | ||
294 | return 0; | 305 | return 0; |
295 | } | 306 | } |
296 | 307 | ||
297 | static int vt1724_midi_output_close(struct snd_rawmidi_substream *s) | 308 | static int vt1724_midi_output_close(struct snd_rawmidi_substream *s) |
298 | { | 309 | { |
299 | vt1724_enable_midi_irq(s, VT1724_IRQ_MPU_TX, 0); | ||
300 | return 0; | 310 | return 0; |
301 | } | 311 | } |
302 | 312 | ||
@@ -311,6 +321,7 @@ static void vt1724_midi_output_trigger(struct snd_rawmidi_substream *s, int up) | |||
311 | vt1724_midi_write(ice); | 321 | vt1724_midi_write(ice); |
312 | } else { | 322 | } else { |
313 | ice->midi_output = 0; | 323 | ice->midi_output = 0; |
324 | enable_midi_irq(ice, VT1724_IRQ_MPU_TX, 0); | ||
314 | } | 325 | } |
315 | spin_unlock_irqrestore(&ice->reg_lock, flags); | 326 | spin_unlock_irqrestore(&ice->reg_lock, flags); |
316 | } | 327 | } |
@@ -320,6 +331,7 @@ static void vt1724_midi_output_drain(struct snd_rawmidi_substream *s) | |||
320 | struct snd_ice1712 *ice = s->rmidi->private_data; | 331 | struct snd_ice1712 *ice = s->rmidi->private_data; |
321 | unsigned long timeout; | 332 | unsigned long timeout; |
322 | 333 | ||
334 | vt1724_enable_midi_irq(s, VT1724_IRQ_MPU_TX, 0); | ||
323 | /* 32 bytes should be transmitted in less than about 12 ms */ | 335 | /* 32 bytes should be transmitted in less than about 12 ms */ |
324 | timeout = jiffies + msecs_to_jiffies(15); | 336 | timeout = jiffies + msecs_to_jiffies(15); |
325 | do { | 337 | do { |
@@ -389,24 +401,24 @@ static irqreturn_t snd_vt1724_interrupt(int irq, void *dev_id) | |||
389 | status &= status_mask; | 401 | status &= status_mask; |
390 | if (status == 0) | 402 | if (status == 0) |
391 | break; | 403 | break; |
404 | spin_lock(&ice->reg_lock); | ||
392 | if (++timeout > 10) { | 405 | if (++timeout > 10) { |
393 | status = inb(ICEREG1724(ice, IRQSTAT)); | 406 | status = inb(ICEREG1724(ice, IRQSTAT)); |
394 | printk(KERN_ERR "ice1724: Too long irq loop, " | 407 | printk(KERN_ERR "ice1724: Too long irq loop, " |
395 | "status = 0x%x\n", status); | 408 | "status = 0x%x\n", status); |
396 | if (status & VT1724_IRQ_MPU_TX) { | 409 | if (status & VT1724_IRQ_MPU_TX) { |
397 | printk(KERN_ERR "ice1724: Disabling MPU_TX\n"); | 410 | printk(KERN_ERR "ice1724: Disabling MPU_TX\n"); |
398 | outb(inb(ICEREG1724(ice, IRQMASK)) | | 411 | enable_midi_irq(ice, VT1724_IRQ_MPU_TX, 0); |
399 | VT1724_IRQ_MPU_TX, | ||
400 | ICEREG1724(ice, IRQMASK)); | ||
401 | } | 412 | } |
413 | spin_unlock(&ice->reg_lock); | ||
402 | break; | 414 | break; |
403 | } | 415 | } |
404 | handled = 1; | 416 | handled = 1; |
405 | if (status & VT1724_IRQ_MPU_TX) { | 417 | if (status & VT1724_IRQ_MPU_TX) { |
406 | spin_lock(&ice->reg_lock); | ||
407 | if (ice->midi_output) | 418 | if (ice->midi_output) |
408 | vt1724_midi_write(ice); | 419 | vt1724_midi_write(ice); |
409 | spin_unlock(&ice->reg_lock); | 420 | else |
421 | enable_midi_irq(ice, VT1724_IRQ_MPU_TX, 0); | ||
410 | /* Due to mysterical reasons, MPU_TX is always | 422 | /* Due to mysterical reasons, MPU_TX is always |
411 | * generated (and can't be cleared) when a PCM | 423 | * generated (and can't be cleared) when a PCM |
412 | * playback is going. So let's ignore at the | 424 | * playback is going. So let's ignore at the |
@@ -415,15 +427,14 @@ static irqreturn_t snd_vt1724_interrupt(int irq, void *dev_id) | |||
415 | status_mask &= ~VT1724_IRQ_MPU_TX; | 427 | status_mask &= ~VT1724_IRQ_MPU_TX; |
416 | } | 428 | } |
417 | if (status & VT1724_IRQ_MPU_RX) { | 429 | if (status & VT1724_IRQ_MPU_RX) { |
418 | spin_lock(&ice->reg_lock); | ||
419 | if (ice->midi_input) | 430 | if (ice->midi_input) |
420 | vt1724_midi_read(ice); | 431 | vt1724_midi_read(ice); |
421 | else | 432 | else |
422 | vt1724_midi_clear_rx(ice); | 433 | vt1724_midi_clear_rx(ice); |
423 | spin_unlock(&ice->reg_lock); | ||
424 | } | 434 | } |
425 | /* ack MPU irq */ | 435 | /* ack MPU irq */ |
426 | outb(status, ICEREG1724(ice, IRQSTAT)); | 436 | outb(status, ICEREG1724(ice, IRQSTAT)); |
437 | spin_unlock(&ice->reg_lock); | ||
427 | if (status & VT1724_IRQ_MTPCM) { | 438 | if (status & VT1724_IRQ_MTPCM) { |
428 | /* | 439 | /* |
429 | * Multi-track PCM | 440 | * Multi-track PCM |
@@ -745,7 +756,14 @@ static int snd_vt1724_playback_pro_prepare(struct snd_pcm_substream *substream) | |||
745 | 756 | ||
746 | spin_unlock_irq(&ice->reg_lock); | 757 | spin_unlock_irq(&ice->reg_lock); |
747 | 758 | ||
748 | /* printk("pro prepare: ch = %d, addr = 0x%x, buffer = 0x%x, period = 0x%x\n", substream->runtime->channels, (unsigned int)substream->runtime->dma_addr, snd_pcm_lib_buffer_bytes(substream), snd_pcm_lib_period_bytes(substream)); */ | 759 | /* |
760 | printk(KERN_DEBUG "pro prepare: ch = %d, addr = 0x%x, " | ||
761 | "buffer = 0x%x, period = 0x%x\n", | ||
762 | substream->runtime->channels, | ||
763 | (unsigned int)substream->runtime->dma_addr, | ||
764 | snd_pcm_lib_buffer_bytes(substream), | ||
765 | snd_pcm_lib_period_bytes(substream)); | ||
766 | */ | ||
749 | return 0; | 767 | return 0; |
750 | } | 768 | } |
751 | 769 | ||
@@ -2122,7 +2140,9 @@ unsigned char snd_vt1724_read_i2c(struct snd_ice1712 *ice, | |||
2122 | wait_i2c_busy(ice); | 2140 | wait_i2c_busy(ice); |
2123 | val = inb(ICEREG1724(ice, I2C_DATA)); | 2141 | val = inb(ICEREG1724(ice, I2C_DATA)); |
2124 | mutex_unlock(&ice->i2c_mutex); | 2142 | mutex_unlock(&ice->i2c_mutex); |
2125 | /* printk("i2c_read: [0x%x,0x%x] = 0x%x\n", dev, addr, val); */ | 2143 | /* |
2144 | printk(KERN_DEBUG "i2c_read: [0x%x,0x%x] = 0x%x\n", dev, addr, val); | ||
2145 | */ | ||
2126 | return val; | 2146 | return val; |
2127 | } | 2147 | } |
2128 | 2148 | ||
@@ -2131,7 +2151,9 @@ void snd_vt1724_write_i2c(struct snd_ice1712 *ice, | |||
2131 | { | 2151 | { |
2132 | mutex_lock(&ice->i2c_mutex); | 2152 | mutex_lock(&ice->i2c_mutex); |
2133 | wait_i2c_busy(ice); | 2153 | wait_i2c_busy(ice); |
2134 | /* printk("i2c_write: [0x%x,0x%x] = 0x%x\n", dev, addr, data); */ | 2154 | /* |
2155 | printk(KERN_DEBUG "i2c_write: [0x%x,0x%x] = 0x%x\n", dev, addr, data); | ||
2156 | */ | ||
2135 | outb(addr, ICEREG1724(ice, I2C_BYTE_ADDR)); | 2157 | outb(addr, ICEREG1724(ice, I2C_BYTE_ADDR)); |
2136 | outb(data, ICEREG1724(ice, I2C_DATA)); | 2158 | outb(data, ICEREG1724(ice, I2C_DATA)); |
2137 | outb(dev | VT1724_I2C_WRITE, ICEREG1724(ice, I2C_DEV_ADDR)); | 2159 | outb(dev | VT1724_I2C_WRITE, ICEREG1724(ice, I2C_DEV_ADDR)); |
@@ -2456,9 +2478,9 @@ static int __devinit snd_vt1724_probe(struct pci_dev *pci, | |||
2456 | return -ENOENT; | 2478 | return -ENOENT; |
2457 | } | 2479 | } |
2458 | 2480 | ||
2459 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 2481 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); |
2460 | if (card == NULL) | 2482 | if (err < 0) |
2461 | return -ENOMEM; | 2483 | return err; |
2462 | 2484 | ||
2463 | strcpy(card->driver, "ICE1724"); | 2485 | strcpy(card->driver, "ICE1724"); |
2464 | strcpy(card->shortname, "ICEnsemble ICE1724"); | 2486 | strcpy(card->shortname, "ICEnsemble ICE1724"); |
diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c index c51659b9caf6..fd948bfd9aef 100644 --- a/sound/pci/ice1712/juli.c +++ b/sound/pci/ice1712/juli.c | |||
@@ -345,8 +345,9 @@ static int juli_mute_put(struct snd_kcontrol *kcontrol, | |||
345 | new_gpio = old_gpio & | 345 | new_gpio = old_gpio & |
346 | ~((unsigned int) kcontrol->private_value); | 346 | ~((unsigned int) kcontrol->private_value); |
347 | } | 347 | } |
348 | /* printk("JULI - mute/unmute: control_value: 0x%x, old_gpio: 0x%x, \ | 348 | /* printk(KERN_DEBUG |
349 | new_gpio 0x%x\n", | 349 | "JULI - mute/unmute: control_value: 0x%x, old_gpio: 0x%x, " |
350 | "new_gpio 0x%x\n", | ||
350 | (unsigned int)ucontrol->value.integer.value[0], old_gpio, | 351 | (unsigned int)ucontrol->value.integer.value[0], old_gpio, |
351 | new_gpio); */ | 352 | new_gpio); */ |
352 | if (old_gpio != new_gpio) { | 353 | if (old_gpio != new_gpio) { |
diff --git a/sound/pci/ice1712/prodigy192.c b/sound/pci/ice1712/prodigy192.c index 48d3679292a7..2a8e5cd8f2d8 100644 --- a/sound/pci/ice1712/prodigy192.c +++ b/sound/pci/ice1712/prodigy192.c | |||
@@ -133,8 +133,10 @@ static int stac9460_dac_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
133 | idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + STAC946X_LF_VOLUME; | 133 | idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + STAC946X_LF_VOLUME; |
134 | /* due to possible conflicts with stac9460_set_rate_val, mutexing */ | 134 | /* due to possible conflicts with stac9460_set_rate_val, mutexing */ |
135 | mutex_lock(&spec->mute_mutex); | 135 | mutex_lock(&spec->mute_mutex); |
136 | /*printk("Mute put: reg 0x%02x, ctrl value: 0x%02x\n", idx, | 136 | /* |
137 | ucontrol->value.integer.value[0]);*/ | 137 | printk(KERN_DEBUG "Mute put: reg 0x%02x, ctrl value: 0x%02x\n", idx, |
138 | ucontrol->value.integer.value[0]); | ||
139 | */ | ||
138 | change = stac9460_dac_mute(ice, idx, ucontrol->value.integer.value[0]); | 140 | change = stac9460_dac_mute(ice, idx, ucontrol->value.integer.value[0]); |
139 | mutex_unlock(&spec->mute_mutex); | 141 | mutex_unlock(&spec->mute_mutex); |
140 | return change; | 142 | return change; |
@@ -185,7 +187,10 @@ static int stac9460_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el | |||
185 | change = (ovol != nvol); | 187 | change = (ovol != nvol); |
186 | if (change) { | 188 | if (change) { |
187 | ovol = (0x7f - nvol) | (tmp & 0x80); | 189 | ovol = (0x7f - nvol) | (tmp & 0x80); |
188 | /*printk("DAC Volume: reg 0x%02x: 0x%02x\n", idx, ovol);*/ | 190 | /* |
191 | printk(KERN_DEBUG "DAC Volume: reg 0x%02x: 0x%02x\n", | ||
192 | idx, ovol); | ||
193 | */ | ||
189 | stac9460_put(ice, idx, (0x7f - nvol) | (tmp & 0x80)); | 194 | stac9460_put(ice, idx, (0x7f - nvol) | (tmp & 0x80)); |
190 | } | 195 | } |
191 | return change; | 196 | return change; |
@@ -344,7 +349,7 @@ static void stac9460_set_rate_val(struct snd_ice1712 *ice, unsigned int rate) | |||
344 | for (idx = 0; idx < 7 ; ++idx) | 349 | for (idx = 0; idx < 7 ; ++idx) |
345 | changed[idx] = stac9460_dac_mute(ice, | 350 | changed[idx] = stac9460_dac_mute(ice, |
346 | STAC946X_MASTER_VOLUME + idx, 0); | 351 | STAC946X_MASTER_VOLUME + idx, 0); |
347 | /*printk("Rate change: %d, new MC: 0x%02x\n", rate, new);*/ | 352 | /*printk(KERN_DEBUG "Rate change: %d, new MC: 0x%02x\n", rate, new);*/ |
348 | stac9460_put(ice, STAC946X_MASTER_CLOCKING, new); | 353 | stac9460_put(ice, STAC946X_MASTER_CLOCKING, new); |
349 | udelay(10); | 354 | udelay(10); |
350 | /* unmuting - only originally unmuted dacs - | 355 | /* unmuting - only originally unmuted dacs - |
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index e900cdc84849..57648810eaf1 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c | |||
@@ -689,7 +689,7 @@ static void snd_intel8x0_setup_periods(struct intel8x0 *chip, struct ichdev *ich | |||
689 | bdbar[idx + 1] = cpu_to_le32(0x80000000 | /* interrupt on completion */ | 689 | bdbar[idx + 1] = cpu_to_le32(0x80000000 | /* interrupt on completion */ |
690 | ichdev->fragsize >> ichdev->pos_shift); | 690 | ichdev->fragsize >> ichdev->pos_shift); |
691 | #if 0 | 691 | #if 0 |
692 | printk("bdbar[%i] = 0x%x [0x%x]\n", | 692 | printk(KERN_DEBUG "bdbar[%i] = 0x%x [0x%x]\n", |
693 | idx + 0, bdbar[idx + 0], bdbar[idx + 1]); | 693 | idx + 0, bdbar[idx + 0], bdbar[idx + 1]); |
694 | #endif | 694 | #endif |
695 | } | 695 | } |
@@ -701,8 +701,10 @@ static void snd_intel8x0_setup_periods(struct intel8x0 *chip, struct ichdev *ich | |||
701 | ichdev->lvi_frag = ICH_REG_LVI_MASK % ichdev->frags; | 701 | ichdev->lvi_frag = ICH_REG_LVI_MASK % ichdev->frags; |
702 | ichdev->position = 0; | 702 | ichdev->position = 0; |
703 | #if 0 | 703 | #if 0 |
704 | printk("lvi_frag = %i, frags = %i, period_size = 0x%x, period_size1 = 0x%x\n", | 704 | printk(KERN_DEBUG "lvi_frag = %i, frags = %i, period_size = 0x%x, " |
705 | ichdev->lvi_frag, ichdev->frags, ichdev->fragsize, ichdev->fragsize1); | 705 | "period_size1 = 0x%x\n", |
706 | ichdev->lvi_frag, ichdev->frags, ichdev->fragsize, | ||
707 | ichdev->fragsize1); | ||
706 | #endif | 708 | #endif |
707 | /* clear interrupts */ | 709 | /* clear interrupts */ |
708 | iputbyte(chip, port + ichdev->roff_sr, ICH_FIFOE | ICH_BCIS | ICH_LVBCI); | 710 | iputbyte(chip, port + ichdev->roff_sr, ICH_FIFOE | ICH_BCIS | ICH_LVBCI); |
@@ -768,7 +770,8 @@ static inline void snd_intel8x0_update(struct intel8x0 *chip, struct ichdev *ich | |||
768 | ichdev->lvi_frag %= ichdev->frags; | 770 | ichdev->lvi_frag %= ichdev->frags; |
769 | ichdev->bdbar[ichdev->lvi * 2] = cpu_to_le32(ichdev->physbuf + ichdev->lvi_frag * ichdev->fragsize1); | 771 | ichdev->bdbar[ichdev->lvi * 2] = cpu_to_le32(ichdev->physbuf + ichdev->lvi_frag * ichdev->fragsize1); |
770 | #if 0 | 772 | #if 0 |
771 | printk("new: bdbar[%i] = 0x%x [0x%x], prefetch = %i, all = 0x%x, 0x%x\n", | 773 | printk(KERN_DEBUG "new: bdbar[%i] = 0x%x [0x%x], prefetch = %i, " |
774 | "all = 0x%x, 0x%x\n", | ||
772 | ichdev->lvi * 2, ichdev->bdbar[ichdev->lvi * 2], | 775 | ichdev->lvi * 2, ichdev->bdbar[ichdev->lvi * 2], |
773 | ichdev->bdbar[ichdev->lvi * 2 + 1], inb(ICH_REG_OFF_PIV + port), | 776 | ichdev->bdbar[ichdev->lvi * 2 + 1], inb(ICH_REG_OFF_PIV + port), |
774 | inl(port + 4), inb(port + ICH_REG_OFF_CR)); | 777 | inl(port + 4), inb(port + ICH_REG_OFF_CR)); |
@@ -2287,23 +2290,23 @@ static void do_ali_reset(struct intel8x0 *chip) | |||
2287 | iputdword(chip, ICHREG(ALI_INTERRUPTSR), 0x00000000); | 2290 | iputdword(chip, ICHREG(ALI_INTERRUPTSR), 0x00000000); |
2288 | } | 2291 | } |
2289 | 2292 | ||
2290 | static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing) | 2293 | #ifdef CONFIG_SND_AC97_POWER_SAVE |
2291 | { | 2294 | static struct snd_pci_quirk ich_chip_reset_mode[] = { |
2292 | unsigned long end_time; | 2295 | SND_PCI_QUIRK(0x1014, 0x051f, "Thinkpad R32", 1), |
2293 | unsigned int cnt, status, nstatus; | 2296 | { } /* end */ |
2294 | 2297 | }; | |
2295 | /* put logic to right state */ | ||
2296 | /* first clear status bits */ | ||
2297 | status = ICH_RCS | ICH_MCINT | ICH_POINT | ICH_PIINT; | ||
2298 | if (chip->device_type == DEVICE_NFORCE) | ||
2299 | status |= ICH_NVSPINT; | ||
2300 | cnt = igetdword(chip, ICHREG(GLOB_STA)); | ||
2301 | iputdword(chip, ICHREG(GLOB_STA), cnt & status); | ||
2302 | 2298 | ||
2299 | static int snd_intel8x0_ich_chip_cold_reset(struct intel8x0 *chip) | ||
2300 | { | ||
2301 | unsigned int cnt; | ||
2303 | /* ACLink on, 2 channels */ | 2302 | /* ACLink on, 2 channels */ |
2303 | |||
2304 | if (snd_pci_quirk_lookup(chip->pci, ich_chip_reset_mode)) | ||
2305 | return -EIO; | ||
2306 | |||
2304 | cnt = igetdword(chip, ICHREG(GLOB_CNT)); | 2307 | cnt = igetdword(chip, ICHREG(GLOB_CNT)); |
2305 | cnt &= ~(ICH_ACLINK | ICH_PCM_246_MASK); | 2308 | cnt &= ~(ICH_ACLINK | ICH_PCM_246_MASK); |
2306 | #ifdef CONFIG_SND_AC97_POWER_SAVE | 2309 | |
2307 | /* do cold reset - the full ac97 powerdown may leave the controller | 2310 | /* do cold reset - the full ac97 powerdown may leave the controller |
2308 | * in a warm state but actually it cannot communicate with the codec. | 2311 | * in a warm state but actually it cannot communicate with the codec. |
2309 | */ | 2312 | */ |
@@ -2312,22 +2315,58 @@ static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing) | |||
2312 | udelay(10); | 2315 | udelay(10); |
2313 | iputdword(chip, ICHREG(GLOB_CNT), cnt | ICH_AC97COLD); | 2316 | iputdword(chip, ICHREG(GLOB_CNT), cnt | ICH_AC97COLD); |
2314 | msleep(1); | 2317 | msleep(1); |
2318 | return 0; | ||
2319 | } | ||
2320 | #define snd_intel8x0_ich_chip_can_cold_reset(chip) \ | ||
2321 | (!snd_pci_quirk_lookup(chip->pci, ich_chip_reset_mode)) | ||
2315 | #else | 2322 | #else |
2323 | #define snd_intel8x0_ich_chip_cold_reset(chip) 0 | ||
2324 | #define snd_intel8x0_ich_chip_can_cold_reset(chip) (0) | ||
2325 | #endif | ||
2326 | |||
2327 | static int snd_intel8x0_ich_chip_reset(struct intel8x0 *chip) | ||
2328 | { | ||
2329 | unsigned long end_time; | ||
2330 | unsigned int cnt; | ||
2331 | /* ACLink on, 2 channels */ | ||
2332 | cnt = igetdword(chip, ICHREG(GLOB_CNT)); | ||
2333 | cnt &= ~(ICH_ACLINK | ICH_PCM_246_MASK); | ||
2316 | /* finish cold or do warm reset */ | 2334 | /* finish cold or do warm reset */ |
2317 | cnt |= (cnt & ICH_AC97COLD) == 0 ? ICH_AC97COLD : ICH_AC97WARM; | 2335 | cnt |= (cnt & ICH_AC97COLD) == 0 ? ICH_AC97COLD : ICH_AC97WARM; |
2318 | iputdword(chip, ICHREG(GLOB_CNT), cnt); | 2336 | iputdword(chip, ICHREG(GLOB_CNT), cnt); |
2319 | end_time = (jiffies + (HZ / 4)) + 1; | 2337 | end_time = (jiffies + (HZ / 4)) + 1; |
2320 | do { | 2338 | do { |
2321 | if ((igetdword(chip, ICHREG(GLOB_CNT)) & ICH_AC97WARM) == 0) | 2339 | if ((igetdword(chip, ICHREG(GLOB_CNT)) & ICH_AC97WARM) == 0) |
2322 | goto __ok; | 2340 | return 0; |
2323 | schedule_timeout_uninterruptible(1); | 2341 | schedule_timeout_uninterruptible(1); |
2324 | } while (time_after_eq(end_time, jiffies)); | 2342 | } while (time_after_eq(end_time, jiffies)); |
2325 | snd_printk(KERN_ERR "AC'97 warm reset still in progress? [0x%x]\n", | 2343 | snd_printk(KERN_ERR "AC'97 warm reset still in progress? [0x%x]\n", |
2326 | igetdword(chip, ICHREG(GLOB_CNT))); | 2344 | igetdword(chip, ICHREG(GLOB_CNT))); |
2327 | return -EIO; | 2345 | return -EIO; |
2346 | } | ||
2347 | |||
2348 | static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing) | ||
2349 | { | ||
2350 | unsigned long end_time; | ||
2351 | unsigned int status, nstatus; | ||
2352 | unsigned int cnt; | ||
2353 | int err; | ||
2354 | |||
2355 | /* put logic to right state */ | ||
2356 | /* first clear status bits */ | ||
2357 | status = ICH_RCS | ICH_MCINT | ICH_POINT | ICH_PIINT; | ||
2358 | if (chip->device_type == DEVICE_NFORCE) | ||
2359 | status |= ICH_NVSPINT; | ||
2360 | cnt = igetdword(chip, ICHREG(GLOB_STA)); | ||
2361 | iputdword(chip, ICHREG(GLOB_STA), cnt & status); | ||
2362 | |||
2363 | if (snd_intel8x0_ich_chip_can_cold_reset(chip)) | ||
2364 | err = snd_intel8x0_ich_chip_cold_reset(chip); | ||
2365 | else | ||
2366 | err = snd_intel8x0_ich_chip_reset(chip); | ||
2367 | if (err < 0) | ||
2368 | return err; | ||
2328 | 2369 | ||
2329 | __ok: | ||
2330 | #endif | ||
2331 | if (probing) { | 2370 | if (probing) { |
2332 | /* wait for any codec ready status. | 2371 | /* wait for any codec ready status. |
2333 | * Once it becomes ready it should remain ready | 2372 | * Once it becomes ready it should remain ready |
@@ -3058,9 +3097,9 @@ static int __devinit snd_intel8x0_probe(struct pci_dev *pci, | |||
3058 | int err; | 3097 | int err; |
3059 | struct shortname_table *name; | 3098 | struct shortname_table *name; |
3060 | 3099 | ||
3061 | card = snd_card_new(index, id, THIS_MODULE, 0); | 3100 | err = snd_card_create(index, id, THIS_MODULE, 0, &card); |
3062 | if (card == NULL) | 3101 | if (err < 0) |
3063 | return -ENOMEM; | 3102 | return err; |
3064 | 3103 | ||
3065 | if (spdif_aclink < 0) | 3104 | if (spdif_aclink < 0) |
3066 | spdif_aclink = check_default_spdif_aclink(pci); | 3105 | spdif_aclink = check_default_spdif_aclink(pci); |
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index 93449e464566..6ec0fc50d6be 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c | |||
@@ -411,7 +411,10 @@ static void snd_intel8x0_setup_periods(struct intel8x0m *chip, struct ichdev *ic | |||
411 | bdbar[idx + 0] = cpu_to_le32(ichdev->physbuf + (((idx >> 1) * ichdev->fragsize) % ichdev->size)); | 411 | bdbar[idx + 0] = cpu_to_le32(ichdev->physbuf + (((idx >> 1) * ichdev->fragsize) % ichdev->size)); |
412 | bdbar[idx + 1] = cpu_to_le32(0x80000000 | /* interrupt on completion */ | 412 | bdbar[idx + 1] = cpu_to_le32(0x80000000 | /* interrupt on completion */ |
413 | ichdev->fragsize >> chip->pcm_pos_shift); | 413 | ichdev->fragsize >> chip->pcm_pos_shift); |
414 | // printk("bdbar[%i] = 0x%x [0x%x]\n", idx + 0, bdbar[idx + 0], bdbar[idx + 1]); | 414 | /* |
415 | printk(KERN_DEBUG "bdbar[%i] = 0x%x [0x%x]\n", | ||
416 | idx + 0, bdbar[idx + 0], bdbar[idx + 1]); | ||
417 | */ | ||
415 | } | 418 | } |
416 | ichdev->frags = ichdev->size / ichdev->fragsize; | 419 | ichdev->frags = ichdev->size / ichdev->fragsize; |
417 | } | 420 | } |
@@ -421,8 +424,10 @@ static void snd_intel8x0_setup_periods(struct intel8x0m *chip, struct ichdev *ic | |||
421 | ichdev->lvi_frag = ICH_REG_LVI_MASK % ichdev->frags; | 424 | ichdev->lvi_frag = ICH_REG_LVI_MASK % ichdev->frags; |
422 | ichdev->position = 0; | 425 | ichdev->position = 0; |
423 | #if 0 | 426 | #if 0 |
424 | printk("lvi_frag = %i, frags = %i, period_size = 0x%x, period_size1 = 0x%x\n", | 427 | printk(KERN_DEBUG "lvi_frag = %i, frags = %i, period_size = 0x%x, " |
425 | ichdev->lvi_frag, ichdev->frags, ichdev->fragsize, ichdev->fragsize1); | 428 | "period_size1 = 0x%x\n", |
429 | ichdev->lvi_frag, ichdev->frags, ichdev->fragsize, | ||
430 | ichdev->fragsize1); | ||
426 | #endif | 431 | #endif |
427 | /* clear interrupts */ | 432 | /* clear interrupts */ |
428 | iputbyte(chip, port + ichdev->roff_sr, ICH_FIFOE | ICH_BCIS | ICH_LVBCI); | 433 | iputbyte(chip, port + ichdev->roff_sr, ICH_FIFOE | ICH_BCIS | ICH_LVBCI); |
@@ -465,7 +470,8 @@ static inline void snd_intel8x0_update(struct intel8x0m *chip, struct ichdev *ic | |||
465 | ichdev->lvi_frag * | 470 | ichdev->lvi_frag * |
466 | ichdev->fragsize1); | 471 | ichdev->fragsize1); |
467 | #if 0 | 472 | #if 0 |
468 | printk("new: bdbar[%i] = 0x%x [0x%x], prefetch = %i, all = 0x%x, 0x%x\n", | 473 | printk(KERN_DEBUG "new: bdbar[%i] = 0x%x [0x%x], " |
474 | "prefetch = %i, all = 0x%x, 0x%x\n", | ||
469 | ichdev->lvi * 2, ichdev->bdbar[ichdev->lvi * 2], | 475 | ichdev->lvi * 2, ichdev->bdbar[ichdev->lvi * 2], |
470 | ichdev->bdbar[ichdev->lvi * 2 + 1], inb(ICH_REG_OFF_PIV + port), | 476 | ichdev->bdbar[ichdev->lvi * 2 + 1], inb(ICH_REG_OFF_PIV + port), |
471 | inl(port + 4), inb(port + ICH_REG_OFF_CR)); | 477 | inl(port + 4), inb(port + ICH_REG_OFF_CR)); |
@@ -1269,9 +1275,9 @@ static int __devinit snd_intel8x0m_probe(struct pci_dev *pci, | |||
1269 | int err; | 1275 | int err; |
1270 | struct shortname_table *name; | 1276 | struct shortname_table *name; |
1271 | 1277 | ||
1272 | card = snd_card_new(index, id, THIS_MODULE, 0); | 1278 | err = snd_card_create(index, id, THIS_MODULE, 0, &card); |
1273 | if (card == NULL) | 1279 | if (err < 0) |
1274 | return -ENOMEM; | 1280 | return err; |
1275 | 1281 | ||
1276 | strcpy(card->driver, "ICH-MODEM"); | 1282 | strcpy(card->driver, "ICH-MODEM"); |
1277 | strcpy(card->shortname, "Intel ICH"); | 1283 | strcpy(card->shortname, "Intel ICH"); |
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c index 5f8006b42750..8b79969034be 100644 --- a/sound/pci/korg1212/korg1212.c +++ b/sound/pci/korg1212/korg1212.c | |||
@@ -2443,9 +2443,9 @@ snd_korg1212_probe(struct pci_dev *pci, | |||
2443 | dev++; | 2443 | dev++; |
2444 | return -ENOENT; | 2444 | return -ENOENT; |
2445 | } | 2445 | } |
2446 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 2446 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); |
2447 | if (card == NULL) | 2447 | if (err < 0) |
2448 | return -ENOMEM; | 2448 | return err; |
2449 | 2449 | ||
2450 | if ((err = snd_korg1212_create(card, pci, &korg1212)) < 0) { | 2450 | if ((err = snd_korg1212_create(card, pci, &korg1212)) < 0) { |
2451 | snd_card_free(card); | 2451 | snd_card_free(card); |
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index 59bbaf8f3e5b..70141548f251 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c | |||
@@ -2691,9 +2691,9 @@ snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) | |||
2691 | return -ENOENT; | 2691 | return -ENOENT; |
2692 | } | 2692 | } |
2693 | 2693 | ||
2694 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 2694 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); |
2695 | if (card == NULL) | 2695 | if (err < 0) |
2696 | return -ENOMEM; | 2696 | return err; |
2697 | 2697 | ||
2698 | switch (pci->device) { | 2698 | switch (pci->device) { |
2699 | case PCI_DEVICE_ID_ESS_ALLEGRO: | 2699 | case PCI_DEVICE_ID_ESS_ALLEGRO: |
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index bb162507fe6c..c1eb84a14c42 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c | |||
@@ -1366,12 +1366,12 @@ static int __devinit snd_mixart_probe(struct pci_dev *pci, | |||
1366 | else | 1366 | else |
1367 | idx = index[dev] + i; | 1367 | idx = index[dev] + i; |
1368 | snprintf(tmpid, sizeof(tmpid), "%s-%d", id[dev] ? id[dev] : "MIXART", i); | 1368 | snprintf(tmpid, sizeof(tmpid), "%s-%d", id[dev] ? id[dev] : "MIXART", i); |
1369 | card = snd_card_new(idx, tmpid, THIS_MODULE, 0); | 1369 | err = snd_card_create(idx, tmpid, THIS_MODULE, 0, &card); |
1370 | 1370 | ||
1371 | if (! card) { | 1371 | if (err < 0) { |
1372 | snd_printk(KERN_ERR "cannot allocate the card %d\n", i); | 1372 | snd_printk(KERN_ERR "cannot allocate the card %d\n", i); |
1373 | snd_mixart_free(mgr); | 1373 | snd_mixart_free(mgr); |
1374 | return -ENOMEM; | 1374 | return err; |
1375 | } | 1375 | } |
1376 | 1376 | ||
1377 | strcpy(card->driver, CARD_NAME); | 1377 | strcpy(card->driver, CARD_NAME); |
diff --git a/sound/pci/mixart/mixart_hwdep.c b/sound/pci/mixart/mixart_hwdep.c index 3782b52bc0e8..4cf4cd8c939c 100644 --- a/sound/pci/mixart/mixart_hwdep.c +++ b/sound/pci/mixart/mixart_hwdep.c | |||
@@ -345,8 +345,8 @@ static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmw | |||
345 | status_daught = readl_be( MIXART_MEM( mgr,MIXART_PSEUDOREG_DXLX_STATUS_OFFSET )); | 345 | status_daught = readl_be( MIXART_MEM( mgr,MIXART_PSEUDOREG_DXLX_STATUS_OFFSET )); |
346 | 346 | ||
347 | /* motherboard xilinx status 5 will say that the board is performing a reset */ | 347 | /* motherboard xilinx status 5 will say that the board is performing a reset */ |
348 | if( status_xilinx == 5 ) { | 348 | if (status_xilinx == 5) { |
349 | snd_printk( KERN_ERR "miXart is resetting !\n"); | 349 | snd_printk(KERN_ERR "miXart is resetting !\n"); |
350 | return -EAGAIN; /* try again later */ | 350 | return -EAGAIN; /* try again later */ |
351 | } | 351 | } |
352 | 352 | ||
@@ -354,13 +354,14 @@ static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmw | |||
354 | case MIXART_MOTHERBOARD_XLX_INDEX: | 354 | case MIXART_MOTHERBOARD_XLX_INDEX: |
355 | 355 | ||
356 | /* xilinx already loaded ? */ | 356 | /* xilinx already loaded ? */ |
357 | if( status_xilinx == 4 ) { | 357 | if (status_xilinx == 4) { |
358 | snd_printk( KERN_DEBUG "xilinx is already loaded !\n"); | 358 | snd_printk(KERN_DEBUG "xilinx is already loaded !\n"); |
359 | return 0; | 359 | return 0; |
360 | } | 360 | } |
361 | /* the status should be 0 == "idle" */ | 361 | /* the status should be 0 == "idle" */ |
362 | if( status_xilinx != 0 ) { | 362 | if (status_xilinx != 0) { |
363 | snd_printk( KERN_ERR "xilinx load error ! status = %d\n", status_xilinx); | 363 | snd_printk(KERN_ERR "xilinx load error ! status = %d\n", |
364 | status_xilinx); | ||
364 | return -EIO; /* modprob -r may help ? */ | 365 | return -EIO; /* modprob -r may help ? */ |
365 | } | 366 | } |
366 | 367 | ||
@@ -389,21 +390,23 @@ static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmw | |||
389 | 390 | ||
390 | case MIXART_MOTHERBOARD_ELF_INDEX: | 391 | case MIXART_MOTHERBOARD_ELF_INDEX: |
391 | 392 | ||
392 | if( status_elf == 4 ) { | 393 | if (status_elf == 4) { |
393 | snd_printk( KERN_DEBUG "elf file already loaded !\n"); | 394 | snd_printk(KERN_DEBUG "elf file already loaded !\n"); |
394 | return 0; | 395 | return 0; |
395 | } | 396 | } |
396 | 397 | ||
397 | /* the status should be 0 == "idle" */ | 398 | /* the status should be 0 == "idle" */ |
398 | if( status_elf != 0 ) { | 399 | if (status_elf != 0) { |
399 | snd_printk( KERN_ERR "elf load error ! status = %d\n", status_elf); | 400 | snd_printk(KERN_ERR "elf load error ! status = %d\n", |
401 | status_elf); | ||
400 | return -EIO; /* modprob -r may help ? */ | 402 | return -EIO; /* modprob -r may help ? */ |
401 | } | 403 | } |
402 | 404 | ||
403 | /* wait for xilinx status == 4 */ | 405 | /* wait for xilinx status == 4 */ |
404 | err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_MXLX_STATUS_OFFSET, 1, 4, 500); /* 5sec */ | 406 | err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_MXLX_STATUS_OFFSET, 1, 4, 500); /* 5sec */ |
405 | if (err < 0) { | 407 | if (err < 0) { |
406 | snd_printk( KERN_ERR "xilinx was not loaded or could not be started\n"); | 408 | snd_printk(KERN_ERR "xilinx was not loaded or " |
409 | "could not be started\n"); | ||
407 | return err; | 410 | return err; |
408 | } | 411 | } |
409 | 412 | ||
@@ -424,7 +427,7 @@ static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmw | |||
424 | /* wait for elf status == 4 */ | 427 | /* wait for elf status == 4 */ |
425 | err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_ELF_STATUS_OFFSET, 1, 4, 300); /* 3sec */ | 428 | err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_ELF_STATUS_OFFSET, 1, 4, 300); /* 3sec */ |
426 | if (err < 0) { | 429 | if (err < 0) { |
427 | snd_printk( KERN_ERR "elf could not be started\n"); | 430 | snd_printk(KERN_ERR "elf could not be started\n"); |
428 | return err; | 431 | return err; |
429 | } | 432 | } |
430 | 433 | ||
@@ -437,15 +440,16 @@ static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmw | |||
437 | default: | 440 | default: |
438 | 441 | ||
439 | /* elf and xilinx should be loaded */ | 442 | /* elf and xilinx should be loaded */ |
440 | if( (status_elf != 4) || (status_xilinx != 4) ) { | 443 | if (status_elf != 4 || status_xilinx != 4) { |
441 | printk( KERN_ERR "xilinx or elf not successfully loaded\n"); | 444 | printk(KERN_ERR "xilinx or elf not " |
445 | "successfully loaded\n"); | ||
442 | return -EIO; /* modprob -r may help ? */ | 446 | return -EIO; /* modprob -r may help ? */ |
443 | } | 447 | } |
444 | 448 | ||
445 | /* wait for daughter detection != 0 */ | 449 | /* wait for daughter detection != 0 */ |
446 | err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_DBRD_PRESENCE_OFFSET, 0, 0, 30); /* 300msec */ | 450 | err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_DBRD_PRESENCE_OFFSET, 0, 0, 30); /* 300msec */ |
447 | if (err < 0) { | 451 | if (err < 0) { |
448 | snd_printk( KERN_ERR "error starting elf file\n"); | 452 | snd_printk(KERN_ERR "error starting elf file\n"); |
449 | return err; | 453 | return err; |
450 | } | 454 | } |
451 | 455 | ||
@@ -460,8 +464,9 @@ static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmw | |||
460 | return -EINVAL; | 464 | return -EINVAL; |
461 | 465 | ||
462 | /* daughter should be idle */ | 466 | /* daughter should be idle */ |
463 | if( status_daught != 0 ) { | 467 | if (status_daught != 0) { |
464 | printk( KERN_ERR "daughter load error ! status = %d\n", status_daught); | 468 | printk(KERN_ERR "daughter load error ! status = %d\n", |
469 | status_daught); | ||
465 | return -EIO; /* modprob -r may help ? */ | 470 | return -EIO; /* modprob -r may help ? */ |
466 | } | 471 | } |
467 | 472 | ||
@@ -480,7 +485,7 @@ static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmw | |||
480 | /* wait for status == 2 */ | 485 | /* wait for status == 2 */ |
481 | err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_DXLX_STATUS_OFFSET, 1, 2, 30); /* 300msec */ | 486 | err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_DXLX_STATUS_OFFSET, 1, 2, 30); /* 300msec */ |
482 | if (err < 0) { | 487 | if (err < 0) { |
483 | snd_printk( KERN_ERR "daughter board load error\n"); | 488 | snd_printk(KERN_ERR "daughter board load error\n"); |
484 | return err; | 489 | return err; |
485 | } | 490 | } |
486 | 491 | ||
@@ -502,7 +507,8 @@ static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmw | |||
502 | /* wait for daughter status == 3 */ | 507 | /* wait for daughter status == 3 */ |
503 | err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_DXLX_STATUS_OFFSET, 1, 3, 300); /* 3sec */ | 508 | err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_DXLX_STATUS_OFFSET, 1, 3, 300); /* 3sec */ |
504 | if (err < 0) { | 509 | if (err < 0) { |
505 | snd_printk( KERN_ERR "daughter board could not be initialised\n"); | 510 | snd_printk(KERN_ERR |
511 | "daughter board could not be initialised\n"); | ||
506 | return err; | 512 | return err; |
507 | } | 513 | } |
508 | 514 | ||
@@ -512,7 +518,7 @@ static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmw | |||
512 | /* first communication with embedded */ | 518 | /* first communication with embedded */ |
513 | err = mixart_first_init(mgr); | 519 | err = mixart_first_init(mgr); |
514 | if (err < 0) { | 520 | if (err < 0) { |
515 | snd_printk( KERN_ERR "miXart could not be set up\n"); | 521 | snd_printk(KERN_ERR "miXart could not be set up\n"); |
516 | return err; | 522 | return err; |
517 | } | 523 | } |
518 | 524 | ||
@@ -581,16 +587,6 @@ MODULE_FIRMWARE("mixart/miXart8AES.xlx"); | |||
581 | /* miXart hwdep interface id string */ | 587 | /* miXart hwdep interface id string */ |
582 | #define SND_MIXART_HWDEP_ID "miXart Loader" | 588 | #define SND_MIXART_HWDEP_ID "miXart Loader" |
583 | 589 | ||
584 | static int mixart_hwdep_open(struct snd_hwdep *hw, struct file *file) | ||
585 | { | ||
586 | return 0; | ||
587 | } | ||
588 | |||
589 | static int mixart_hwdep_release(struct snd_hwdep *hw, struct file *file) | ||
590 | { | ||
591 | return 0; | ||
592 | } | ||
593 | |||
594 | static int mixart_hwdep_dsp_status(struct snd_hwdep *hw, | 590 | static int mixart_hwdep_dsp_status(struct snd_hwdep *hw, |
595 | struct snd_hwdep_dsp_status *info) | 591 | struct snd_hwdep_dsp_status *info) |
596 | { | 592 | { |
@@ -643,8 +639,6 @@ int snd_mixart_setup_firmware(struct mixart_mgr *mgr) | |||
643 | 639 | ||
644 | hw->iface = SNDRV_HWDEP_IFACE_MIXART; | 640 | hw->iface = SNDRV_HWDEP_IFACE_MIXART; |
645 | hw->private_data = mgr; | 641 | hw->private_data = mgr; |
646 | hw->ops.open = mixart_hwdep_open; | ||
647 | hw->ops.release = mixart_hwdep_release; | ||
648 | hw->ops.dsp_status = mixart_hwdep_dsp_status; | 642 | hw->ops.dsp_status = mixart_hwdep_dsp_status; |
649 | hw->ops.dsp_load = mixart_hwdep_dsp_load; | 643 | hw->ops.dsp_load = mixart_hwdep_dsp_load; |
650 | hw->exclusive = 1; | 644 | hw->exclusive = 1; |
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index 50c9f8a05082..522a040855d4 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c | |||
@@ -1668,9 +1668,9 @@ static int __devinit snd_nm256_probe(struct pci_dev *pci, | |||
1668 | } | 1668 | } |
1669 | } | 1669 | } |
1670 | 1670 | ||
1671 | card = snd_card_new(index, id, THIS_MODULE, 0); | 1671 | err = snd_card_create(index, id, THIS_MODULE, 0, &card); |
1672 | if (card == NULL) | 1672 | if (err < 0) |
1673 | return -ENOMEM; | 1673 | return err; |
1674 | 1674 | ||
1675 | switch (pci->device) { | 1675 | switch (pci->device) { |
1676 | case PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO: | 1676 | case PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO: |
diff --git a/sound/pci/oxygen/hifier.c b/sound/pci/oxygen/hifier.c index 1ab833f843eb..84ef13183419 100644 --- a/sound/pci/oxygen/hifier.c +++ b/sound/pci/oxygen/hifier.c | |||
@@ -45,6 +45,7 @@ MODULE_PARM_DESC(enable, "enable card"); | |||
45 | static struct pci_device_id hifier_ids[] __devinitdata = { | 45 | static struct pci_device_id hifier_ids[] __devinitdata = { |
46 | { OXYGEN_PCI_SUBID(0x14c3, 0x1710) }, | 46 | { OXYGEN_PCI_SUBID(0x14c3, 0x1710) }, |
47 | { OXYGEN_PCI_SUBID(0x14c3, 0x1711) }, | 47 | { OXYGEN_PCI_SUBID(0x14c3, 0x1711) }, |
48 | { OXYGEN_PCI_SUBID_BROKEN_EEPROM }, | ||
48 | { } | 49 | { } |
49 | }; | 50 | }; |
50 | MODULE_DEVICE_TABLE(pci, hifier_ids); | 51 | MODULE_DEVICE_TABLE(pci, hifier_ids); |
@@ -151,7 +152,6 @@ static const struct oxygen_model model_hifier = { | |||
151 | .shortname = "C-Media CMI8787", | 152 | .shortname = "C-Media CMI8787", |
152 | .longname = "C-Media Oxygen HD Audio", | 153 | .longname = "C-Media Oxygen HD Audio", |
153 | .chip = "CMI8788", | 154 | .chip = "CMI8788", |
154 | .owner = THIS_MODULE, | ||
155 | .init = hifier_init, | 155 | .init = hifier_init, |
156 | .control_filter = hifier_control_filter, | 156 | .control_filter = hifier_control_filter, |
157 | .cleanup = hifier_cleanup, | 157 | .cleanup = hifier_cleanup, |
@@ -173,6 +173,13 @@ static const struct oxygen_model model_hifier = { | |||
173 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | 173 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, |
174 | }; | 174 | }; |
175 | 175 | ||
176 | static int __devinit get_hifier_model(struct oxygen *chip, | ||
177 | const struct pci_device_id *id) | ||
178 | { | ||
179 | chip->model = model_hifier; | ||
180 | return 0; | ||
181 | } | ||
182 | |||
176 | static int __devinit hifier_probe(struct pci_dev *pci, | 183 | static int __devinit hifier_probe(struct pci_dev *pci, |
177 | const struct pci_device_id *pci_id) | 184 | const struct pci_device_id *pci_id) |
178 | { | 185 | { |
@@ -185,7 +192,8 @@ static int __devinit hifier_probe(struct pci_dev *pci, | |||
185 | ++dev; | 192 | ++dev; |
186 | return -ENOENT; | 193 | return -ENOENT; |
187 | } | 194 | } |
188 | err = oxygen_pci_probe(pci, index[dev], id[dev], &model_hifier, 0); | 195 | err = oxygen_pci_probe(pci, index[dev], id[dev], THIS_MODULE, |
196 | hifier_ids, get_hifier_model); | ||
189 | if (err >= 0) | 197 | if (err >= 0) |
190 | ++dev; | 198 | ++dev; |
191 | return err; | 199 | return err; |
diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c index de999c6d6dd3..72db4c39007f 100644 --- a/sound/pci/oxygen/oxygen.c +++ b/sound/pci/oxygen/oxygen.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * C-Media CMI8788 driver for C-Media's reference design and for the X-Meridian | 2 | * C-Media CMI8788 driver for C-Media's reference design and similar models |
3 | * | 3 | * |
4 | * Copyright (c) Clemens Ladisch <clemens@ladisch.de> | 4 | * Copyright (c) Clemens Ladisch <clemens@ladisch.de> |
5 | * | 5 | * |
@@ -26,6 +26,7 @@ | |||
26 | * | 26 | * |
27 | * GPIO 0 -> DFS0 of AK5385 | 27 | * GPIO 0 -> DFS0 of AK5385 |
28 | * GPIO 1 -> DFS1 of AK5385 | 28 | * GPIO 1 -> DFS1 of AK5385 |
29 | * GPIO 8 -> enable headphone amplifier on HT-Omega models | ||
29 | */ | 30 | */ |
30 | 31 | ||
31 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
@@ -61,7 +62,8 @@ MODULE_PARM_DESC(enable, "enable card"); | |||
61 | enum { | 62 | enum { |
62 | MODEL_CMEDIA_REF, /* C-Media's reference design */ | 63 | MODEL_CMEDIA_REF, /* C-Media's reference design */ |
63 | MODEL_MERIDIAN, /* AuzenTech X-Meridian */ | 64 | MODEL_MERIDIAN, /* AuzenTech X-Meridian */ |
64 | MODEL_HALO, /* HT-Omega Claro halo */ | 65 | MODEL_CLARO, /* HT-Omega Claro */ |
66 | MODEL_CLARO_HALO, /* HT-Omega Claro halo */ | ||
65 | }; | 67 | }; |
66 | 68 | ||
67 | static struct pci_device_id oxygen_ids[] __devinitdata = { | 69 | static struct pci_device_id oxygen_ids[] __devinitdata = { |
@@ -74,8 +76,8 @@ static struct pci_device_id oxygen_ids[] __devinitdata = { | |||
74 | { OXYGEN_PCI_SUBID(0x147a, 0xa017), .driver_data = MODEL_CMEDIA_REF }, | 76 | { OXYGEN_PCI_SUBID(0x147a, 0xa017), .driver_data = MODEL_CMEDIA_REF }, |
75 | { OXYGEN_PCI_SUBID(0x1a58, 0x0910), .driver_data = MODEL_CMEDIA_REF }, | 77 | { OXYGEN_PCI_SUBID(0x1a58, 0x0910), .driver_data = MODEL_CMEDIA_REF }, |
76 | { OXYGEN_PCI_SUBID(0x415a, 0x5431), .driver_data = MODEL_MERIDIAN }, | 78 | { OXYGEN_PCI_SUBID(0x415a, 0x5431), .driver_data = MODEL_MERIDIAN }, |
77 | { OXYGEN_PCI_SUBID(0x7284, 0x9761), .driver_data = MODEL_CMEDIA_REF }, | 79 | { OXYGEN_PCI_SUBID(0x7284, 0x9761), .driver_data = MODEL_CLARO }, |
78 | { OXYGEN_PCI_SUBID(0x7284, 0x9781), .driver_data = MODEL_HALO }, | 80 | { OXYGEN_PCI_SUBID(0x7284, 0x9781), .driver_data = MODEL_CLARO_HALO }, |
79 | { } | 81 | { } |
80 | }; | 82 | }; |
81 | MODULE_DEVICE_TABLE(pci, oxygen_ids); | 83 | MODULE_DEVICE_TABLE(pci, oxygen_ids); |
@@ -86,6 +88,8 @@ MODULE_DEVICE_TABLE(pci, oxygen_ids); | |||
86 | #define GPIO_AK5385_DFS_DOUBLE 0x0001 | 88 | #define GPIO_AK5385_DFS_DOUBLE 0x0001 |
87 | #define GPIO_AK5385_DFS_QUAD 0x0002 | 89 | #define GPIO_AK5385_DFS_QUAD 0x0002 |
88 | 90 | ||
91 | #define GPIO_CLARO_HP 0x0100 | ||
92 | |||
89 | struct generic_data { | 93 | struct generic_data { |
90 | u8 ak4396_ctl2; | 94 | u8 ak4396_ctl2; |
91 | u16 saved_wm8785_registers[2]; | 95 | u16 saved_wm8785_registers[2]; |
@@ -196,10 +200,46 @@ static void meridian_init(struct oxygen *chip) | |||
196 | ak5385_init(chip); | 200 | ak5385_init(chip); |
197 | } | 201 | } |
198 | 202 | ||
203 | static void claro_enable_hp(struct oxygen *chip) | ||
204 | { | ||
205 | msleep(300); | ||
206 | oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_CLARO_HP); | ||
207 | oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_CLARO_HP); | ||
208 | } | ||
209 | |||
210 | static void claro_init(struct oxygen *chip) | ||
211 | { | ||
212 | ak4396_init(chip); | ||
213 | wm8785_init(chip); | ||
214 | claro_enable_hp(chip); | ||
215 | } | ||
216 | |||
217 | static void claro_halo_init(struct oxygen *chip) | ||
218 | { | ||
219 | ak4396_init(chip); | ||
220 | ak5385_init(chip); | ||
221 | claro_enable_hp(chip); | ||
222 | } | ||
223 | |||
199 | static void generic_cleanup(struct oxygen *chip) | 224 | static void generic_cleanup(struct oxygen *chip) |
200 | { | 225 | { |
201 | } | 226 | } |
202 | 227 | ||
228 | static void claro_disable_hp(struct oxygen *chip) | ||
229 | { | ||
230 | oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_CLARO_HP); | ||
231 | } | ||
232 | |||
233 | static void claro_cleanup(struct oxygen *chip) | ||
234 | { | ||
235 | claro_disable_hp(chip); | ||
236 | } | ||
237 | |||
238 | static void claro_suspend(struct oxygen *chip) | ||
239 | { | ||
240 | claro_disable_hp(chip); | ||
241 | } | ||
242 | |||
203 | static void generic_resume(struct oxygen *chip) | 243 | static void generic_resume(struct oxygen *chip) |
204 | { | 244 | { |
205 | ak4396_registers_init(chip); | 245 | ak4396_registers_init(chip); |
@@ -211,6 +251,12 @@ static void meridian_resume(struct oxygen *chip) | |||
211 | ak4396_registers_init(chip); | 251 | ak4396_registers_init(chip); |
212 | } | 252 | } |
213 | 253 | ||
254 | static void claro_resume(struct oxygen *chip) | ||
255 | { | ||
256 | ak4396_registers_init(chip); | ||
257 | claro_enable_hp(chip); | ||
258 | } | ||
259 | |||
214 | static void set_ak4396_params(struct oxygen *chip, | 260 | static void set_ak4396_params(struct oxygen *chip, |
215 | struct snd_pcm_hw_params *params) | 261 | struct snd_pcm_hw_params *params) |
216 | { | 262 | { |
@@ -293,30 +339,10 @@ static void set_ak5385_params(struct oxygen *chip, | |||
293 | 339 | ||
294 | static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0); | 340 | static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0); |
295 | 341 | ||
296 | static int generic_probe(struct oxygen *chip, unsigned long driver_data) | ||
297 | { | ||
298 | if (driver_data == MODEL_MERIDIAN) { | ||
299 | chip->model.init = meridian_init; | ||
300 | chip->model.resume = meridian_resume; | ||
301 | chip->model.set_adc_params = set_ak5385_params; | ||
302 | chip->model.device_config = PLAYBACK_0_TO_I2S | | ||
303 | PLAYBACK_1_TO_SPDIF | | ||
304 | CAPTURE_0_FROM_I2S_2 | | ||
305 | CAPTURE_1_FROM_SPDIF; | ||
306 | } | ||
307 | if (driver_data == MODEL_MERIDIAN || driver_data == MODEL_HALO) { | ||
308 | chip->model.misc_flags = OXYGEN_MISC_MIDI; | ||
309 | chip->model.device_config |= MIDI_OUTPUT | MIDI_INPUT; | ||
310 | } | ||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | static const struct oxygen_model model_generic = { | 342 | static const struct oxygen_model model_generic = { |
315 | .shortname = "C-Media CMI8788", | 343 | .shortname = "C-Media CMI8788", |
316 | .longname = "C-Media Oxygen HD Audio", | 344 | .longname = "C-Media Oxygen HD Audio", |
317 | .chip = "CMI8788", | 345 | .chip = "CMI8788", |
318 | .owner = THIS_MODULE, | ||
319 | .probe = generic_probe, | ||
320 | .init = generic_init, | 346 | .init = generic_init, |
321 | .cleanup = generic_cleanup, | 347 | .cleanup = generic_cleanup, |
322 | .resume = generic_resume, | 348 | .resume = generic_resume, |
@@ -341,6 +367,42 @@ static const struct oxygen_model model_generic = { | |||
341 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | 367 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, |
342 | }; | 368 | }; |
343 | 369 | ||
370 | static int __devinit get_oxygen_model(struct oxygen *chip, | ||
371 | const struct pci_device_id *id) | ||
372 | { | ||
373 | chip->model = model_generic; | ||
374 | switch (id->driver_data) { | ||
375 | case MODEL_MERIDIAN: | ||
376 | chip->model.init = meridian_init; | ||
377 | chip->model.resume = meridian_resume; | ||
378 | chip->model.set_adc_params = set_ak5385_params; | ||
379 | chip->model.device_config = PLAYBACK_0_TO_I2S | | ||
380 | PLAYBACK_1_TO_SPDIF | | ||
381 | CAPTURE_0_FROM_I2S_2 | | ||
382 | CAPTURE_1_FROM_SPDIF; | ||
383 | break; | ||
384 | case MODEL_CLARO: | ||
385 | chip->model.init = claro_init; | ||
386 | chip->model.cleanup = claro_cleanup; | ||
387 | chip->model.suspend = claro_suspend; | ||
388 | chip->model.resume = claro_resume; | ||
389 | break; | ||
390 | case MODEL_CLARO_HALO: | ||
391 | chip->model.init = claro_halo_init; | ||
392 | chip->model.cleanup = claro_cleanup; | ||
393 | chip->model.suspend = claro_suspend; | ||
394 | chip->model.resume = claro_resume; | ||
395 | chip->model.set_adc_params = set_ak5385_params; | ||
396 | break; | ||
397 | } | ||
398 | if (id->driver_data == MODEL_MERIDIAN || | ||
399 | id->driver_data == MODEL_CLARO_HALO) { | ||
400 | chip->model.misc_flags = OXYGEN_MISC_MIDI; | ||
401 | chip->model.device_config |= MIDI_OUTPUT | MIDI_INPUT; | ||
402 | } | ||
403 | return 0; | ||
404 | } | ||
405 | |||
344 | static int __devinit generic_oxygen_probe(struct pci_dev *pci, | 406 | static int __devinit generic_oxygen_probe(struct pci_dev *pci, |
345 | const struct pci_device_id *pci_id) | 407 | const struct pci_device_id *pci_id) |
346 | { | 408 | { |
@@ -353,8 +415,8 @@ static int __devinit generic_oxygen_probe(struct pci_dev *pci, | |||
353 | ++dev; | 415 | ++dev; |
354 | return -ENOENT; | 416 | return -ENOENT; |
355 | } | 417 | } |
356 | err = oxygen_pci_probe(pci, index[dev], id[dev], | 418 | err = oxygen_pci_probe(pci, index[dev], id[dev], THIS_MODULE, |
357 | &model_generic, pci_id->driver_data); | 419 | oxygen_ids, get_oxygen_model); |
358 | if (err >= 0) | 420 | if (err >= 0) |
359 | ++dev; | 421 | ++dev; |
360 | return err; | 422 | return err; |
diff --git a/sound/pci/oxygen/oxygen.h b/sound/pci/oxygen/oxygen.h index 19107c6307e5..bd615dbffadb 100644 --- a/sound/pci/oxygen/oxygen.h +++ b/sound/pci/oxygen/oxygen.h | |||
@@ -18,6 +18,8 @@ | |||
18 | 18 | ||
19 | #define OXYGEN_IO_SIZE 0x100 | 19 | #define OXYGEN_IO_SIZE 0x100 |
20 | 20 | ||
21 | #define OXYGEN_EEPROM_ID 0x434d /* "CM" */ | ||
22 | |||
21 | /* model-specific configuration of outputs/inputs */ | 23 | /* model-specific configuration of outputs/inputs */ |
22 | #define PLAYBACK_0_TO_I2S 0x0001 | 24 | #define PLAYBACK_0_TO_I2S 0x0001 |
23 | /* PLAYBACK_0_TO_AC97_0 not implemented */ | 25 | /* PLAYBACK_0_TO_AC97_0 not implemented */ |
@@ -49,7 +51,13 @@ enum { | |||
49 | .subvendor = sv, \ | 51 | .subvendor = sv, \ |
50 | .subdevice = sd | 52 | .subdevice = sd |
51 | 53 | ||
54 | #define BROKEN_EEPROM_DRIVER_DATA ((unsigned long)-1) | ||
55 | #define OXYGEN_PCI_SUBID_BROKEN_EEPROM \ | ||
56 | OXYGEN_PCI_SUBID(PCI_VENDOR_ID_CMEDIA, 0x8788), \ | ||
57 | .driver_data = BROKEN_EEPROM_DRIVER_DATA | ||
58 | |||
52 | struct pci_dev; | 59 | struct pci_dev; |
60 | struct pci_device_id; | ||
53 | struct snd_card; | 61 | struct snd_card; |
54 | struct snd_pcm_substream; | 62 | struct snd_pcm_substream; |
55 | struct snd_pcm_hardware; | 63 | struct snd_pcm_hardware; |
@@ -62,8 +70,6 @@ struct oxygen_model { | |||
62 | const char *shortname; | 70 | const char *shortname; |
63 | const char *longname; | 71 | const char *longname; |
64 | const char *chip; | 72 | const char *chip; |
65 | struct module *owner; | ||
66 | int (*probe)(struct oxygen *chip, unsigned long driver_data); | ||
67 | void (*init)(struct oxygen *chip); | 73 | void (*init)(struct oxygen *chip); |
68 | int (*control_filter)(struct snd_kcontrol_new *template); | 74 | int (*control_filter)(struct snd_kcontrol_new *template); |
69 | int (*mixer_init)(struct oxygen *chip); | 75 | int (*mixer_init)(struct oxygen *chip); |
@@ -83,6 +89,7 @@ struct oxygen_model { | |||
83 | void (*ac97_switch)(struct oxygen *chip, | 89 | void (*ac97_switch)(struct oxygen *chip, |
84 | unsigned int reg, unsigned int mute); | 90 | unsigned int reg, unsigned int mute); |
85 | const unsigned int *dac_tlv; | 91 | const unsigned int *dac_tlv; |
92 | unsigned long private_data; | ||
86 | size_t model_data_size; | 93 | size_t model_data_size; |
87 | unsigned int device_config; | 94 | unsigned int device_config; |
88 | u8 dac_channels; | 95 | u8 dac_channels; |
@@ -134,8 +141,12 @@ struct oxygen { | |||
134 | /* oxygen_lib.c */ | 141 | /* oxygen_lib.c */ |
135 | 142 | ||
136 | int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, | 143 | int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, |
137 | const struct oxygen_model *model, | 144 | struct module *owner, |
138 | unsigned long driver_data); | 145 | const struct pci_device_id *ids, |
146 | int (*get_model)(struct oxygen *chip, | ||
147 | const struct pci_device_id *id | ||
148 | ) | ||
149 | ); | ||
139 | void oxygen_pci_remove(struct pci_dev *pci); | 150 | void oxygen_pci_remove(struct pci_dev *pci); |
140 | #ifdef CONFIG_PM | 151 | #ifdef CONFIG_PM |
141 | int oxygen_pci_suspend(struct pci_dev *pci, pm_message_t state); | 152 | int oxygen_pci_suspend(struct pci_dev *pci, pm_message_t state); |
@@ -180,6 +191,9 @@ void oxygen_write_i2c(struct oxygen *chip, u8 device, u8 map, u8 data); | |||
180 | void oxygen_reset_uart(struct oxygen *chip); | 191 | void oxygen_reset_uart(struct oxygen *chip); |
181 | void oxygen_write_uart(struct oxygen *chip, u8 data); | 192 | void oxygen_write_uart(struct oxygen *chip, u8 data); |
182 | 193 | ||
194 | u16 oxygen_read_eeprom(struct oxygen *chip, unsigned int index); | ||
195 | void oxygen_write_eeprom(struct oxygen *chip, unsigned int index, u16 value); | ||
196 | |||
183 | static inline void oxygen_set_bits8(struct oxygen *chip, | 197 | static inline void oxygen_set_bits8(struct oxygen *chip, |
184 | unsigned int reg, u8 value) | 198 | unsigned int reg, u8 value) |
185 | { | 199 | { |
diff --git a/sound/pci/oxygen/oxygen_io.c b/sound/pci/oxygen/oxygen_io.c index 3126c4b403dd..c1eb923f2ac9 100644 --- a/sound/pci/oxygen/oxygen_io.c +++ b/sound/pci/oxygen/oxygen_io.c | |||
@@ -254,3 +254,34 @@ void oxygen_write_uart(struct oxygen *chip, u8 data) | |||
254 | _write_uart(chip, 0, data); | 254 | _write_uart(chip, 0, data); |
255 | } | 255 | } |
256 | EXPORT_SYMBOL(oxygen_write_uart); | 256 | EXPORT_SYMBOL(oxygen_write_uart); |
257 | |||
258 | u16 oxygen_read_eeprom(struct oxygen *chip, unsigned int index) | ||
259 | { | ||
260 | unsigned int timeout; | ||
261 | |||
262 | oxygen_write8(chip, OXYGEN_EEPROM_CONTROL, | ||
263 | index | OXYGEN_EEPROM_DIR_READ); | ||
264 | for (timeout = 0; timeout < 100; ++timeout) { | ||
265 | udelay(1); | ||
266 | if (!(oxygen_read8(chip, OXYGEN_EEPROM_STATUS) | ||
267 | & OXYGEN_EEPROM_BUSY)) | ||
268 | break; | ||
269 | } | ||
270 | return oxygen_read16(chip, OXYGEN_EEPROM_DATA); | ||
271 | } | ||
272 | |||
273 | void oxygen_write_eeprom(struct oxygen *chip, unsigned int index, u16 value) | ||
274 | { | ||
275 | unsigned int timeout; | ||
276 | |||
277 | oxygen_write16(chip, OXYGEN_EEPROM_DATA, value); | ||
278 | oxygen_write8(chip, OXYGEN_EEPROM_CONTROL, | ||
279 | index | OXYGEN_EEPROM_DIR_WRITE); | ||
280 | for (timeout = 0; timeout < 10; ++timeout) { | ||
281 | msleep(1); | ||
282 | if (!(oxygen_read8(chip, OXYGEN_EEPROM_STATUS) | ||
283 | & OXYGEN_EEPROM_BUSY)) | ||
284 | return; | ||
285 | } | ||
286 | snd_printk(KERN_ERR "EEPROM write timeout\n"); | ||
287 | } | ||
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c index 84f481d41efa..312251d39696 100644 --- a/sound/pci/oxygen/oxygen_lib.c +++ b/sound/pci/oxygen/oxygen_lib.c | |||
@@ -34,6 +34,7 @@ MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); | |||
34 | MODULE_DESCRIPTION("C-Media CMI8788 helper library"); | 34 | MODULE_DESCRIPTION("C-Media CMI8788 helper library"); |
35 | MODULE_LICENSE("GPL v2"); | 35 | MODULE_LICENSE("GPL v2"); |
36 | 36 | ||
37 | #define DRIVER "oxygen" | ||
37 | 38 | ||
38 | static inline int oxygen_uart_input_ready(struct oxygen *chip) | 39 | static inline int oxygen_uart_input_ready(struct oxygen *chip) |
39 | { | 40 | { |
@@ -243,6 +244,62 @@ static void oxygen_proc_init(struct oxygen *chip) | |||
243 | #define oxygen_proc_init(chip) | 244 | #define oxygen_proc_init(chip) |
244 | #endif | 245 | #endif |
245 | 246 | ||
247 | static const struct pci_device_id * | ||
248 | oxygen_search_pci_id(struct oxygen *chip, const struct pci_device_id ids[]) | ||
249 | { | ||
250 | u16 subdevice; | ||
251 | |||
252 | /* | ||
253 | * Make sure the EEPROM pins are available, i.e., not used for SPI. | ||
254 | * (This function is called before we initialize or use SPI.) | ||
255 | */ | ||
256 | oxygen_clear_bits8(chip, OXYGEN_FUNCTION, | ||
257 | OXYGEN_FUNCTION_ENABLE_SPI_4_5); | ||
258 | /* | ||
259 | * Read the subsystem device ID directly from the EEPROM, because the | ||
260 | * chip didn't if the first EEPROM word was overwritten. | ||
261 | */ | ||
262 | subdevice = oxygen_read_eeprom(chip, 2); | ||
263 | /* | ||
264 | * We use only the subsystem device ID for searching because it is | ||
265 | * unique even without the subsystem vendor ID, which may have been | ||
266 | * overwritten in the EEPROM. | ||
267 | */ | ||
268 | for (; ids->vendor; ++ids) | ||
269 | if (ids->subdevice == subdevice && | ||
270 | ids->driver_data != BROKEN_EEPROM_DRIVER_DATA) | ||
271 | return ids; | ||
272 | return NULL; | ||
273 | } | ||
274 | |||
275 | static void oxygen_restore_eeprom(struct oxygen *chip, | ||
276 | const struct pci_device_id *id) | ||
277 | { | ||
278 | if (oxygen_read_eeprom(chip, 0) != OXYGEN_EEPROM_ID) { | ||
279 | /* | ||
280 | * This function gets called only when a known card model has | ||
281 | * been detected, i.e., we know there is a valid subsystem | ||
282 | * product ID at index 2 in the EEPROM. Therefore, we have | ||
283 | * been able to deduce the correct subsystem vendor ID, and | ||
284 | * this is enough information to restore the original EEPROM | ||
285 | * contents. | ||
286 | */ | ||
287 | oxygen_write_eeprom(chip, 1, id->subvendor); | ||
288 | oxygen_write_eeprom(chip, 0, OXYGEN_EEPROM_ID); | ||
289 | |||
290 | oxygen_set_bits8(chip, OXYGEN_MISC, | ||
291 | OXYGEN_MISC_WRITE_PCI_SUBID); | ||
292 | pci_write_config_word(chip->pci, PCI_SUBSYSTEM_VENDOR_ID, | ||
293 | id->subvendor); | ||
294 | pci_write_config_word(chip->pci, PCI_SUBSYSTEM_ID, | ||
295 | id->subdevice); | ||
296 | oxygen_clear_bits8(chip, OXYGEN_MISC, | ||
297 | OXYGEN_MISC_WRITE_PCI_SUBID); | ||
298 | |||
299 | snd_printk(KERN_INFO "EEPROM ID restored\n"); | ||
300 | } | ||
301 | } | ||
302 | |||
246 | static void oxygen_init(struct oxygen *chip) | 303 | static void oxygen_init(struct oxygen *chip) |
247 | { | 304 | { |
248 | unsigned int i; | 305 | unsigned int i; |
@@ -446,30 +503,33 @@ static void oxygen_card_free(struct snd_card *card) | |||
446 | free_irq(chip->irq, chip); | 503 | free_irq(chip->irq, chip); |
447 | flush_scheduled_work(); | 504 | flush_scheduled_work(); |
448 | chip->model.cleanup(chip); | 505 | chip->model.cleanup(chip); |
506 | kfree(chip->model_data); | ||
449 | mutex_destroy(&chip->mutex); | 507 | mutex_destroy(&chip->mutex); |
450 | pci_release_regions(chip->pci); | 508 | pci_release_regions(chip->pci); |
451 | pci_disable_device(chip->pci); | 509 | pci_disable_device(chip->pci); |
452 | } | 510 | } |
453 | 511 | ||
454 | int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, | 512 | int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, |
455 | const struct oxygen_model *model, | 513 | struct module *owner, |
456 | unsigned long driver_data) | 514 | const struct pci_device_id *ids, |
515 | int (*get_model)(struct oxygen *chip, | ||
516 | const struct pci_device_id *id | ||
517 | ) | ||
518 | ) | ||
457 | { | 519 | { |
458 | struct snd_card *card; | 520 | struct snd_card *card; |
459 | struct oxygen *chip; | 521 | struct oxygen *chip; |
522 | const struct pci_device_id *pci_id; | ||
460 | int err; | 523 | int err; |
461 | 524 | ||
462 | card = snd_card_new(index, id, model->owner, | 525 | err = snd_card_create(index, id, owner, sizeof(*chip), &card); |
463 | sizeof *chip + model->model_data_size); | 526 | if (err < 0) |
464 | if (!card) | 527 | return err; |
465 | return -ENOMEM; | ||
466 | 528 | ||
467 | chip = card->private_data; | 529 | chip = card->private_data; |
468 | chip->card = card; | 530 | chip->card = card; |
469 | chip->pci = pci; | 531 | chip->pci = pci; |
470 | chip->irq = -1; | 532 | chip->irq = -1; |
471 | chip->model = *model; | ||
472 | chip->model_data = chip + 1; | ||
473 | spin_lock_init(&chip->reg_lock); | 533 | spin_lock_init(&chip->reg_lock); |
474 | mutex_init(&chip->mutex); | 534 | mutex_init(&chip->mutex); |
475 | INIT_WORK(&chip->spdif_input_bits_work, | 535 | INIT_WORK(&chip->spdif_input_bits_work, |
@@ -481,7 +541,7 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, | |||
481 | if (err < 0) | 541 | if (err < 0) |
482 | goto err_card; | 542 | goto err_card; |
483 | 543 | ||
484 | err = pci_request_regions(pci, model->chip); | 544 | err = pci_request_regions(pci, DRIVER); |
485 | if (err < 0) { | 545 | if (err < 0) { |
486 | snd_printk(KERN_ERR "cannot reserve PCI resources\n"); | 546 | snd_printk(KERN_ERR "cannot reserve PCI resources\n"); |
487 | goto err_pci_enable; | 547 | goto err_pci_enable; |
@@ -495,20 +555,34 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, | |||
495 | } | 555 | } |
496 | chip->addr = pci_resource_start(pci, 0); | 556 | chip->addr = pci_resource_start(pci, 0); |
497 | 557 | ||
558 | pci_id = oxygen_search_pci_id(chip, ids); | ||
559 | if (!pci_id) { | ||
560 | err = -ENODEV; | ||
561 | goto err_pci_regions; | ||
562 | } | ||
563 | oxygen_restore_eeprom(chip, pci_id); | ||
564 | err = get_model(chip, pci_id); | ||
565 | if (err < 0) | ||
566 | goto err_pci_regions; | ||
567 | |||
568 | if (chip->model.model_data_size) { | ||
569 | chip->model_data = kzalloc(chip->model.model_data_size, | ||
570 | GFP_KERNEL); | ||
571 | if (!chip->model_data) { | ||
572 | err = -ENOMEM; | ||
573 | goto err_pci_regions; | ||
574 | } | ||
575 | } | ||
576 | |||
498 | pci_set_master(pci); | 577 | pci_set_master(pci); |
499 | snd_card_set_dev(card, &pci->dev); | 578 | snd_card_set_dev(card, &pci->dev); |
500 | card->private_free = oxygen_card_free; | 579 | card->private_free = oxygen_card_free; |
501 | 580 | ||
502 | if (chip->model.probe) { | ||
503 | err = chip->model.probe(chip, driver_data); | ||
504 | if (err < 0) | ||
505 | goto err_card; | ||
506 | } | ||
507 | oxygen_init(chip); | 581 | oxygen_init(chip); |
508 | chip->model.init(chip); | 582 | chip->model.init(chip); |
509 | 583 | ||
510 | err = request_irq(pci->irq, oxygen_interrupt, IRQF_SHARED, | 584 | err = request_irq(pci->irq, oxygen_interrupt, IRQF_SHARED, |
511 | chip->model.chip, chip); | 585 | DRIVER, chip); |
512 | if (err < 0) { | 586 | if (err < 0) { |
513 | snd_printk(KERN_ERR "cannot grab interrupt %d\n", pci->irq); | 587 | snd_printk(KERN_ERR "cannot grab interrupt %d\n", pci->irq); |
514 | goto err_card; | 588 | goto err_card; |
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c index 6c870c12a177..bc5ce11c8b14 100644 --- a/sound/pci/oxygen/virtuoso.c +++ b/sound/pci/oxygen/virtuoso.c | |||
@@ -112,6 +112,34 @@ | |||
112 | * CS4362A: AD0 <- 0 | 112 | * CS4362A: AD0 <- 0 |
113 | */ | 113 | */ |
114 | 114 | ||
115 | /* | ||
116 | * Xonar Essence STX | ||
117 | * ----------------- | ||
118 | * | ||
119 | * CMI8788: | ||
120 | * | ||
121 | * I²C <-> PCM1792A | ||
122 | * | ||
123 | * GPI 0 <- external power present | ||
124 | * | ||
125 | * GPIO 0 -> enable output to speakers | ||
126 | * GPIO 1 -> route HP to front panel (0) or rear jack (1) | ||
127 | * GPIO 2 -> M0 of CS5381 | ||
128 | * GPIO 3 -> M1 of CS5381 | ||
129 | * GPIO 7 -> route output to speaker jacks (0) or HP (1) | ||
130 | * GPIO 8 -> route input jack to line-in (0) or mic-in (1) | ||
131 | * | ||
132 | * PCM1792A: | ||
133 | * | ||
134 | * AD0 <- 0 | ||
135 | * | ||
136 | * H6 daughterboard | ||
137 | * ---------------- | ||
138 | * | ||
139 | * GPIO 4 <- 0 | ||
140 | * GPIO 5 <- 0 | ||
141 | */ | ||
142 | |||
115 | #include <linux/pci.h> | 143 | #include <linux/pci.h> |
116 | #include <linux/delay.h> | 144 | #include <linux/delay.h> |
117 | #include <linux/mutex.h> | 145 | #include <linux/mutex.h> |
@@ -152,6 +180,7 @@ enum { | |||
152 | MODEL_DX, | 180 | MODEL_DX, |
153 | MODEL_HDAV, /* without daughterboard */ | 181 | MODEL_HDAV, /* without daughterboard */ |
154 | MODEL_HDAV_H6, /* with H6 daughterboard */ | 182 | MODEL_HDAV_H6, /* with H6 daughterboard */ |
183 | MODEL_STX, | ||
155 | }; | 184 | }; |
156 | 185 | ||
157 | static struct pci_device_id xonar_ids[] __devinitdata = { | 186 | static struct pci_device_id xonar_ids[] __devinitdata = { |
@@ -160,6 +189,8 @@ static struct pci_device_id xonar_ids[] __devinitdata = { | |||
160 | { OXYGEN_PCI_SUBID(0x1043, 0x82b7), .driver_data = MODEL_D2X }, | 189 | { OXYGEN_PCI_SUBID(0x1043, 0x82b7), .driver_data = MODEL_D2X }, |
161 | { OXYGEN_PCI_SUBID(0x1043, 0x8314), .driver_data = MODEL_HDAV }, | 190 | { OXYGEN_PCI_SUBID(0x1043, 0x8314), .driver_data = MODEL_HDAV }, |
162 | { OXYGEN_PCI_SUBID(0x1043, 0x834f), .driver_data = MODEL_D1 }, | 191 | { OXYGEN_PCI_SUBID(0x1043, 0x834f), .driver_data = MODEL_D1 }, |
192 | { OXYGEN_PCI_SUBID(0x1043, 0x835c), .driver_data = MODEL_STX }, | ||
193 | { OXYGEN_PCI_SUBID_BROKEN_EEPROM }, | ||
163 | { } | 194 | { } |
164 | }; | 195 | }; |
165 | MODULE_DEVICE_TABLE(pci, xonar_ids); | 196 | MODULE_DEVICE_TABLE(pci, xonar_ids); |
@@ -183,12 +214,14 @@ MODULE_DEVICE_TABLE(pci, xonar_ids); | |||
183 | #define GPIO_HDAV_DB_H6 0x0000 | 214 | #define GPIO_HDAV_DB_H6 0x0000 |
184 | #define GPIO_HDAV_DB_XX 0x0020 | 215 | #define GPIO_HDAV_DB_XX 0x0020 |
185 | 216 | ||
217 | #define GPIO_ST_HP_REAR 0x0002 | ||
218 | #define GPIO_ST_HP 0x0080 | ||
219 | |||
186 | #define I2C_DEVICE_PCM1796(i) (0x98 + ((i) << 1)) /* 10011, ADx=i, /W=0 */ | 220 | #define I2C_DEVICE_PCM1796(i) (0x98 + ((i) << 1)) /* 10011, ADx=i, /W=0 */ |
187 | #define I2C_DEVICE_CS4398 0x9e /* 10011, AD1=1, AD0=1, /W=0 */ | 221 | #define I2C_DEVICE_CS4398 0x9e /* 10011, AD1=1, AD0=1, /W=0 */ |
188 | #define I2C_DEVICE_CS4362A 0x30 /* 001100, AD0=0, /W=0 */ | 222 | #define I2C_DEVICE_CS4362A 0x30 /* 001100, AD0=0, /W=0 */ |
189 | 223 | ||
190 | struct xonar_data { | 224 | struct xonar_data { |
191 | unsigned int model; | ||
192 | unsigned int anti_pop_delay; | 225 | unsigned int anti_pop_delay; |
193 | unsigned int dacs; | 226 | unsigned int dacs; |
194 | u16 output_enable_bit; | 227 | u16 output_enable_bit; |
@@ -334,15 +367,9 @@ static void xonar_d2_init(struct oxygen *chip) | |||
334 | struct xonar_data *data = chip->model_data; | 367 | struct xonar_data *data = chip->model_data; |
335 | 368 | ||
336 | data->anti_pop_delay = 300; | 369 | data->anti_pop_delay = 300; |
370 | data->dacs = 4; | ||
337 | data->output_enable_bit = GPIO_D2_OUTPUT_ENABLE; | 371 | data->output_enable_bit = GPIO_D2_OUTPUT_ENABLE; |
338 | data->pcm1796_oversampling = PCM1796_OS_64; | 372 | data->pcm1796_oversampling = PCM1796_OS_64; |
339 | if (data->model == MODEL_D2X) { | ||
340 | data->ext_power_reg = OXYGEN_GPIO_DATA; | ||
341 | data->ext_power_int_reg = OXYGEN_GPIO_INTERRUPT_MASK; | ||
342 | data->ext_power_bit = GPIO_D2X_EXT_POWER; | ||
343 | oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, | ||
344 | GPIO_D2X_EXT_POWER); | ||
345 | } | ||
346 | 373 | ||
347 | pcm1796_init(chip); | 374 | pcm1796_init(chip); |
348 | 375 | ||
@@ -355,6 +382,18 @@ static void xonar_d2_init(struct oxygen *chip) | |||
355 | snd_component_add(chip->card, "CS5381"); | 382 | snd_component_add(chip->card, "CS5381"); |
356 | } | 383 | } |
357 | 384 | ||
385 | static void xonar_d2x_init(struct oxygen *chip) | ||
386 | { | ||
387 | struct xonar_data *data = chip->model_data; | ||
388 | |||
389 | data->ext_power_reg = OXYGEN_GPIO_DATA; | ||
390 | data->ext_power_int_reg = OXYGEN_GPIO_INTERRUPT_MASK; | ||
391 | data->ext_power_bit = GPIO_D2X_EXT_POWER; | ||
392 | oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_D2X_EXT_POWER); | ||
393 | |||
394 | xonar_d2_init(chip); | ||
395 | } | ||
396 | |||
358 | static void update_cs4362a_volumes(struct oxygen *chip) | 397 | static void update_cs4362a_volumes(struct oxygen *chip) |
359 | { | 398 | { |
360 | u8 mute; | 399 | u8 mute; |
@@ -422,11 +461,6 @@ static void xonar_d1_init(struct oxygen *chip) | |||
422 | data->cs4398_fm = CS4398_FM_SINGLE | CS4398_DEM_NONE | CS4398_DIF_LJUST; | 461 | data->cs4398_fm = CS4398_FM_SINGLE | CS4398_DEM_NONE | CS4398_DIF_LJUST; |
423 | data->cs4362a_fm = CS4362A_FM_SINGLE | | 462 | data->cs4362a_fm = CS4362A_FM_SINGLE | |
424 | CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L; | 463 | CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L; |
425 | if (data->model == MODEL_DX) { | ||
426 | data->ext_power_reg = OXYGEN_GPI_DATA; | ||
427 | data->ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK; | ||
428 | data->ext_power_bit = GPI_DX_EXT_POWER; | ||
429 | } | ||
430 | 464 | ||
431 | oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS, | 465 | oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS, |
432 | OXYGEN_2WIRE_LENGTH_8 | | 466 | OXYGEN_2WIRE_LENGTH_8 | |
@@ -447,6 +481,17 @@ static void xonar_d1_init(struct oxygen *chip) | |||
447 | snd_component_add(chip->card, "CS5361"); | 481 | snd_component_add(chip->card, "CS5361"); |
448 | } | 482 | } |
449 | 483 | ||
484 | static void xonar_dx_init(struct oxygen *chip) | ||
485 | { | ||
486 | struct xonar_data *data = chip->model_data; | ||
487 | |||
488 | data->ext_power_reg = OXYGEN_GPI_DATA; | ||
489 | data->ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK; | ||
490 | data->ext_power_bit = GPI_DX_EXT_POWER; | ||
491 | |||
492 | xonar_d1_init(chip); | ||
493 | } | ||
494 | |||
450 | static void xonar_hdav_init(struct oxygen *chip) | 495 | static void xonar_hdav_init(struct oxygen *chip) |
451 | { | 496 | { |
452 | struct xonar_data *data = chip->model_data; | 497 | struct xonar_data *data = chip->model_data; |
@@ -458,6 +503,7 @@ static void xonar_hdav_init(struct oxygen *chip) | |||
458 | OXYGEN_2WIRE_SPEED_FAST); | 503 | OXYGEN_2WIRE_SPEED_FAST); |
459 | 504 | ||
460 | data->anti_pop_delay = 100; | 505 | data->anti_pop_delay = 100; |
506 | data->dacs = chip->model.private_data == MODEL_HDAV_H6 ? 4 : 1; | ||
461 | data->output_enable_bit = GPIO_DX_OUTPUT_ENABLE; | 507 | data->output_enable_bit = GPIO_DX_OUTPUT_ENABLE; |
462 | data->ext_power_reg = OXYGEN_GPI_DATA; | 508 | data->ext_power_reg = OXYGEN_GPI_DATA; |
463 | data->ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK; | 509 | data->ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK; |
@@ -484,6 +530,36 @@ static void xonar_hdav_init(struct oxygen *chip) | |||
484 | snd_component_add(chip->card, "CS5381"); | 530 | snd_component_add(chip->card, "CS5381"); |
485 | } | 531 | } |
486 | 532 | ||
533 | static void xonar_stx_init(struct oxygen *chip) | ||
534 | { | ||
535 | struct xonar_data *data = chip->model_data; | ||
536 | |||
537 | oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS, | ||
538 | OXYGEN_2WIRE_LENGTH_8 | | ||
539 | OXYGEN_2WIRE_INTERRUPT_MASK | | ||
540 | OXYGEN_2WIRE_SPEED_FAST); | ||
541 | |||
542 | data->anti_pop_delay = 100; | ||
543 | data->dacs = 1; | ||
544 | data->output_enable_bit = GPIO_DX_OUTPUT_ENABLE; | ||
545 | data->ext_power_reg = OXYGEN_GPI_DATA; | ||
546 | data->ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK; | ||
547 | data->ext_power_bit = GPI_DX_EXT_POWER; | ||
548 | data->pcm1796_oversampling = PCM1796_OS_64; | ||
549 | |||
550 | pcm1796_init(chip); | ||
551 | |||
552 | oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, | ||
553 | GPIO_DX_INPUT_ROUTE | GPIO_ST_HP_REAR | GPIO_ST_HP); | ||
554 | oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, | ||
555 | GPIO_DX_INPUT_ROUTE | GPIO_ST_HP_REAR | GPIO_ST_HP); | ||
556 | |||
557 | xonar_common_init(chip); | ||
558 | |||
559 | snd_component_add(chip->card, "PCM1792A"); | ||
560 | snd_component_add(chip->card, "CS5381"); | ||
561 | } | ||
562 | |||
487 | static void xonar_disable_output(struct oxygen *chip) | 563 | static void xonar_disable_output(struct oxygen *chip) |
488 | { | 564 | { |
489 | struct xonar_data *data = chip->model_data; | 565 | struct xonar_data *data = chip->model_data; |
@@ -511,6 +587,11 @@ static void xonar_hdav_cleanup(struct oxygen *chip) | |||
511 | xonar_disable_output(chip); | 587 | xonar_disable_output(chip); |
512 | } | 588 | } |
513 | 589 | ||
590 | static void xonar_st_cleanup(struct oxygen *chip) | ||
591 | { | ||
592 | xonar_disable_output(chip); | ||
593 | } | ||
594 | |||
514 | static void xonar_d2_suspend(struct oxygen *chip) | 595 | static void xonar_d2_suspend(struct oxygen *chip) |
515 | { | 596 | { |
516 | xonar_d2_cleanup(chip); | 597 | xonar_d2_cleanup(chip); |
@@ -527,6 +608,11 @@ static void xonar_hdav_suspend(struct oxygen *chip) | |||
527 | msleep(2); | 608 | msleep(2); |
528 | } | 609 | } |
529 | 610 | ||
611 | static void xonar_st_suspend(struct oxygen *chip) | ||
612 | { | ||
613 | xonar_st_cleanup(chip); | ||
614 | } | ||
615 | |||
530 | static void xonar_d2_resume(struct oxygen *chip) | 616 | static void xonar_d2_resume(struct oxygen *chip) |
531 | { | 617 | { |
532 | pcm1796_init(chip); | 618 | pcm1796_init(chip); |
@@ -554,6 +640,12 @@ static void xonar_hdav_resume(struct oxygen *chip) | |||
554 | xonar_enable_output(chip); | 640 | xonar_enable_output(chip); |
555 | } | 641 | } |
556 | 642 | ||
643 | static void xonar_st_resume(struct oxygen *chip) | ||
644 | { | ||
645 | pcm1796_init(chip); | ||
646 | xonar_enable_output(chip); | ||
647 | } | ||
648 | |||
557 | static void xonar_hdav_pcm_hardware_filter(unsigned int channel, | 649 | static void xonar_hdav_pcm_hardware_filter(unsigned int channel, |
558 | struct snd_pcm_hardware *hardware) | 650 | struct snd_pcm_hardware *hardware) |
559 | { | 651 | { |
@@ -733,6 +825,72 @@ static const struct snd_kcontrol_new front_panel_switch = { | |||
733 | .private_value = GPIO_DX_FRONT_PANEL, | 825 | .private_value = GPIO_DX_FRONT_PANEL, |
734 | }; | 826 | }; |
735 | 827 | ||
828 | static int st_output_switch_info(struct snd_kcontrol *ctl, | ||
829 | struct snd_ctl_elem_info *info) | ||
830 | { | ||
831 | static const char *const names[3] = { | ||
832 | "Speakers", "Headphones", "FP Headphones" | ||
833 | }; | ||
834 | |||
835 | info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
836 | info->count = 1; | ||
837 | info->value.enumerated.items = 3; | ||
838 | if (info->value.enumerated.item >= 3) | ||
839 | info->value.enumerated.item = 2; | ||
840 | strcpy(info->value.enumerated.name, names[info->value.enumerated.item]); | ||
841 | return 0; | ||
842 | } | ||
843 | |||
844 | static int st_output_switch_get(struct snd_kcontrol *ctl, | ||
845 | struct snd_ctl_elem_value *value) | ||
846 | { | ||
847 | struct oxygen *chip = ctl->private_data; | ||
848 | u16 gpio; | ||
849 | |||
850 | gpio = oxygen_read16(chip, OXYGEN_GPIO_DATA); | ||
851 | if (!(gpio & GPIO_ST_HP)) | ||
852 | value->value.enumerated.item[0] = 0; | ||
853 | else if (gpio & GPIO_ST_HP_REAR) | ||
854 | value->value.enumerated.item[0] = 1; | ||
855 | else | ||
856 | value->value.enumerated.item[0] = 2; | ||
857 | return 0; | ||
858 | } | ||
859 | |||
860 | |||
861 | static int st_output_switch_put(struct snd_kcontrol *ctl, | ||
862 | struct snd_ctl_elem_value *value) | ||
863 | { | ||
864 | struct oxygen *chip = ctl->private_data; | ||
865 | u16 gpio_old, gpio; | ||
866 | |||
867 | mutex_lock(&chip->mutex); | ||
868 | gpio_old = oxygen_read16(chip, OXYGEN_GPIO_DATA); | ||
869 | gpio = gpio_old; | ||
870 | switch (value->value.enumerated.item[0]) { | ||
871 | case 0: | ||
872 | gpio &= ~(GPIO_ST_HP | GPIO_ST_HP_REAR); | ||
873 | break; | ||
874 | case 1: | ||
875 | gpio |= GPIO_ST_HP | GPIO_ST_HP_REAR; | ||
876 | break; | ||
877 | case 2: | ||
878 | gpio = (gpio | GPIO_ST_HP) & ~GPIO_ST_HP_REAR; | ||
879 | break; | ||
880 | } | ||
881 | oxygen_write16(chip, OXYGEN_GPIO_DATA, gpio); | ||
882 | mutex_unlock(&chip->mutex); | ||
883 | return gpio != gpio_old; | ||
884 | } | ||
885 | |||
886 | static const struct snd_kcontrol_new st_output_switch = { | ||
887 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
888 | .name = "Analog Output", | ||
889 | .info = st_output_switch_info, | ||
890 | .get = st_output_switch_get, | ||
891 | .put = st_output_switch_put, | ||
892 | }; | ||
893 | |||
736 | static void xonar_line_mic_ac97_switch(struct oxygen *chip, | 894 | static void xonar_line_mic_ac97_switch(struct oxygen *chip, |
737 | unsigned int reg, unsigned int mute) | 895 | unsigned int reg, unsigned int mute) |
738 | { | 896 | { |
@@ -745,8 +903,8 @@ static void xonar_line_mic_ac97_switch(struct oxygen *chip, | |||
745 | } | 903 | } |
746 | } | 904 | } |
747 | 905 | ||
748 | static const DECLARE_TLV_DB_SCALE(pcm1796_db_scale, -12000, 50, 0); | 906 | static const DECLARE_TLV_DB_SCALE(pcm1796_db_scale, -6000, 50, 0); |
749 | static const DECLARE_TLV_DB_SCALE(cs4362a_db_scale, -12700, 100, 0); | 907 | static const DECLARE_TLV_DB_SCALE(cs4362a_db_scale, -6000, 100, 0); |
750 | 908 | ||
751 | static int xonar_d2_control_filter(struct snd_kcontrol_new *template) | 909 | static int xonar_d2_control_filter(struct snd_kcontrol_new *template) |
752 | { | 910 | { |
@@ -763,6 +921,15 @@ static int xonar_d1_control_filter(struct snd_kcontrol_new *template) | |||
763 | return 0; | 921 | return 0; |
764 | } | 922 | } |
765 | 923 | ||
924 | static int xonar_st_control_filter(struct snd_kcontrol_new *template) | ||
925 | { | ||
926 | if (!strncmp(template->name, "CD Capture ", 11)) | ||
927 | return 1; /* no CD input */ | ||
928 | if (!strcmp(template->name, "Stereo Upmixing")) | ||
929 | return 1; /* stereo only - we don't need upmixing */ | ||
930 | return 0; | ||
931 | } | ||
932 | |||
766 | static int xonar_d2_mixer_init(struct oxygen *chip) | 933 | static int xonar_d2_mixer_init(struct oxygen *chip) |
767 | { | 934 | { |
768 | return snd_ctl_add(chip->card, snd_ctl_new1(&alt_switch, chip)); | 935 | return snd_ctl_add(chip->card, snd_ctl_new1(&alt_switch, chip)); |
@@ -773,51 +940,14 @@ static int xonar_d1_mixer_init(struct oxygen *chip) | |||
773 | return snd_ctl_add(chip->card, snd_ctl_new1(&front_panel_switch, chip)); | 940 | return snd_ctl_add(chip->card, snd_ctl_new1(&front_panel_switch, chip)); |
774 | } | 941 | } |
775 | 942 | ||
776 | static int xonar_model_probe(struct oxygen *chip, unsigned long driver_data) | 943 | static int xonar_st_mixer_init(struct oxygen *chip) |
777 | { | 944 | { |
778 | static const char *const names[] = { | 945 | return snd_ctl_add(chip->card, snd_ctl_new1(&st_output_switch, chip)); |
779 | [MODEL_D1] = "Xonar D1", | ||
780 | [MODEL_DX] = "Xonar DX", | ||
781 | [MODEL_D2] = "Xonar D2", | ||
782 | [MODEL_D2X] = "Xonar D2X", | ||
783 | [MODEL_HDAV] = "Xonar HDAV1.3", | ||
784 | [MODEL_HDAV_H6] = "Xonar HDAV1.3+H6", | ||
785 | }; | ||
786 | static const u8 dacs[] = { | ||
787 | [MODEL_D1] = 2, | ||
788 | [MODEL_DX] = 2, | ||
789 | [MODEL_D2] = 4, | ||
790 | [MODEL_D2X] = 4, | ||
791 | [MODEL_HDAV] = 1, | ||
792 | [MODEL_HDAV_H6] = 4, | ||
793 | }; | ||
794 | struct xonar_data *data = chip->model_data; | ||
795 | |||
796 | data->model = driver_data; | ||
797 | if (data->model == MODEL_HDAV) { | ||
798 | oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, | ||
799 | GPIO_HDAV_DB_MASK); | ||
800 | switch (oxygen_read16(chip, OXYGEN_GPIO_DATA) & | ||
801 | GPIO_HDAV_DB_MASK) { | ||
802 | case GPIO_HDAV_DB_H6: | ||
803 | data->model = MODEL_HDAV_H6; | ||
804 | break; | ||
805 | case GPIO_HDAV_DB_XX: | ||
806 | snd_printk(KERN_ERR "unknown daughterboard\n"); | ||
807 | return -ENODEV; | ||
808 | } | ||
809 | } | ||
810 | |||
811 | data->dacs = dacs[data->model]; | ||
812 | chip->model.shortname = names[data->model]; | ||
813 | return 0; | ||
814 | } | 946 | } |
815 | 947 | ||
816 | static const struct oxygen_model model_xonar_d2 = { | 948 | static const struct oxygen_model model_xonar_d2 = { |
817 | .longname = "Asus Virtuoso 200", | 949 | .longname = "Asus Virtuoso 200", |
818 | .chip = "AV200", | 950 | .chip = "AV200", |
819 | .owner = THIS_MODULE, | ||
820 | .probe = xonar_model_probe, | ||
821 | .init = xonar_d2_init, | 951 | .init = xonar_d2_init, |
822 | .control_filter = xonar_d2_control_filter, | 952 | .control_filter = xonar_d2_control_filter, |
823 | .mixer_init = xonar_d2_mixer_init, | 953 | .mixer_init = xonar_d2_mixer_init, |
@@ -837,8 +967,8 @@ static const struct oxygen_model model_xonar_d2 = { | |||
837 | MIDI_OUTPUT | | 967 | MIDI_OUTPUT | |
838 | MIDI_INPUT, | 968 | MIDI_INPUT, |
839 | .dac_channels = 8, | 969 | .dac_channels = 8, |
840 | .dac_volume_min = 0x0f, | 970 | .dac_volume_min = 255 - 2*60, |
841 | .dac_volume_max = 0xff, | 971 | .dac_volume_max = 255, |
842 | .misc_flags = OXYGEN_MISC_MIDI, | 972 | .misc_flags = OXYGEN_MISC_MIDI, |
843 | .function_flags = OXYGEN_FUNCTION_SPI | | 973 | .function_flags = OXYGEN_FUNCTION_SPI | |
844 | OXYGEN_FUNCTION_ENABLE_SPI_4_5, | 974 | OXYGEN_FUNCTION_ENABLE_SPI_4_5, |
@@ -849,8 +979,6 @@ static const struct oxygen_model model_xonar_d2 = { | |||
849 | static const struct oxygen_model model_xonar_d1 = { | 979 | static const struct oxygen_model model_xonar_d1 = { |
850 | .longname = "Asus Virtuoso 100", | 980 | .longname = "Asus Virtuoso 100", |
851 | .chip = "AV200", | 981 | .chip = "AV200", |
852 | .owner = THIS_MODULE, | ||
853 | .probe = xonar_model_probe, | ||
854 | .init = xonar_d1_init, | 982 | .init = xonar_d1_init, |
855 | .control_filter = xonar_d1_control_filter, | 983 | .control_filter = xonar_d1_control_filter, |
856 | .mixer_init = xonar_d1_mixer_init, | 984 | .mixer_init = xonar_d1_mixer_init, |
@@ -868,7 +996,7 @@ static const struct oxygen_model model_xonar_d1 = { | |||
868 | PLAYBACK_1_TO_SPDIF | | 996 | PLAYBACK_1_TO_SPDIF | |
869 | CAPTURE_0_FROM_I2S_2, | 997 | CAPTURE_0_FROM_I2S_2, |
870 | .dac_channels = 8, | 998 | .dac_channels = 8, |
871 | .dac_volume_min = 0, | 999 | .dac_volume_min = 127 - 60, |
872 | .dac_volume_max = 127, | 1000 | .dac_volume_max = 127, |
873 | .function_flags = OXYGEN_FUNCTION_2WIRE, | 1001 | .function_flags = OXYGEN_FUNCTION_2WIRE, |
874 | .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | 1002 | .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, |
@@ -878,8 +1006,6 @@ static const struct oxygen_model model_xonar_d1 = { | |||
878 | static const struct oxygen_model model_xonar_hdav = { | 1006 | static const struct oxygen_model model_xonar_hdav = { |
879 | .longname = "Asus Virtuoso 200", | 1007 | .longname = "Asus Virtuoso 200", |
880 | .chip = "AV200", | 1008 | .chip = "AV200", |
881 | .owner = THIS_MODULE, | ||
882 | .probe = xonar_model_probe, | ||
883 | .init = xonar_hdav_init, | 1009 | .init = xonar_hdav_init, |
884 | .cleanup = xonar_hdav_cleanup, | 1010 | .cleanup = xonar_hdav_cleanup, |
885 | .suspend = xonar_hdav_suspend, | 1011 | .suspend = xonar_hdav_suspend, |
@@ -897,16 +1023,43 @@ static const struct oxygen_model model_xonar_hdav = { | |||
897 | PLAYBACK_1_TO_SPDIF | | 1023 | PLAYBACK_1_TO_SPDIF | |
898 | CAPTURE_0_FROM_I2S_2, | 1024 | CAPTURE_0_FROM_I2S_2, |
899 | .dac_channels = 8, | 1025 | .dac_channels = 8, |
900 | .dac_volume_min = 0x0f, | 1026 | .dac_volume_min = 255 - 2*60, |
901 | .dac_volume_max = 0xff, | 1027 | .dac_volume_max = 255, |
902 | .misc_flags = OXYGEN_MISC_MIDI, | 1028 | .misc_flags = OXYGEN_MISC_MIDI, |
903 | .function_flags = OXYGEN_FUNCTION_2WIRE, | 1029 | .function_flags = OXYGEN_FUNCTION_2WIRE, |
904 | .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | 1030 | .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, |
905 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | 1031 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, |
906 | }; | 1032 | }; |
907 | 1033 | ||
908 | static int __devinit xonar_probe(struct pci_dev *pci, | 1034 | static const struct oxygen_model model_xonar_st = { |
909 | const struct pci_device_id *pci_id) | 1035 | .longname = "Asus Virtuoso 100", |
1036 | .chip = "AV200", | ||
1037 | .init = xonar_stx_init, | ||
1038 | .control_filter = xonar_st_control_filter, | ||
1039 | .mixer_init = xonar_st_mixer_init, | ||
1040 | .cleanup = xonar_st_cleanup, | ||
1041 | .suspend = xonar_st_suspend, | ||
1042 | .resume = xonar_st_resume, | ||
1043 | .set_dac_params = set_pcm1796_params, | ||
1044 | .set_adc_params = set_cs53x1_params, | ||
1045 | .update_dac_volume = update_pcm1796_volume, | ||
1046 | .update_dac_mute = update_pcm1796_mute, | ||
1047 | .ac97_switch = xonar_line_mic_ac97_switch, | ||
1048 | .dac_tlv = pcm1796_db_scale, | ||
1049 | .model_data_size = sizeof(struct xonar_data), | ||
1050 | .device_config = PLAYBACK_0_TO_I2S | | ||
1051 | PLAYBACK_1_TO_SPDIF | | ||
1052 | CAPTURE_0_FROM_I2S_2, | ||
1053 | .dac_channels = 2, | ||
1054 | .dac_volume_min = 255 - 2*60, | ||
1055 | .dac_volume_max = 255, | ||
1056 | .function_flags = OXYGEN_FUNCTION_2WIRE, | ||
1057 | .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | ||
1058 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | ||
1059 | }; | ||
1060 | |||
1061 | static int __devinit get_xonar_model(struct oxygen *chip, | ||
1062 | const struct pci_device_id *id) | ||
910 | { | 1063 | { |
911 | static const struct oxygen_model *const models[] = { | 1064 | static const struct oxygen_model *const models[] = { |
912 | [MODEL_D1] = &model_xonar_d1, | 1065 | [MODEL_D1] = &model_xonar_d1, |
@@ -914,7 +1067,57 @@ static int __devinit xonar_probe(struct pci_dev *pci, | |||
914 | [MODEL_D2] = &model_xonar_d2, | 1067 | [MODEL_D2] = &model_xonar_d2, |
915 | [MODEL_D2X] = &model_xonar_d2, | 1068 | [MODEL_D2X] = &model_xonar_d2, |
916 | [MODEL_HDAV] = &model_xonar_hdav, | 1069 | [MODEL_HDAV] = &model_xonar_hdav, |
1070 | [MODEL_STX] = &model_xonar_st, | ||
917 | }; | 1071 | }; |
1072 | static const char *const names[] = { | ||
1073 | [MODEL_D1] = "Xonar D1", | ||
1074 | [MODEL_DX] = "Xonar DX", | ||
1075 | [MODEL_D2] = "Xonar D2", | ||
1076 | [MODEL_D2X] = "Xonar D2X", | ||
1077 | [MODEL_HDAV] = "Xonar HDAV1.3", | ||
1078 | [MODEL_HDAV_H6] = "Xonar HDAV1.3+H6", | ||
1079 | [MODEL_STX] = "Xonar Essence STX", | ||
1080 | }; | ||
1081 | unsigned int model = id->driver_data; | ||
1082 | |||
1083 | if (model >= ARRAY_SIZE(models) || !models[model]) | ||
1084 | return -EINVAL; | ||
1085 | chip->model = *models[model]; | ||
1086 | |||
1087 | switch (model) { | ||
1088 | case MODEL_D2X: | ||
1089 | chip->model.init = xonar_d2x_init; | ||
1090 | break; | ||
1091 | case MODEL_DX: | ||
1092 | chip->model.init = xonar_dx_init; | ||
1093 | break; | ||
1094 | case MODEL_HDAV: | ||
1095 | oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, | ||
1096 | GPIO_HDAV_DB_MASK); | ||
1097 | switch (oxygen_read16(chip, OXYGEN_GPIO_DATA) & | ||
1098 | GPIO_HDAV_DB_MASK) { | ||
1099 | case GPIO_HDAV_DB_H6: | ||
1100 | model = MODEL_HDAV_H6; | ||
1101 | break; | ||
1102 | case GPIO_HDAV_DB_XX: | ||
1103 | snd_printk(KERN_ERR "unknown daughterboard\n"); | ||
1104 | return -ENODEV; | ||
1105 | } | ||
1106 | break; | ||
1107 | case MODEL_STX: | ||
1108 | oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, | ||
1109 | GPIO_HDAV_DB_MASK); | ||
1110 | break; | ||
1111 | } | ||
1112 | |||
1113 | chip->model.shortname = names[model]; | ||
1114 | chip->model.private_data = model; | ||
1115 | return 0; | ||
1116 | } | ||
1117 | |||
1118 | static int __devinit xonar_probe(struct pci_dev *pci, | ||
1119 | const struct pci_device_id *pci_id) | ||
1120 | { | ||
918 | static int dev; | 1121 | static int dev; |
919 | int err; | 1122 | int err; |
920 | 1123 | ||
@@ -924,10 +1127,8 @@ static int __devinit xonar_probe(struct pci_dev *pci, | |||
924 | ++dev; | 1127 | ++dev; |
925 | return -ENOENT; | 1128 | return -ENOENT; |
926 | } | 1129 | } |
927 | BUG_ON(pci_id->driver_data >= ARRAY_SIZE(models)); | 1130 | err = oxygen_pci_probe(pci, index[dev], id[dev], THIS_MODULE, |
928 | err = oxygen_pci_probe(pci, index[dev], id[dev], | 1131 | xonar_ids, get_xonar_model); |
929 | models[pci_id->driver_data], | ||
930 | pci_id->driver_data); | ||
931 | if (err >= 0) | 1132 | if (err >= 0) |
932 | ++dev; | 1133 | ++dev; |
933 | return err; | 1134 | return err; |
diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c index 27cf2c28d113..80e064a3efff 100644 --- a/sound/pci/pcxhr/pcxhr.c +++ b/sound/pci/pcxhr/pcxhr.c | |||
@@ -1334,6 +1334,40 @@ static void pcxhr_proc_sync(struct snd_info_entry *entry, | |||
1334 | snd_iprintf(buffer, "\n"); | 1334 | snd_iprintf(buffer, "\n"); |
1335 | } | 1335 | } |
1336 | 1336 | ||
1337 | static void pcxhr_proc_gpio_read(struct snd_info_entry *entry, | ||
1338 | struct snd_info_buffer *buffer) | ||
1339 | { | ||
1340 | struct snd_pcxhr *chip = entry->private_data; | ||
1341 | struct pcxhr_mgr *mgr = chip->mgr; | ||
1342 | /* commands available when embedded DSP is running */ | ||
1343 | if (mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX)) { | ||
1344 | /* gpio ports on stereo boards only available */ | ||
1345 | int value = 0; | ||
1346 | hr222_read_gpio(mgr, 1, &value); /* GPI */ | ||
1347 | snd_iprintf(buffer, "GPI: 0x%x\n", value); | ||
1348 | hr222_read_gpio(mgr, 0, &value); /* GP0 */ | ||
1349 | snd_iprintf(buffer, "GPO: 0x%x\n", value); | ||
1350 | } else | ||
1351 | snd_iprintf(buffer, "no firmware loaded\n"); | ||
1352 | snd_iprintf(buffer, "\n"); | ||
1353 | } | ||
1354 | static void pcxhr_proc_gpo_write(struct snd_info_entry *entry, | ||
1355 | struct snd_info_buffer *buffer) | ||
1356 | { | ||
1357 | struct snd_pcxhr *chip = entry->private_data; | ||
1358 | struct pcxhr_mgr *mgr = chip->mgr; | ||
1359 | char line[64]; | ||
1360 | int value; | ||
1361 | /* commands available when embedded DSP is running */ | ||
1362 | if (!(mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX))) | ||
1363 | return; | ||
1364 | while (!snd_info_get_line(buffer, line, sizeof(line))) { | ||
1365 | if (sscanf(line, "GPO: 0x%x", &value) != 1) | ||
1366 | continue; | ||
1367 | hr222_write_gpo(mgr, value); /* GP0 */ | ||
1368 | } | ||
1369 | } | ||
1370 | |||
1337 | static void __devinit pcxhr_proc_init(struct snd_pcxhr *chip) | 1371 | static void __devinit pcxhr_proc_init(struct snd_pcxhr *chip) |
1338 | { | 1372 | { |
1339 | struct snd_info_entry *entry; | 1373 | struct snd_info_entry *entry; |
@@ -1342,6 +1376,13 @@ static void __devinit pcxhr_proc_init(struct snd_pcxhr *chip) | |||
1342 | snd_info_set_text_ops(entry, chip, pcxhr_proc_info); | 1376 | snd_info_set_text_ops(entry, chip, pcxhr_proc_info); |
1343 | if (! snd_card_proc_new(chip->card, "sync", &entry)) | 1377 | if (! snd_card_proc_new(chip->card, "sync", &entry)) |
1344 | snd_info_set_text_ops(entry, chip, pcxhr_proc_sync); | 1378 | snd_info_set_text_ops(entry, chip, pcxhr_proc_sync); |
1379 | /* gpio available on stereo sound cards only */ | ||
1380 | if (chip->mgr->is_hr_stereo && | ||
1381 | !snd_card_proc_new(chip->card, "gpio", &entry)) { | ||
1382 | snd_info_set_text_ops(entry, chip, pcxhr_proc_gpio_read); | ||
1383 | entry->c.text.write = pcxhr_proc_gpo_write; | ||
1384 | entry->mode |= S_IWUSR; | ||
1385 | } | ||
1345 | } | 1386 | } |
1346 | /* end of proc interface */ | 1387 | /* end of proc interface */ |
1347 | 1388 | ||
@@ -1510,12 +1551,12 @@ static int __devinit pcxhr_probe(struct pci_dev *pci, | |||
1510 | 1551 | ||
1511 | snprintf(tmpid, sizeof(tmpid), "%s-%d", | 1552 | snprintf(tmpid, sizeof(tmpid), "%s-%d", |
1512 | id[dev] ? id[dev] : card_name, i); | 1553 | id[dev] ? id[dev] : card_name, i); |
1513 | card = snd_card_new(idx, tmpid, THIS_MODULE, 0); | 1554 | err = snd_card_create(idx, tmpid, THIS_MODULE, 0, &card); |
1514 | 1555 | ||
1515 | if (! card) { | 1556 | if (err < 0) { |
1516 | snd_printk(KERN_ERR "cannot allocate the card %d\n", i); | 1557 | snd_printk(KERN_ERR "cannot allocate the card %d\n", i); |
1517 | pcxhr_free(mgr); | 1558 | pcxhr_free(mgr); |
1518 | return -ENOMEM; | 1559 | return err; |
1519 | } | 1560 | } |
1520 | 1561 | ||
1521 | strcpy(card->driver, DRIVER_NAME); | 1562 | strcpy(card->driver, DRIVER_NAME); |
diff --git a/sound/pci/pcxhr/pcxhr.h b/sound/pci/pcxhr/pcxhr.h index 69d87dee6995..bda776c49884 100644 --- a/sound/pci/pcxhr/pcxhr.h +++ b/sound/pci/pcxhr/pcxhr.h | |||
@@ -27,8 +27,8 @@ | |||
27 | #include <linux/mutex.h> | 27 | #include <linux/mutex.h> |
28 | #include <sound/pcm.h> | 28 | #include <sound/pcm.h> |
29 | 29 | ||
30 | #define PCXHR_DRIVER_VERSION 0x000905 /* 0.9.5 */ | 30 | #define PCXHR_DRIVER_VERSION 0x000906 /* 0.9.6 */ |
31 | #define PCXHR_DRIVER_VERSION_STRING "0.9.5" /* 0.9.5 */ | 31 | #define PCXHR_DRIVER_VERSION_STRING "0.9.6" /* 0.9.6 */ |
32 | 32 | ||
33 | 33 | ||
34 | #define PCXHR_MAX_CARDS 6 | 34 | #define PCXHR_MAX_CARDS 6 |
@@ -124,6 +124,7 @@ struct pcxhr_mgr { | |||
124 | 124 | ||
125 | unsigned char xlx_cfg; /* copy of PCXHR_XLX_CFG register */ | 125 | unsigned char xlx_cfg; /* copy of PCXHR_XLX_CFG register */ |
126 | unsigned char xlx_selmic; /* copy of PCXHR_XLX_SELMIC register */ | 126 | unsigned char xlx_selmic; /* copy of PCXHR_XLX_SELMIC register */ |
127 | unsigned char dsp_reset; /* copy of PCXHR_DSP_RESET register */ | ||
127 | }; | 128 | }; |
128 | 129 | ||
129 | 130 | ||
diff --git a/sound/pci/pcxhr/pcxhr_core.h b/sound/pci/pcxhr/pcxhr_core.h index bbbd66d13a64..be0173796cdb 100644 --- a/sound/pci/pcxhr/pcxhr_core.h +++ b/sound/pci/pcxhr/pcxhr_core.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for Digigram pcxhr compatible soundcards | 2 | * Driver for Digigram pcxhr compatible soundcards |
3 | * | 3 | * |
4 | * low level interface with interrupt ans message handling | 4 | * low level interface with interrupt and message handling |
5 | * | 5 | * |
6 | * Copyright (c) 2004 by Digigram <alsa@digigram.com> | 6 | * Copyright (c) 2004 by Digigram <alsa@digigram.com> |
7 | * | 7 | * |
diff --git a/sound/pci/pcxhr/pcxhr_hwdep.c b/sound/pci/pcxhr/pcxhr_hwdep.c index 592743a298b0..17cb1233a903 100644 --- a/sound/pci/pcxhr/pcxhr_hwdep.c +++ b/sound/pci/pcxhr/pcxhr_hwdep.c | |||
@@ -471,16 +471,6 @@ static int pcxhr_hwdep_dsp_load(struct snd_hwdep *hw, | |||
471 | return 0; | 471 | return 0; |
472 | } | 472 | } |
473 | 473 | ||
474 | static int pcxhr_hwdep_open(struct snd_hwdep *hw, struct file *file) | ||
475 | { | ||
476 | return 0; | ||
477 | } | ||
478 | |||
479 | static int pcxhr_hwdep_release(struct snd_hwdep *hw, struct file *file) | ||
480 | { | ||
481 | return 0; | ||
482 | } | ||
483 | |||
484 | int pcxhr_setup_firmware(struct pcxhr_mgr *mgr) | 474 | int pcxhr_setup_firmware(struct pcxhr_mgr *mgr) |
485 | { | 475 | { |
486 | int err; | 476 | int err; |
@@ -495,8 +485,6 @@ int pcxhr_setup_firmware(struct pcxhr_mgr *mgr) | |||
495 | 485 | ||
496 | hw->iface = SNDRV_HWDEP_IFACE_PCXHR; | 486 | hw->iface = SNDRV_HWDEP_IFACE_PCXHR; |
497 | hw->private_data = mgr; | 487 | hw->private_data = mgr; |
498 | hw->ops.open = pcxhr_hwdep_open; | ||
499 | hw->ops.release = pcxhr_hwdep_release; | ||
500 | hw->ops.dsp_status = pcxhr_hwdep_dsp_status; | 488 | hw->ops.dsp_status = pcxhr_hwdep_dsp_status; |
501 | hw->ops.dsp_load = pcxhr_hwdep_dsp_load; | 489 | hw->ops.dsp_load = pcxhr_hwdep_dsp_load; |
502 | hw->exclusive = 1; | 490 | hw->exclusive = 1; |
diff --git a/sound/pci/pcxhr/pcxhr_mix22.c b/sound/pci/pcxhr/pcxhr_mix22.c index ff019126b672..1cb82c0a9cb3 100644 --- a/sound/pci/pcxhr/pcxhr_mix22.c +++ b/sound/pci/pcxhr/pcxhr_mix22.c | |||
@@ -53,6 +53,8 @@ | |||
53 | #define PCXHR_DSP_RESET_DSP 0x01 | 53 | #define PCXHR_DSP_RESET_DSP 0x01 |
54 | #define PCXHR_DSP_RESET_MUTE 0x02 | 54 | #define PCXHR_DSP_RESET_MUTE 0x02 |
55 | #define PCXHR_DSP_RESET_CODEC 0x08 | 55 | #define PCXHR_DSP_RESET_CODEC 0x08 |
56 | #define PCXHR_DSP_RESET_GPO_OFFSET 5 | ||
57 | #define PCXHR_DSP_RESET_GPO_MASK 0x60 | ||
56 | 58 | ||
57 | /* values for PCHR_XLX_CFG register */ | 59 | /* values for PCHR_XLX_CFG register */ |
58 | #define PCXHR_CFG_SYNCDSP_MASK 0x80 | 60 | #define PCXHR_CFG_SYNCDSP_MASK 0x80 |
@@ -81,6 +83,8 @@ | |||
81 | /* values for PCHR_XLX_STATUS register - READ */ | 83 | /* values for PCHR_XLX_STATUS register - READ */ |
82 | #define PCXHR_STAT_SRC_LOCK 0x01 | 84 | #define PCXHR_STAT_SRC_LOCK 0x01 |
83 | #define PCXHR_STAT_LEVEL_IN 0x02 | 85 | #define PCXHR_STAT_LEVEL_IN 0x02 |
86 | #define PCXHR_STAT_GPI_OFFSET 2 | ||
87 | #define PCXHR_STAT_GPI_MASK 0x0C | ||
84 | #define PCXHR_STAT_MIC_CAPS 0x10 | 88 | #define PCXHR_STAT_MIC_CAPS 0x10 |
85 | /* values for PCHR_XLX_STATUS register - WRITE */ | 89 | /* values for PCHR_XLX_STATUS register - WRITE */ |
86 | #define PCXHR_STAT_FREQ_SYNC_MASK 0x01 | 90 | #define PCXHR_STAT_FREQ_SYNC_MASK 0x01 |
@@ -291,10 +295,11 @@ int hr222_sub_init(struct pcxhr_mgr *mgr) | |||
291 | PCXHR_OUTPB(mgr, PCXHR_DSP_RESET, | 295 | PCXHR_OUTPB(mgr, PCXHR_DSP_RESET, |
292 | PCXHR_DSP_RESET_DSP); | 296 | PCXHR_DSP_RESET_DSP); |
293 | msleep(5); | 297 | msleep(5); |
294 | PCXHR_OUTPB(mgr, PCXHR_DSP_RESET, | 298 | mgr->dsp_reset = PCXHR_DSP_RESET_DSP | |
295 | PCXHR_DSP_RESET_DSP | | 299 | PCXHR_DSP_RESET_MUTE | |
296 | PCXHR_DSP_RESET_MUTE | | 300 | PCXHR_DSP_RESET_CODEC; |
297 | PCXHR_DSP_RESET_CODEC); | 301 | PCXHR_OUTPB(mgr, PCXHR_DSP_RESET, mgr->dsp_reset); |
302 | /* hr222_write_gpo(mgr, 0); does the same */ | ||
298 | msleep(5); | 303 | msleep(5); |
299 | 304 | ||
300 | /* config AKM */ | 305 | /* config AKM */ |
@@ -496,6 +501,33 @@ int hr222_get_external_clock(struct pcxhr_mgr *mgr, | |||
496 | } | 501 | } |
497 | 502 | ||
498 | 503 | ||
504 | int hr222_read_gpio(struct pcxhr_mgr *mgr, int is_gpi, int *value) | ||
505 | { | ||
506 | if (is_gpi) { | ||
507 | unsigned char reg = PCXHR_INPB(mgr, PCXHR_XLX_STATUS); | ||
508 | *value = (int)(reg & PCXHR_STAT_GPI_MASK) >> | ||
509 | PCXHR_STAT_GPI_OFFSET; | ||
510 | } else { | ||
511 | *value = (int)(mgr->dsp_reset & PCXHR_DSP_RESET_GPO_MASK) >> | ||
512 | PCXHR_DSP_RESET_GPO_OFFSET; | ||
513 | } | ||
514 | return 0; | ||
515 | } | ||
516 | |||
517 | |||
518 | int hr222_write_gpo(struct pcxhr_mgr *mgr, int value) | ||
519 | { | ||
520 | unsigned char reg = mgr->dsp_reset & ~PCXHR_DSP_RESET_GPO_MASK; | ||
521 | |||
522 | reg |= (unsigned char)(value << PCXHR_DSP_RESET_GPO_OFFSET) & | ||
523 | PCXHR_DSP_RESET_GPO_MASK; | ||
524 | |||
525 | PCXHR_OUTPB(mgr, PCXHR_DSP_RESET, reg); | ||
526 | mgr->dsp_reset = reg; | ||
527 | return 0; | ||
528 | } | ||
529 | |||
530 | |||
499 | int hr222_update_analog_audio_level(struct snd_pcxhr *chip, | 531 | int hr222_update_analog_audio_level(struct snd_pcxhr *chip, |
500 | int is_capture, int channel) | 532 | int is_capture, int channel) |
501 | { | 533 | { |
diff --git a/sound/pci/pcxhr/pcxhr_mix22.h b/sound/pci/pcxhr/pcxhr_mix22.h index 6b318b2f0100..5a37a0007e8f 100644 --- a/sound/pci/pcxhr/pcxhr_mix22.h +++ b/sound/pci/pcxhr/pcxhr_mix22.h | |||
@@ -32,6 +32,9 @@ int hr222_get_external_clock(struct pcxhr_mgr *mgr, | |||
32 | enum pcxhr_clock_type clock_type, | 32 | enum pcxhr_clock_type clock_type, |
33 | int *sample_rate); | 33 | int *sample_rate); |
34 | 34 | ||
35 | int hr222_read_gpio(struct pcxhr_mgr *mgr, int is_gpi, int *value); | ||
36 | int hr222_write_gpo(struct pcxhr_mgr *mgr, int value); | ||
37 | |||
35 | #define HR222_LINE_PLAYBACK_LEVEL_MIN 0 /* -25.5 dB */ | 38 | #define HR222_LINE_PLAYBACK_LEVEL_MIN 0 /* -25.5 dB */ |
36 | #define HR222_LINE_PLAYBACK_ZERO_LEVEL 51 /* 0.0 dB */ | 39 | #define HR222_LINE_PLAYBACK_ZERO_LEVEL 51 /* 0.0 dB */ |
37 | #define HR222_LINE_PLAYBACK_LEVEL_MAX 99 /* +24.0 dB */ | 40 | #define HR222_LINE_PLAYBACK_LEVEL_MAX 99 /* +24.0 dB */ |
diff --git a/sound/pci/pcxhr/pcxhr_mixer.c b/sound/pci/pcxhr/pcxhr_mixer.c index 2436e374586f..fec049344621 100644 --- a/sound/pci/pcxhr/pcxhr_mixer.c +++ b/sound/pci/pcxhr/pcxhr_mixer.c | |||
@@ -789,11 +789,15 @@ static int pcxhr_clock_type_put(struct snd_kcontrol *kcontrol, | |||
789 | if (mgr->use_clock_type != ucontrol->value.enumerated.item[0]) { | 789 | if (mgr->use_clock_type != ucontrol->value.enumerated.item[0]) { |
790 | mutex_lock(&mgr->setup_mutex); | 790 | mutex_lock(&mgr->setup_mutex); |
791 | mgr->use_clock_type = ucontrol->value.enumerated.item[0]; | 791 | mgr->use_clock_type = ucontrol->value.enumerated.item[0]; |
792 | if (mgr->use_clock_type) | 792 | rate = 0; |
793 | if (mgr->use_clock_type != PCXHR_CLOCK_TYPE_INTERNAL) { | ||
793 | pcxhr_get_external_clock(mgr, mgr->use_clock_type, | 794 | pcxhr_get_external_clock(mgr, mgr->use_clock_type, |
794 | &rate); | 795 | &rate); |
795 | else | 796 | } else { |
796 | rate = mgr->sample_rate; | 797 | rate = mgr->sample_rate; |
798 | if (!rate) | ||
799 | rate = 48000; | ||
800 | } | ||
797 | if (rate) { | 801 | if (rate) { |
798 | pcxhr_set_clock(mgr, rate); | 802 | pcxhr_set_clock(mgr, rate); |
799 | if (mgr->sample_rate) | 803 | if (mgr->sample_rate) |
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c index 3caacfb9d8e0..6f1034417a02 100644 --- a/sound/pci/riptide/riptide.c +++ b/sound/pci/riptide/riptide.c | |||
@@ -2102,9 +2102,9 @@ snd_card_riptide_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) | |||
2102 | return -ENOENT; | 2102 | return -ENOENT; |
2103 | } | 2103 | } |
2104 | 2104 | ||
2105 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 2105 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); |
2106 | if (card == NULL) | 2106 | if (err < 0) |
2107 | return -ENOMEM; | 2107 | return err; |
2108 | if ((err = snd_riptide_create(card, pci, &chip)) < 0) { | 2108 | if ((err = snd_riptide_create(card, pci, &chip)) < 0) { |
2109 | snd_card_free(card); | 2109 | snd_card_free(card); |
2110 | return err; | 2110 | return err; |
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c index e7ef3a1a25a8..d7b966e7c4cf 100644 --- a/sound/pci/rme32.c +++ b/sound/pci/rme32.c | |||
@@ -1941,9 +1941,10 @@ snd_rme32_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) | |||
1941 | return -ENOENT; | 1941 | return -ENOENT; |
1942 | } | 1942 | } |
1943 | 1943 | ||
1944 | if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE, | 1944 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, |
1945 | sizeof(struct rme32))) == NULL) | 1945 | sizeof(struct rme32), &card); |
1946 | return -ENOMEM; | 1946 | if (err < 0) |
1947 | return err; | ||
1947 | card->private_free = snd_rme32_card_free; | 1948 | card->private_free = snd_rme32_card_free; |
1948 | rme32 = (struct rme32 *) card->private_data; | 1949 | rme32 = (struct rme32 *) card->private_data; |
1949 | rme32->card = card; | 1950 | rme32->card = card; |
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c index 3fdd488d0975..55fb1c131f58 100644 --- a/sound/pci/rme96.c +++ b/sound/pci/rme96.c | |||
@@ -2348,9 +2348,10 @@ snd_rme96_probe(struct pci_dev *pci, | |||
2348 | dev++; | 2348 | dev++; |
2349 | return -ENOENT; | 2349 | return -ENOENT; |
2350 | } | 2350 | } |
2351 | if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE, | 2351 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, |
2352 | sizeof(struct rme96))) == NULL) | 2352 | sizeof(struct rme96), &card); |
2353 | return -ENOMEM; | 2353 | if (err < 0) |
2354 | return err; | ||
2354 | card->private_free = snd_rme96_card_free; | 2355 | card->private_free = snd_rme96_card_free; |
2355 | rme96 = (struct rme96 *)card->private_data; | 2356 | rme96 = (struct rme96 *)card->private_data; |
2356 | rme96->card = card; | 2357 | rme96->card = card; |
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index 44d0c15e2b71..314e73531bd1 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c | |||
@@ -113,7 +113,7 @@ MODULE_FIRMWARE("digiface_firmware_rev11.bin"); | |||
113 | 113 | ||
114 | /* the meters are regular i/o-mapped registers, but offset | 114 | /* the meters are regular i/o-mapped registers, but offset |
115 | considerably from the rest. the peak registers are reset | 115 | considerably from the rest. the peak registers are reset |
116 | when read; the least-significant 4 bits are full-scale counters; | 116 | when read; the least-significant 4 bits are full-scale counters; |
117 | the actual peak value is in the most-significant 24 bits. | 117 | the actual peak value is in the most-significant 24 bits. |
118 | */ | 118 | */ |
119 | 119 | ||
@@ -131,7 +131,7 @@ MODULE_FIRMWARE("digiface_firmware_rev11.bin"); | |||
131 | 26*3 values are read in ss mode | 131 | 26*3 values are read in ss mode |
132 | 14*3 in ds mode, with no gap between values | 132 | 14*3 in ds mode, with no gap between values |
133 | */ | 133 | */ |
134 | #define HDSP_9652_peakBase 7164 | 134 | #define HDSP_9652_peakBase 7164 |
135 | #define HDSP_9652_rmsBase 4096 | 135 | #define HDSP_9652_rmsBase 4096 |
136 | 136 | ||
137 | /* c.f. the hdsp_9632_meters_t struct */ | 137 | /* c.f. the hdsp_9632_meters_t struct */ |
@@ -173,12 +173,12 @@ MODULE_FIRMWARE("digiface_firmware_rev11.bin"); | |||
173 | #define HDSP_SPDIFEmphasis (1<<10) /* 0=none, 1=on */ | 173 | #define HDSP_SPDIFEmphasis (1<<10) /* 0=none, 1=on */ |
174 | #define HDSP_SPDIFNonAudio (1<<11) /* 0=off, 1=on */ | 174 | #define HDSP_SPDIFNonAudio (1<<11) /* 0=off, 1=on */ |
175 | #define HDSP_SPDIFOpticalOut (1<<12) /* 1=use 1st ADAT connector for SPDIF, 0=do not */ | 175 | #define HDSP_SPDIFOpticalOut (1<<12) /* 1=use 1st ADAT connector for SPDIF, 0=do not */ |
176 | #define HDSP_SyncRef2 (1<<13) | 176 | #define HDSP_SyncRef2 (1<<13) |
177 | #define HDSP_SPDIFInputSelect0 (1<<14) | 177 | #define HDSP_SPDIFInputSelect0 (1<<14) |
178 | #define HDSP_SPDIFInputSelect1 (1<<15) | 178 | #define HDSP_SPDIFInputSelect1 (1<<15) |
179 | #define HDSP_SyncRef0 (1<<16) | 179 | #define HDSP_SyncRef0 (1<<16) |
180 | #define HDSP_SyncRef1 (1<<17) | 180 | #define HDSP_SyncRef1 (1<<17) |
181 | #define HDSP_AnalogExtensionBoard (1<<18) /* For H9632 cards */ | 181 | #define HDSP_AnalogExtensionBoard (1<<18) /* For H9632 cards */ |
182 | #define HDSP_XLRBreakoutCable (1<<20) /* For H9632 cards */ | 182 | #define HDSP_XLRBreakoutCable (1<<20) /* For H9632 cards */ |
183 | #define HDSP_Midi0InterruptEnable (1<<22) | 183 | #define HDSP_Midi0InterruptEnable (1<<22) |
184 | #define HDSP_Midi1InterruptEnable (1<<23) | 184 | #define HDSP_Midi1InterruptEnable (1<<23) |
@@ -314,7 +314,7 @@ MODULE_FIRMWARE("digiface_firmware_rev11.bin"); | |||
314 | #define HDSP_TimecodeSync (1<<27) | 314 | #define HDSP_TimecodeSync (1<<27) |
315 | #define HDSP_AEBO (1<<28) /* H9632 specific Analog Extension Boards */ | 315 | #define HDSP_AEBO (1<<28) /* H9632 specific Analog Extension Boards */ |
316 | #define HDSP_AEBI (1<<29) /* 0 = present, 1 = absent */ | 316 | #define HDSP_AEBI (1<<29) /* 0 = present, 1 = absent */ |
317 | #define HDSP_midi0IRQPending (1<<30) | 317 | #define HDSP_midi0IRQPending (1<<30) |
318 | #define HDSP_midi1IRQPending (1<<31) | 318 | #define HDSP_midi1IRQPending (1<<31) |
319 | 319 | ||
320 | #define HDSP_spdifFrequencyMask (HDSP_spdifFrequency0|HDSP_spdifFrequency1|HDSP_spdifFrequency2) | 320 | #define HDSP_spdifFrequencyMask (HDSP_spdifFrequency0|HDSP_spdifFrequency1|HDSP_spdifFrequency2) |
@@ -391,7 +391,7 @@ MODULE_FIRMWARE("digiface_firmware_rev11.bin"); | |||
391 | #define HDSP_CHANNEL_BUFFER_BYTES (4*HDSP_CHANNEL_BUFFER_SAMPLES) | 391 | #define HDSP_CHANNEL_BUFFER_BYTES (4*HDSP_CHANNEL_BUFFER_SAMPLES) |
392 | 392 | ||
393 | /* the size of the area we need to allocate for DMA transfers. the | 393 | /* the size of the area we need to allocate for DMA transfers. the |
394 | size is the same regardless of the number of channels - the | 394 | size is the same regardless of the number of channels - the |
395 | Multiface still uses the same memory area. | 395 | Multiface still uses the same memory area. |
396 | 396 | ||
397 | Note that we allocate 1 more channel than is apparently needed | 397 | Note that we allocate 1 more channel than is apparently needed |
@@ -460,7 +460,7 @@ struct hdsp { | |||
460 | unsigned char qs_in_channels; /* quad speed mode for H9632 */ | 460 | unsigned char qs_in_channels; /* quad speed mode for H9632 */ |
461 | unsigned char ds_in_channels; | 461 | unsigned char ds_in_channels; |
462 | unsigned char ss_in_channels; /* different for multiface/digiface */ | 462 | unsigned char ss_in_channels; /* different for multiface/digiface */ |
463 | unsigned char qs_out_channels; | 463 | unsigned char qs_out_channels; |
464 | unsigned char ds_out_channels; | 464 | unsigned char ds_out_channels; |
465 | unsigned char ss_out_channels; | 465 | unsigned char ss_out_channels; |
466 | 466 | ||
@@ -502,9 +502,9 @@ static char channel_map_df_ss[HDSP_MAX_CHANNELS] = { | |||
502 | 502 | ||
503 | static char channel_map_mf_ss[HDSP_MAX_CHANNELS] = { /* Multiface */ | 503 | static char channel_map_mf_ss[HDSP_MAX_CHANNELS] = { /* Multiface */ |
504 | /* Analog */ | 504 | /* Analog */ |
505 | 0, 1, 2, 3, 4, 5, 6, 7, | 505 | 0, 1, 2, 3, 4, 5, 6, 7, |
506 | /* ADAT 2 */ | 506 | /* ADAT 2 */ |
507 | 16, 17, 18, 19, 20, 21, 22, 23, | 507 | 16, 17, 18, 19, 20, 21, 22, 23, |
508 | /* SPDIF */ | 508 | /* SPDIF */ |
509 | 24, 25, | 509 | 24, 25, |
510 | -1, -1, -1, -1, -1, -1, -1, -1 | 510 | -1, -1, -1, -1, -1, -1, -1, -1 |
@@ -525,11 +525,11 @@ static char channel_map_H9632_ss[HDSP_MAX_CHANNELS] = { | |||
525 | /* SPDIF */ | 525 | /* SPDIF */ |
526 | 8, 9, | 526 | 8, 9, |
527 | /* Analog */ | 527 | /* Analog */ |
528 | 10, 11, | 528 | 10, 11, |
529 | /* AO4S-192 and AI4S-192 extension boards */ | 529 | /* AO4S-192 and AI4S-192 extension boards */ |
530 | 12, 13, 14, 15, | 530 | 12, 13, 14, 15, |
531 | /* others don't exist */ | 531 | /* others don't exist */ |
532 | -1, -1, -1, -1, -1, -1, -1, -1, | 532 | -1, -1, -1, -1, -1, -1, -1, -1, |
533 | -1, -1 | 533 | -1, -1 |
534 | }; | 534 | }; |
535 | 535 | ||
@@ -539,7 +539,7 @@ static char channel_map_H9632_ds[HDSP_MAX_CHANNELS] = { | |||
539 | /* SPDIF */ | 539 | /* SPDIF */ |
540 | 8, 9, | 540 | 8, 9, |
541 | /* Analog */ | 541 | /* Analog */ |
542 | 10, 11, | 542 | 10, 11, |
543 | /* AO4S-192 and AI4S-192 extension boards */ | 543 | /* AO4S-192 and AI4S-192 extension boards */ |
544 | 12, 13, 14, 15, | 544 | 12, 13, 14, 15, |
545 | /* others don't exist */ | 545 | /* others don't exist */ |
@@ -587,7 +587,7 @@ static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_d | |||
587 | static struct pci_device_id snd_hdsp_ids[] = { | 587 | static struct pci_device_id snd_hdsp_ids[] = { |
588 | { | 588 | { |
589 | .vendor = PCI_VENDOR_ID_XILINX, | 589 | .vendor = PCI_VENDOR_ID_XILINX, |
590 | .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP, | 590 | .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP, |
591 | .subvendor = PCI_ANY_ID, | 591 | .subvendor = PCI_ANY_ID, |
592 | .subdevice = PCI_ANY_ID, | 592 | .subdevice = PCI_ANY_ID, |
593 | }, /* RME Hammerfall-DSP */ | 593 | }, /* RME Hammerfall-DSP */ |
@@ -653,7 +653,6 @@ static unsigned int hdsp_read(struct hdsp *hdsp, int reg) | |||
653 | 653 | ||
654 | static int hdsp_check_for_iobox (struct hdsp *hdsp) | 654 | static int hdsp_check_for_iobox (struct hdsp *hdsp) |
655 | { | 655 | { |
656 | |||
657 | if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0; | 656 | if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0; |
658 | if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_ConfigError) { | 657 | if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_ConfigError) { |
659 | snd_printk ("Hammerfall-DSP: no Digiface or Multiface connected!\n"); | 658 | snd_printk ("Hammerfall-DSP: no Digiface or Multiface connected!\n"); |
@@ -661,7 +660,29 @@ static int hdsp_check_for_iobox (struct hdsp *hdsp) | |||
661 | return -EIO; | 660 | return -EIO; |
662 | } | 661 | } |
663 | return 0; | 662 | return 0; |
663 | } | ||
664 | 664 | ||
665 | static int hdsp_wait_for_iobox(struct hdsp *hdsp, unsigned int loops, | ||
666 | unsigned int delay) | ||
667 | { | ||
668 | unsigned int i; | ||
669 | |||
670 | if (hdsp->io_type == H9652 || hdsp->io_type == H9632) | ||
671 | return 0; | ||
672 | |||
673 | for (i = 0; i != loops; ++i) { | ||
674 | if (hdsp_read(hdsp, HDSP_statusRegister) & HDSP_ConfigError) | ||
675 | msleep(delay); | ||
676 | else { | ||
677 | snd_printd("Hammerfall-DSP: iobox found after %ums!\n", | ||
678 | i * delay); | ||
679 | return 0; | ||
680 | } | ||
681 | } | ||
682 | |||
683 | snd_printk("Hammerfall-DSP: no Digiface or Multiface connected!\n"); | ||
684 | hdsp->state &= ~HDSP_FirmwareLoaded; | ||
685 | return -EIO; | ||
665 | } | 686 | } |
666 | 687 | ||
667 | static int snd_hdsp_load_firmware_from_cache(struct hdsp *hdsp) { | 688 | static int snd_hdsp_load_firmware_from_cache(struct hdsp *hdsp) { |
@@ -670,19 +691,19 @@ static int snd_hdsp_load_firmware_from_cache(struct hdsp *hdsp) { | |||
670 | unsigned long flags; | 691 | unsigned long flags; |
671 | 692 | ||
672 | if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) { | 693 | if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) { |
673 | 694 | ||
674 | snd_printk ("Hammerfall-DSP: loading firmware\n"); | 695 | snd_printk ("Hammerfall-DSP: loading firmware\n"); |
675 | 696 | ||
676 | hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_PROGRAM); | 697 | hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_PROGRAM); |
677 | hdsp_write (hdsp, HDSP_fifoData, 0); | 698 | hdsp_write (hdsp, HDSP_fifoData, 0); |
678 | 699 | ||
679 | if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) { | 700 | if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) { |
680 | snd_printk ("Hammerfall-DSP: timeout waiting for download preparation\n"); | 701 | snd_printk ("Hammerfall-DSP: timeout waiting for download preparation\n"); |
681 | return -EIO; | 702 | return -EIO; |
682 | } | 703 | } |
683 | 704 | ||
684 | hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD); | 705 | hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD); |
685 | 706 | ||
686 | for (i = 0; i < 24413; ++i) { | 707 | for (i = 0; i < 24413; ++i) { |
687 | hdsp_write(hdsp, HDSP_fifoData, hdsp->firmware_cache[i]); | 708 | hdsp_write(hdsp, HDSP_fifoData, hdsp->firmware_cache[i]); |
688 | if (hdsp_fifo_wait (hdsp, 127, HDSP_LONG_WAIT)) { | 709 | if (hdsp_fifo_wait (hdsp, 127, HDSP_LONG_WAIT)) { |
@@ -692,7 +713,7 @@ static int snd_hdsp_load_firmware_from_cache(struct hdsp *hdsp) { | |||
692 | } | 713 | } |
693 | 714 | ||
694 | ssleep(3); | 715 | ssleep(3); |
695 | 716 | ||
696 | if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) { | 717 | if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) { |
697 | snd_printk ("Hammerfall-DSP: timeout at end of firmware loading\n"); | 718 | snd_printk ("Hammerfall-DSP: timeout at end of firmware loading\n"); |
698 | return -EIO; | 719 | return -EIO; |
@@ -705,15 +726,15 @@ static int snd_hdsp_load_firmware_from_cache(struct hdsp *hdsp) { | |||
705 | #endif | 726 | #endif |
706 | hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register); | 727 | hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register); |
707 | snd_printk ("Hammerfall-DSP: finished firmware loading\n"); | 728 | snd_printk ("Hammerfall-DSP: finished firmware loading\n"); |
708 | 729 | ||
709 | } | 730 | } |
710 | if (hdsp->state & HDSP_InitializationComplete) { | 731 | if (hdsp->state & HDSP_InitializationComplete) { |
711 | snd_printk(KERN_INFO "Hammerfall-DSP: firmware loaded from cache, restoring defaults\n"); | 732 | snd_printk(KERN_INFO "Hammerfall-DSP: firmware loaded from cache, restoring defaults\n"); |
712 | spin_lock_irqsave(&hdsp->lock, flags); | 733 | spin_lock_irqsave(&hdsp->lock, flags); |
713 | snd_hdsp_set_defaults(hdsp); | 734 | snd_hdsp_set_defaults(hdsp); |
714 | spin_unlock_irqrestore(&hdsp->lock, flags); | 735 | spin_unlock_irqrestore(&hdsp->lock, flags); |
715 | } | 736 | } |
716 | 737 | ||
717 | hdsp->state |= HDSP_FirmwareLoaded; | 738 | hdsp->state |= HDSP_FirmwareLoaded; |
718 | 739 | ||
719 | return 0; | 740 | return 0; |
@@ -722,7 +743,7 @@ static int snd_hdsp_load_firmware_from_cache(struct hdsp *hdsp) { | |||
722 | static int hdsp_get_iobox_version (struct hdsp *hdsp) | 743 | static int hdsp_get_iobox_version (struct hdsp *hdsp) |
723 | { | 744 | { |
724 | if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) { | 745 | if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) { |
725 | 746 | ||
726 | hdsp_write (hdsp, HDSP_control2Reg, HDSP_PROGRAM); | 747 | hdsp_write (hdsp, HDSP_control2Reg, HDSP_PROGRAM); |
727 | hdsp_write (hdsp, HDSP_fifoData, 0); | 748 | hdsp_write (hdsp, HDSP_fifoData, 0); |
728 | if (hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT) < 0) | 749 | if (hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT) < 0) |
@@ -738,7 +759,7 @@ static int hdsp_get_iobox_version (struct hdsp *hdsp) | |||
738 | hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT); | 759 | hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT); |
739 | } else { | 760 | } else { |
740 | hdsp->io_type = Digiface; | 761 | hdsp->io_type = Digiface; |
741 | } | 762 | } |
742 | } else { | 763 | } else { |
743 | /* firmware was already loaded, get iobox type */ | 764 | /* firmware was already loaded, get iobox type */ |
744 | if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1) | 765 | if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1) |
@@ -786,13 +807,13 @@ static int hdsp_check_for_firmware (struct hdsp *hdsp, int load_on_demand) | |||
786 | 807 | ||
787 | 808 | ||
788 | static int hdsp_fifo_wait(struct hdsp *hdsp, int count, int timeout) | 809 | static int hdsp_fifo_wait(struct hdsp *hdsp, int count, int timeout) |
789 | { | 810 | { |
790 | int i; | 811 | int i; |
791 | 812 | ||
792 | /* the fifoStatus registers reports on how many words | 813 | /* the fifoStatus registers reports on how many words |
793 | are available in the command FIFO. | 814 | are available in the command FIFO. |
794 | */ | 815 | */ |
795 | 816 | ||
796 | for (i = 0; i < timeout; i++) { | 817 | for (i = 0; i < timeout; i++) { |
797 | 818 | ||
798 | if ((int)(hdsp_read (hdsp, HDSP_fifoStatus) & 0xff) <= count) | 819 | if ((int)(hdsp_read (hdsp, HDSP_fifoStatus) & 0xff) <= count) |
@@ -824,11 +845,11 @@ static int hdsp_write_gain(struct hdsp *hdsp, unsigned int addr, unsigned short | |||
824 | 845 | ||
825 | if (addr >= HDSP_MATRIX_MIXER_SIZE) | 846 | if (addr >= HDSP_MATRIX_MIXER_SIZE) |
826 | return -1; | 847 | return -1; |
827 | 848 | ||
828 | if (hdsp->io_type == H9652 || hdsp->io_type == H9632) { | 849 | if (hdsp->io_type == H9652 || hdsp->io_type == H9632) { |
829 | 850 | ||
830 | /* from martin bjornsen: | 851 | /* from martin bjornsen: |
831 | 852 | ||
832 | "You can only write dwords to the | 853 | "You can only write dwords to the |
833 | mixer memory which contain two | 854 | mixer memory which contain two |
834 | mixer values in the low and high | 855 | mixer values in the low and high |
@@ -847,7 +868,7 @@ static int hdsp_write_gain(struct hdsp *hdsp, unsigned int addr, unsigned short | |||
847 | 868 | ||
848 | hdsp->mixer_matrix[addr] = data; | 869 | hdsp->mixer_matrix[addr] = data; |
849 | 870 | ||
850 | 871 | ||
851 | /* `addr' addresses a 16-bit wide address, but | 872 | /* `addr' addresses a 16-bit wide address, but |
852 | the address space accessed via hdsp_write | 873 | the address space accessed via hdsp_write |
853 | uses byte offsets. put another way, addr | 874 | uses byte offsets. put another way, addr |
@@ -856,17 +877,17 @@ static int hdsp_write_gain(struct hdsp *hdsp, unsigned int addr, unsigned short | |||
856 | to access 0 to 2703 ... | 877 | to access 0 to 2703 ... |
857 | */ | 878 | */ |
858 | ad = addr/2; | 879 | ad = addr/2; |
859 | 880 | ||
860 | hdsp_write (hdsp, 4096 + (ad*4), | 881 | hdsp_write (hdsp, 4096 + (ad*4), |
861 | (hdsp->mixer_matrix[(addr&0x7fe)+1] << 16) + | 882 | (hdsp->mixer_matrix[(addr&0x7fe)+1] << 16) + |
862 | hdsp->mixer_matrix[addr&0x7fe]); | 883 | hdsp->mixer_matrix[addr&0x7fe]); |
863 | 884 | ||
864 | return 0; | 885 | return 0; |
865 | 886 | ||
866 | } else { | 887 | } else { |
867 | 888 | ||
868 | ad = (addr << 16) + data; | 889 | ad = (addr << 16) + data; |
869 | 890 | ||
870 | if (hdsp_fifo_wait(hdsp, 127, HDSP_LONG_WAIT)) | 891 | if (hdsp_fifo_wait(hdsp, 127, HDSP_LONG_WAIT)) |
871 | return -1; | 892 | return -1; |
872 | 893 | ||
@@ -902,7 +923,7 @@ static int hdsp_spdif_sample_rate(struct hdsp *hdsp) | |||
902 | 923 | ||
903 | if (status & HDSP_SPDIFErrorFlag) | 924 | if (status & HDSP_SPDIFErrorFlag) |
904 | return 0; | 925 | return 0; |
905 | 926 | ||
906 | switch (rate_bits) { | 927 | switch (rate_bits) { |
907 | case HDSP_spdifFrequency32KHz: return 32000; | 928 | case HDSP_spdifFrequency32KHz: return 32000; |
908 | case HDSP_spdifFrequency44_1KHz: return 44100; | 929 | case HDSP_spdifFrequency44_1KHz: return 44100; |
@@ -910,13 +931,13 @@ static int hdsp_spdif_sample_rate(struct hdsp *hdsp) | |||
910 | case HDSP_spdifFrequency64KHz: return 64000; | 931 | case HDSP_spdifFrequency64KHz: return 64000; |
911 | case HDSP_spdifFrequency88_2KHz: return 88200; | 932 | case HDSP_spdifFrequency88_2KHz: return 88200; |
912 | case HDSP_spdifFrequency96KHz: return 96000; | 933 | case HDSP_spdifFrequency96KHz: return 96000; |
913 | case HDSP_spdifFrequency128KHz: | 934 | case HDSP_spdifFrequency128KHz: |
914 | if (hdsp->io_type == H9632) return 128000; | 935 | if (hdsp->io_type == H9632) return 128000; |
915 | break; | 936 | break; |
916 | case HDSP_spdifFrequency176_4KHz: | 937 | case HDSP_spdifFrequency176_4KHz: |
917 | if (hdsp->io_type == H9632) return 176400; | 938 | if (hdsp->io_type == H9632) return 176400; |
918 | break; | 939 | break; |
919 | case HDSP_spdifFrequency192KHz: | 940 | case HDSP_spdifFrequency192KHz: |
920 | if (hdsp->io_type == H9632) return 192000; | 941 | if (hdsp->io_type == H9632) return 192000; |
921 | break; | 942 | break; |
922 | default: | 943 | default: |
@@ -1027,7 +1048,7 @@ static void hdsp_set_dds_value(struct hdsp *hdsp, int rate) | |||
1027 | { | 1048 | { |
1028 | u64 n; | 1049 | u64 n; |
1029 | u32 r; | 1050 | u32 r; |
1030 | 1051 | ||
1031 | if (rate >= 112000) | 1052 | if (rate >= 112000) |
1032 | rate /= 4; | 1053 | rate /= 4; |
1033 | else if (rate >= 56000) | 1054 | else if (rate >= 56000) |
@@ -1053,35 +1074,35 @@ static int hdsp_set_rate(struct hdsp *hdsp, int rate, int called_internally) | |||
1053 | there is no need for it (e.g. during module | 1074 | there is no need for it (e.g. during module |
1054 | initialization). | 1075 | initialization). |
1055 | */ | 1076 | */ |
1056 | 1077 | ||
1057 | if (!(hdsp->control_register & HDSP_ClockModeMaster)) { | 1078 | if (!(hdsp->control_register & HDSP_ClockModeMaster)) { |
1058 | if (called_internally) { | 1079 | if (called_internally) { |
1059 | /* request from ctl or card initialization */ | 1080 | /* request from ctl or card initialization */ |
1060 | snd_printk(KERN_ERR "Hammerfall-DSP: device is not running as a clock master: cannot set sample rate.\n"); | 1081 | snd_printk(KERN_ERR "Hammerfall-DSP: device is not running as a clock master: cannot set sample rate.\n"); |
1061 | return -1; | 1082 | return -1; |
1062 | } else { | 1083 | } else { |
1063 | /* hw_param request while in AutoSync mode */ | 1084 | /* hw_param request while in AutoSync mode */ |
1064 | int external_freq = hdsp_external_sample_rate(hdsp); | 1085 | int external_freq = hdsp_external_sample_rate(hdsp); |
1065 | int spdif_freq = hdsp_spdif_sample_rate(hdsp); | 1086 | int spdif_freq = hdsp_spdif_sample_rate(hdsp); |
1066 | 1087 | ||
1067 | if ((spdif_freq == external_freq*2) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1)) | 1088 | if ((spdif_freq == external_freq*2) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1)) |
1068 | snd_printk(KERN_INFO "Hammerfall-DSP: Detected ADAT in double speed mode\n"); | 1089 | snd_printk(KERN_INFO "Hammerfall-DSP: Detected ADAT in double speed mode\n"); |
1069 | else if (hdsp->io_type == H9632 && (spdif_freq == external_freq*4) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1)) | 1090 | else if (hdsp->io_type == H9632 && (spdif_freq == external_freq*4) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1)) |
1070 | snd_printk(KERN_INFO "Hammerfall-DSP: Detected ADAT in quad speed mode\n"); | 1091 | snd_printk(KERN_INFO "Hammerfall-DSP: Detected ADAT in quad speed mode\n"); |
1071 | else if (rate != external_freq) { | 1092 | else if (rate != external_freq) { |
1072 | snd_printk(KERN_INFO "Hammerfall-DSP: No AutoSync source for requested rate\n"); | 1093 | snd_printk(KERN_INFO "Hammerfall-DSP: No AutoSync source for requested rate\n"); |
1073 | return -1; | 1094 | return -1; |
1074 | } | 1095 | } |
1075 | } | 1096 | } |
1076 | } | 1097 | } |
1077 | 1098 | ||
1078 | current_rate = hdsp->system_sample_rate; | 1099 | current_rate = hdsp->system_sample_rate; |
1079 | 1100 | ||
1080 | /* Changing from a "single speed" to a "double speed" rate is | 1101 | /* Changing from a "single speed" to a "double speed" rate is |
1081 | not allowed if any substreams are open. This is because | 1102 | not allowed if any substreams are open. This is because |
1082 | such a change causes a shift in the location of | 1103 | such a change causes a shift in the location of |
1083 | the DMA buffers and a reduction in the number of available | 1104 | the DMA buffers and a reduction in the number of available |
1084 | buffers. | 1105 | buffers. |
1085 | 1106 | ||
1086 | Note that a similar but essentially insoluble problem | 1107 | Note that a similar but essentially insoluble problem |
1087 | exists for externally-driven rate changes. All we can do | 1108 | exists for externally-driven rate changes. All we can do |
@@ -1089,7 +1110,7 @@ static int hdsp_set_rate(struct hdsp *hdsp, int rate, int called_internally) | |||
1089 | 1110 | ||
1090 | if (rate > 96000 && hdsp->io_type != H9632) | 1111 | if (rate > 96000 && hdsp->io_type != H9632) |
1091 | return -EINVAL; | 1112 | return -EINVAL; |
1092 | 1113 | ||
1093 | switch (rate) { | 1114 | switch (rate) { |
1094 | case 32000: | 1115 | case 32000: |
1095 | if (current_rate > 48000) | 1116 | if (current_rate > 48000) |
@@ -1179,7 +1200,7 @@ static int hdsp_set_rate(struct hdsp *hdsp, int rate, int called_internally) | |||
1179 | break; | 1200 | break; |
1180 | } | 1201 | } |
1181 | } | 1202 | } |
1182 | 1203 | ||
1183 | hdsp->system_sample_rate = rate; | 1204 | hdsp->system_sample_rate = rate; |
1184 | 1205 | ||
1185 | return 0; | 1206 | return 0; |
@@ -1245,16 +1266,16 @@ static int snd_hdsp_midi_output_write (struct hdsp_midi *hmidi) | |||
1245 | unsigned char buf[128]; | 1266 | unsigned char buf[128]; |
1246 | 1267 | ||
1247 | /* Output is not interrupt driven */ | 1268 | /* Output is not interrupt driven */ |
1248 | 1269 | ||
1249 | spin_lock_irqsave (&hmidi->lock, flags); | 1270 | spin_lock_irqsave (&hmidi->lock, flags); |
1250 | if (hmidi->output) { | 1271 | if (hmidi->output) { |
1251 | if (!snd_rawmidi_transmit_empty (hmidi->output)) { | 1272 | if (!snd_rawmidi_transmit_empty (hmidi->output)) { |
1252 | if ((n_pending = snd_hdsp_midi_output_possible (hmidi->hdsp, hmidi->id)) > 0) { | 1273 | if ((n_pending = snd_hdsp_midi_output_possible (hmidi->hdsp, hmidi->id)) > 0) { |
1253 | if (n_pending > (int)sizeof (buf)) | 1274 | if (n_pending > (int)sizeof (buf)) |
1254 | n_pending = sizeof (buf); | 1275 | n_pending = sizeof (buf); |
1255 | 1276 | ||
1256 | if ((to_write = snd_rawmidi_transmit (hmidi->output, buf, n_pending)) > 0) { | 1277 | if ((to_write = snd_rawmidi_transmit (hmidi->output, buf, n_pending)) > 0) { |
1257 | for (i = 0; i < to_write; ++i) | 1278 | for (i = 0; i < to_write; ++i) |
1258 | snd_hdsp_midi_write_byte (hmidi->hdsp, hmidi->id, buf[i]); | 1279 | snd_hdsp_midi_write_byte (hmidi->hdsp, hmidi->id, buf[i]); |
1259 | } | 1280 | } |
1260 | } | 1281 | } |
@@ -1325,14 +1346,14 @@ static void snd_hdsp_midi_output_timer(unsigned long data) | |||
1325 | { | 1346 | { |
1326 | struct hdsp_midi *hmidi = (struct hdsp_midi *) data; | 1347 | struct hdsp_midi *hmidi = (struct hdsp_midi *) data; |
1327 | unsigned long flags; | 1348 | unsigned long flags; |
1328 | 1349 | ||
1329 | snd_hdsp_midi_output_write(hmidi); | 1350 | snd_hdsp_midi_output_write(hmidi); |
1330 | spin_lock_irqsave (&hmidi->lock, flags); | 1351 | spin_lock_irqsave (&hmidi->lock, flags); |
1331 | 1352 | ||
1332 | /* this does not bump hmidi->istimer, because the | 1353 | /* this does not bump hmidi->istimer, because the |
1333 | kernel automatically removed the timer when it | 1354 | kernel automatically removed the timer when it |
1334 | expired, and we are now adding it back, thus | 1355 | expired, and we are now adding it back, thus |
1335 | leaving istimer wherever it was set before. | 1356 | leaving istimer wherever it was set before. |
1336 | */ | 1357 | */ |
1337 | 1358 | ||
1338 | if (hmidi->istimer) { | 1359 | if (hmidi->istimer) { |
@@ -1501,7 +1522,7 @@ static int snd_hdsp_control_spdif_info(struct snd_kcontrol *kcontrol, struct snd | |||
1501 | static int snd_hdsp_control_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1522 | static int snd_hdsp_control_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1502 | { | 1523 | { |
1503 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 1524 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
1504 | 1525 | ||
1505 | snd_hdsp_convert_to_aes(&ucontrol->value.iec958, hdsp->creg_spdif); | 1526 | snd_hdsp_convert_to_aes(&ucontrol->value.iec958, hdsp->creg_spdif); |
1506 | return 0; | 1527 | return 0; |
1507 | } | 1528 | } |
@@ -1511,7 +1532,7 @@ static int snd_hdsp_control_spdif_put(struct snd_kcontrol *kcontrol, struct snd_ | |||
1511 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 1532 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
1512 | int change; | 1533 | int change; |
1513 | u32 val; | 1534 | u32 val; |
1514 | 1535 | ||
1515 | val = snd_hdsp_convert_from_aes(&ucontrol->value.iec958); | 1536 | val = snd_hdsp_convert_from_aes(&ucontrol->value.iec958); |
1516 | spin_lock_irq(&hdsp->lock); | 1537 | spin_lock_irq(&hdsp->lock); |
1517 | change = val != hdsp->creg_spdif; | 1538 | change = val != hdsp->creg_spdif; |
@@ -1530,7 +1551,7 @@ static int snd_hdsp_control_spdif_stream_info(struct snd_kcontrol *kcontrol, str | |||
1530 | static int snd_hdsp_control_spdif_stream_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1551 | static int snd_hdsp_control_spdif_stream_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1531 | { | 1552 | { |
1532 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 1553 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
1533 | 1554 | ||
1534 | snd_hdsp_convert_to_aes(&ucontrol->value.iec958, hdsp->creg_spdif_stream); | 1555 | snd_hdsp_convert_to_aes(&ucontrol->value.iec958, hdsp->creg_spdif_stream); |
1535 | return 0; | 1556 | return 0; |
1536 | } | 1557 | } |
@@ -1540,7 +1561,7 @@ static int snd_hdsp_control_spdif_stream_put(struct snd_kcontrol *kcontrol, stru | |||
1540 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 1561 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
1541 | int change; | 1562 | int change; |
1542 | u32 val; | 1563 | u32 val; |
1543 | 1564 | ||
1544 | val = snd_hdsp_convert_from_aes(&ucontrol->value.iec958); | 1565 | val = snd_hdsp_convert_from_aes(&ucontrol->value.iec958); |
1545 | spin_lock_irq(&hdsp->lock); | 1566 | spin_lock_irq(&hdsp->lock); |
1546 | change = val != hdsp->creg_spdif_stream; | 1567 | change = val != hdsp->creg_spdif_stream; |
@@ -1602,7 +1623,7 @@ static int snd_hdsp_info_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
1602 | static int snd_hdsp_get_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1623 | static int snd_hdsp_get_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1603 | { | 1624 | { |
1604 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 1625 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
1605 | 1626 | ||
1606 | ucontrol->value.enumerated.item[0] = hdsp_spdif_in(hdsp); | 1627 | ucontrol->value.enumerated.item[0] = hdsp_spdif_in(hdsp); |
1607 | return 0; | 1628 | return 0; |
1608 | } | 1629 | } |
@@ -1612,7 +1633,7 @@ static int snd_hdsp_put_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
1612 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 1633 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
1613 | int change; | 1634 | int change; |
1614 | unsigned int val; | 1635 | unsigned int val; |
1615 | 1636 | ||
1616 | if (!snd_hdsp_use_is_exclusive(hdsp)) | 1637 | if (!snd_hdsp_use_is_exclusive(hdsp)) |
1617 | return -EBUSY; | 1638 | return -EBUSY; |
1618 | val = ucontrol->value.enumerated.item[0] % ((hdsp->io_type == H9632) ? 4 : 3); | 1639 | val = ucontrol->value.enumerated.item[0] % ((hdsp->io_type == H9632) ? 4 : 3); |
@@ -1649,7 +1670,7 @@ static int hdsp_set_spdif_output(struct hdsp *hdsp, int out) | |||
1649 | static int snd_hdsp_get_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1670 | static int snd_hdsp_get_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1650 | { | 1671 | { |
1651 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 1672 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
1652 | 1673 | ||
1653 | ucontrol->value.integer.value[0] = hdsp_spdif_out(hdsp); | 1674 | ucontrol->value.integer.value[0] = hdsp_spdif_out(hdsp); |
1654 | return 0; | 1675 | return 0; |
1655 | } | 1676 | } |
@@ -1659,7 +1680,7 @@ static int snd_hdsp_put_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
1659 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 1680 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
1660 | int change; | 1681 | int change; |
1661 | unsigned int val; | 1682 | unsigned int val; |
1662 | 1683 | ||
1663 | if (!snd_hdsp_use_is_exclusive(hdsp)) | 1684 | if (!snd_hdsp_use_is_exclusive(hdsp)) |
1664 | return -EBUSY; | 1685 | return -EBUSY; |
1665 | val = ucontrol->value.integer.value[0] & 1; | 1686 | val = ucontrol->value.integer.value[0] & 1; |
@@ -1693,7 +1714,7 @@ static int hdsp_set_spdif_professional(struct hdsp *hdsp, int val) | |||
1693 | static int snd_hdsp_get_spdif_professional(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1714 | static int snd_hdsp_get_spdif_professional(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1694 | { | 1715 | { |
1695 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 1716 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
1696 | 1717 | ||
1697 | ucontrol->value.integer.value[0] = hdsp_spdif_professional(hdsp); | 1718 | ucontrol->value.integer.value[0] = hdsp_spdif_professional(hdsp); |
1698 | return 0; | 1719 | return 0; |
1699 | } | 1720 | } |
@@ -1703,7 +1724,7 @@ static int snd_hdsp_put_spdif_professional(struct snd_kcontrol *kcontrol, struct | |||
1703 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 1724 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
1704 | int change; | 1725 | int change; |
1705 | unsigned int val; | 1726 | unsigned int val; |
1706 | 1727 | ||
1707 | if (!snd_hdsp_use_is_exclusive(hdsp)) | 1728 | if (!snd_hdsp_use_is_exclusive(hdsp)) |
1708 | return -EBUSY; | 1729 | return -EBUSY; |
1709 | val = ucontrol->value.integer.value[0] & 1; | 1730 | val = ucontrol->value.integer.value[0] & 1; |
@@ -1737,7 +1758,7 @@ static int hdsp_set_spdif_emphasis(struct hdsp *hdsp, int val) | |||
1737 | static int snd_hdsp_get_spdif_emphasis(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1758 | static int snd_hdsp_get_spdif_emphasis(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1738 | { | 1759 | { |
1739 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 1760 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
1740 | 1761 | ||
1741 | ucontrol->value.integer.value[0] = hdsp_spdif_emphasis(hdsp); | 1762 | ucontrol->value.integer.value[0] = hdsp_spdif_emphasis(hdsp); |
1742 | return 0; | 1763 | return 0; |
1743 | } | 1764 | } |
@@ -1747,7 +1768,7 @@ static int snd_hdsp_put_spdif_emphasis(struct snd_kcontrol *kcontrol, struct snd | |||
1747 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 1768 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
1748 | int change; | 1769 | int change; |
1749 | unsigned int val; | 1770 | unsigned int val; |
1750 | 1771 | ||
1751 | if (!snd_hdsp_use_is_exclusive(hdsp)) | 1772 | if (!snd_hdsp_use_is_exclusive(hdsp)) |
1752 | return -EBUSY; | 1773 | return -EBUSY; |
1753 | val = ucontrol->value.integer.value[0] & 1; | 1774 | val = ucontrol->value.integer.value[0] & 1; |
@@ -1781,7 +1802,7 @@ static int hdsp_set_spdif_nonaudio(struct hdsp *hdsp, int val) | |||
1781 | static int snd_hdsp_get_spdif_nonaudio(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1802 | static int snd_hdsp_get_spdif_nonaudio(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1782 | { | 1803 | { |
1783 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 1804 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
1784 | 1805 | ||
1785 | ucontrol->value.integer.value[0] = hdsp_spdif_nonaudio(hdsp); | 1806 | ucontrol->value.integer.value[0] = hdsp_spdif_nonaudio(hdsp); |
1786 | return 0; | 1807 | return 0; |
1787 | } | 1808 | } |
@@ -1791,7 +1812,7 @@ static int snd_hdsp_put_spdif_nonaudio(struct snd_kcontrol *kcontrol, struct snd | |||
1791 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 1812 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
1792 | int change; | 1813 | int change; |
1793 | unsigned int val; | 1814 | unsigned int val; |
1794 | 1815 | ||
1795 | if (!snd_hdsp_use_is_exclusive(hdsp)) | 1816 | if (!snd_hdsp_use_is_exclusive(hdsp)) |
1796 | return -EBUSY; | 1817 | return -EBUSY; |
1797 | val = ucontrol->value.integer.value[0] & 1; | 1818 | val = ucontrol->value.integer.value[0] & 1; |
@@ -1828,7 +1849,7 @@ static int snd_hdsp_info_spdif_sample_rate(struct snd_kcontrol *kcontrol, struct | |||
1828 | static int snd_hdsp_get_spdif_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1849 | static int snd_hdsp_get_spdif_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1829 | { | 1850 | { |
1830 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 1851 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
1831 | 1852 | ||
1832 | switch (hdsp_spdif_sample_rate(hdsp)) { | 1853 | switch (hdsp_spdif_sample_rate(hdsp)) { |
1833 | case 32000: | 1854 | case 32000: |
1834 | ucontrol->value.enumerated.item[0] = 0; | 1855 | ucontrol->value.enumerated.item[0] = 0; |
@@ -1858,7 +1879,7 @@ static int snd_hdsp_get_spdif_sample_rate(struct snd_kcontrol *kcontrol, struct | |||
1858 | ucontrol->value.enumerated.item[0] = 9; | 1879 | ucontrol->value.enumerated.item[0] = 9; |
1859 | break; | 1880 | break; |
1860 | default: | 1881 | default: |
1861 | ucontrol->value.enumerated.item[0] = 6; | 1882 | ucontrol->value.enumerated.item[0] = 6; |
1862 | } | 1883 | } |
1863 | return 0; | 1884 | return 0; |
1864 | } | 1885 | } |
@@ -1882,7 +1903,7 @@ static int snd_hdsp_info_system_sample_rate(struct snd_kcontrol *kcontrol, struc | |||
1882 | static int snd_hdsp_get_system_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1903 | static int snd_hdsp_get_system_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1883 | { | 1904 | { |
1884 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 1905 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
1885 | 1906 | ||
1886 | ucontrol->value.enumerated.item[0] = hdsp->system_sample_rate; | 1907 | ucontrol->value.enumerated.item[0] = hdsp->system_sample_rate; |
1887 | return 0; | 1908 | return 0; |
1888 | } | 1909 | } |
@@ -1899,7 +1920,7 @@ static int snd_hdsp_get_system_sample_rate(struct snd_kcontrol *kcontrol, struct | |||
1899 | static int snd_hdsp_info_autosync_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1920 | static int snd_hdsp_info_autosync_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) |
1900 | { | 1921 | { |
1901 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 1922 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
1902 | static char *texts[] = {"32000", "44100", "48000", "64000", "88200", "96000", "None", "128000", "176400", "192000"}; | 1923 | static char *texts[] = {"32000", "44100", "48000", "64000", "88200", "96000", "None", "128000", "176400", "192000"}; |
1903 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 1924 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
1904 | uinfo->count = 1; | 1925 | uinfo->count = 1; |
1905 | uinfo->value.enumerated.items = (hdsp->io_type == H9632) ? 10 : 7 ; | 1926 | uinfo->value.enumerated.items = (hdsp->io_type == H9632) ? 10 : 7 ; |
@@ -1912,7 +1933,7 @@ static int snd_hdsp_info_autosync_sample_rate(struct snd_kcontrol *kcontrol, str | |||
1912 | static int snd_hdsp_get_autosync_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1933 | static int snd_hdsp_get_autosync_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1913 | { | 1934 | { |
1914 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 1935 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
1915 | 1936 | ||
1916 | switch (hdsp_external_sample_rate(hdsp)) { | 1937 | switch (hdsp_external_sample_rate(hdsp)) { |
1917 | case 32000: | 1938 | case 32000: |
1918 | ucontrol->value.enumerated.item[0] = 0; | 1939 | ucontrol->value.enumerated.item[0] = 0; |
@@ -1940,9 +1961,9 @@ static int snd_hdsp_get_autosync_sample_rate(struct snd_kcontrol *kcontrol, stru | |||
1940 | break; | 1961 | break; |
1941 | case 192000: | 1962 | case 192000: |
1942 | ucontrol->value.enumerated.item[0] = 9; | 1963 | ucontrol->value.enumerated.item[0] = 9; |
1943 | break; | 1964 | break; |
1944 | default: | 1965 | default: |
1945 | ucontrol->value.enumerated.item[0] = 6; | 1966 | ucontrol->value.enumerated.item[0] = 6; |
1946 | } | 1967 | } |
1947 | return 0; | 1968 | return 0; |
1948 | } | 1969 | } |
@@ -1968,7 +1989,7 @@ static int hdsp_system_clock_mode(struct hdsp *hdsp) | |||
1968 | static int snd_hdsp_info_system_clock_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1989 | static int snd_hdsp_info_system_clock_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) |
1969 | { | 1990 | { |
1970 | static char *texts[] = {"Master", "Slave" }; | 1991 | static char *texts[] = {"Master", "Slave" }; |
1971 | 1992 | ||
1972 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 1993 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
1973 | uinfo->count = 1; | 1994 | uinfo->count = 1; |
1974 | uinfo->value.enumerated.items = 2; | 1995 | uinfo->value.enumerated.items = 2; |
@@ -1981,7 +2002,7 @@ static int snd_hdsp_info_system_clock_mode(struct snd_kcontrol *kcontrol, struct | |||
1981 | static int snd_hdsp_get_system_clock_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 2002 | static int snd_hdsp_get_system_clock_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1982 | { | 2003 | { |
1983 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 2004 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
1984 | 2005 | ||
1985 | ucontrol->value.enumerated.item[0] = hdsp_system_clock_mode(hdsp); | 2006 | ucontrol->value.enumerated.item[0] = hdsp_system_clock_mode(hdsp); |
1986 | return 0; | 2007 | return 0; |
1987 | } | 2008 | } |
@@ -2018,7 +2039,7 @@ static int hdsp_clock_source(struct hdsp *hdsp) | |||
2018 | case 192000: | 2039 | case 192000: |
2019 | return 9; | 2040 | return 9; |
2020 | default: | 2041 | default: |
2021 | return 3; | 2042 | return 3; |
2022 | } | 2043 | } |
2023 | } else { | 2044 | } else { |
2024 | return 0; | 2045 | return 0; |
@@ -2032,7 +2053,7 @@ static int hdsp_set_clock_source(struct hdsp *hdsp, int mode) | |||
2032 | case HDSP_CLOCK_SOURCE_AUTOSYNC: | 2053 | case HDSP_CLOCK_SOURCE_AUTOSYNC: |
2033 | if (hdsp_external_sample_rate(hdsp) != 0) { | 2054 | if (hdsp_external_sample_rate(hdsp) != 0) { |
2034 | if (!hdsp_set_rate(hdsp, hdsp_external_sample_rate(hdsp), 1)) { | 2055 | if (!hdsp_set_rate(hdsp, hdsp_external_sample_rate(hdsp), 1)) { |
2035 | hdsp->control_register &= ~HDSP_ClockModeMaster; | 2056 | hdsp->control_register &= ~HDSP_ClockModeMaster; |
2036 | hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); | 2057 | hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); |
2037 | return 0; | 2058 | return 0; |
2038 | } | 2059 | } |
@@ -2043,7 +2064,7 @@ static int hdsp_set_clock_source(struct hdsp *hdsp, int mode) | |||
2043 | break; | 2064 | break; |
2044 | case HDSP_CLOCK_SOURCE_INTERNAL_44_1KHZ: | 2065 | case HDSP_CLOCK_SOURCE_INTERNAL_44_1KHZ: |
2045 | rate = 44100; | 2066 | rate = 44100; |
2046 | break; | 2067 | break; |
2047 | case HDSP_CLOCK_SOURCE_INTERNAL_48KHZ: | 2068 | case HDSP_CLOCK_SOURCE_INTERNAL_48KHZ: |
2048 | rate = 48000; | 2069 | rate = 48000; |
2049 | break; | 2070 | break; |
@@ -2078,13 +2099,13 @@ static int snd_hdsp_info_clock_source(struct snd_kcontrol *kcontrol, struct snd_ | |||
2078 | { | 2099 | { |
2079 | static char *texts[] = {"AutoSync", "Internal 32.0 kHz", "Internal 44.1 kHz", "Internal 48.0 kHz", "Internal 64.0 kHz", "Internal 88.2 kHz", "Internal 96.0 kHz", "Internal 128 kHz", "Internal 176.4 kHz", "Internal 192.0 KHz" }; | 2100 | static char *texts[] = {"AutoSync", "Internal 32.0 kHz", "Internal 44.1 kHz", "Internal 48.0 kHz", "Internal 64.0 kHz", "Internal 88.2 kHz", "Internal 96.0 kHz", "Internal 128 kHz", "Internal 176.4 kHz", "Internal 192.0 KHz" }; |
2080 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 2101 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
2081 | 2102 | ||
2082 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 2103 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
2083 | uinfo->count = 1; | 2104 | uinfo->count = 1; |
2084 | if (hdsp->io_type == H9632) | 2105 | if (hdsp->io_type == H9632) |
2085 | uinfo->value.enumerated.items = 10; | 2106 | uinfo->value.enumerated.items = 10; |
2086 | else | 2107 | else |
2087 | uinfo->value.enumerated.items = 7; | 2108 | uinfo->value.enumerated.items = 7; |
2088 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | 2109 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) |
2089 | uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; | 2110 | uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; |
2090 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | 2111 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); |
@@ -2094,7 +2115,7 @@ static int snd_hdsp_info_clock_source(struct snd_kcontrol *kcontrol, struct snd_ | |||
2094 | static int snd_hdsp_get_clock_source(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 2115 | static int snd_hdsp_get_clock_source(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
2095 | { | 2116 | { |
2096 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 2117 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
2097 | 2118 | ||
2098 | ucontrol->value.enumerated.item[0] = hdsp_clock_source(hdsp); | 2119 | ucontrol->value.enumerated.item[0] = hdsp_clock_source(hdsp); |
2099 | return 0; | 2120 | return 0; |
2100 | } | 2121 | } |
@@ -2104,7 +2125,7 @@ static int snd_hdsp_put_clock_source(struct snd_kcontrol *kcontrol, struct snd_c | |||
2104 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 2125 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
2105 | int change; | 2126 | int change; |
2106 | int val; | 2127 | int val; |
2107 | 2128 | ||
2108 | if (!snd_hdsp_use_is_exclusive(hdsp)) | 2129 | if (!snd_hdsp_use_is_exclusive(hdsp)) |
2109 | return -EBUSY; | 2130 | return -EBUSY; |
2110 | val = ucontrol->value.enumerated.item[0]; | 2131 | val = ucontrol->value.enumerated.item[0]; |
@@ -2130,7 +2151,7 @@ static int snd_hdsp_put_clock_source(struct snd_kcontrol *kcontrol, struct snd_c | |||
2130 | static int snd_hdsp_get_clock_source_lock(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 2151 | static int snd_hdsp_get_clock_source_lock(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
2131 | { | 2152 | { |
2132 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 2153 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
2133 | 2154 | ||
2134 | ucontrol->value.integer.value[0] = hdsp->clock_source_locked; | 2155 | ucontrol->value.integer.value[0] = hdsp->clock_source_locked; |
2135 | return 0; | 2156 | return 0; |
2136 | } | 2157 | } |
@@ -2165,7 +2186,7 @@ static int hdsp_da_gain(struct hdsp *hdsp) | |||
2165 | case HDSP_DAGainMinus10dBV: | 2186 | case HDSP_DAGainMinus10dBV: |
2166 | return 2; | 2187 | return 2; |
2167 | default: | 2188 | default: |
2168 | return 1; | 2189 | return 1; |
2169 | } | 2190 | } |
2170 | } | 2191 | } |
2171 | 2192 | ||
@@ -2180,8 +2201,8 @@ static int hdsp_set_da_gain(struct hdsp *hdsp, int mode) | |||
2180 | hdsp->control_register |= HDSP_DAGainPlus4dBu; | 2201 | hdsp->control_register |= HDSP_DAGainPlus4dBu; |
2181 | break; | 2202 | break; |
2182 | case 2: | 2203 | case 2: |
2183 | hdsp->control_register |= HDSP_DAGainMinus10dBV; | 2204 | hdsp->control_register |= HDSP_DAGainMinus10dBV; |
2184 | break; | 2205 | break; |
2185 | default: | 2206 | default: |
2186 | return -1; | 2207 | return -1; |
2187 | 2208 | ||
@@ -2193,7 +2214,7 @@ static int hdsp_set_da_gain(struct hdsp *hdsp, int mode) | |||
2193 | static int snd_hdsp_info_da_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 2214 | static int snd_hdsp_info_da_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) |
2194 | { | 2215 | { |
2195 | static char *texts[] = {"Hi Gain", "+4 dBu", "-10 dbV"}; | 2216 | static char *texts[] = {"Hi Gain", "+4 dBu", "-10 dbV"}; |
2196 | 2217 | ||
2197 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 2218 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
2198 | uinfo->count = 1; | 2219 | uinfo->count = 1; |
2199 | uinfo->value.enumerated.items = 3; | 2220 | uinfo->value.enumerated.items = 3; |
@@ -2206,7 +2227,7 @@ static int snd_hdsp_info_da_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
2206 | static int snd_hdsp_get_da_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 2227 | static int snd_hdsp_get_da_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
2207 | { | 2228 | { |
2208 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 2229 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
2209 | 2230 | ||
2210 | ucontrol->value.enumerated.item[0] = hdsp_da_gain(hdsp); | 2231 | ucontrol->value.enumerated.item[0] = hdsp_da_gain(hdsp); |
2211 | return 0; | 2232 | return 0; |
2212 | } | 2233 | } |
@@ -2216,7 +2237,7 @@ static int snd_hdsp_put_da_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_el | |||
2216 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 2237 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
2217 | int change; | 2238 | int change; |
2218 | int val; | 2239 | int val; |
2219 | 2240 | ||
2220 | if (!snd_hdsp_use_is_exclusive(hdsp)) | 2241 | if (!snd_hdsp_use_is_exclusive(hdsp)) |
2221 | return -EBUSY; | 2242 | return -EBUSY; |
2222 | val = ucontrol->value.enumerated.item[0]; | 2243 | val = ucontrol->value.enumerated.item[0]; |
@@ -2250,7 +2271,7 @@ static int hdsp_ad_gain(struct hdsp *hdsp) | |||
2250 | case HDSP_ADGainLowGain: | 2271 | case HDSP_ADGainLowGain: |
2251 | return 2; | 2272 | return 2; |
2252 | default: | 2273 | default: |
2253 | return 1; | 2274 | return 1; |
2254 | } | 2275 | } |
2255 | } | 2276 | } |
2256 | 2277 | ||
@@ -2262,11 +2283,11 @@ static int hdsp_set_ad_gain(struct hdsp *hdsp, int mode) | |||
2262 | hdsp->control_register |= HDSP_ADGainMinus10dBV; | 2283 | hdsp->control_register |= HDSP_ADGainMinus10dBV; |
2263 | break; | 2284 | break; |
2264 | case 1: | 2285 | case 1: |
2265 | hdsp->control_register |= HDSP_ADGainPlus4dBu; | 2286 | hdsp->control_register |= HDSP_ADGainPlus4dBu; |
2266 | break; | 2287 | break; |
2267 | case 2: | 2288 | case 2: |
2268 | hdsp->control_register |= HDSP_ADGainLowGain; | 2289 | hdsp->control_register |= HDSP_ADGainLowGain; |
2269 | break; | 2290 | break; |
2270 | default: | 2291 | default: |
2271 | return -1; | 2292 | return -1; |
2272 | 2293 | ||
@@ -2278,7 +2299,7 @@ static int hdsp_set_ad_gain(struct hdsp *hdsp, int mode) | |||
2278 | static int snd_hdsp_info_ad_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 2299 | static int snd_hdsp_info_ad_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) |
2279 | { | 2300 | { |
2280 | static char *texts[] = {"-10 dBV", "+4 dBu", "Lo Gain"}; | 2301 | static char *texts[] = {"-10 dBV", "+4 dBu", "Lo Gain"}; |
2281 | 2302 | ||
2282 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 2303 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
2283 | uinfo->count = 1; | 2304 | uinfo->count = 1; |
2284 | uinfo->value.enumerated.items = 3; | 2305 | uinfo->value.enumerated.items = 3; |
@@ -2291,7 +2312,7 @@ static int snd_hdsp_info_ad_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
2291 | static int snd_hdsp_get_ad_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 2312 | static int snd_hdsp_get_ad_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
2292 | { | 2313 | { |
2293 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 2314 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
2294 | 2315 | ||
2295 | ucontrol->value.enumerated.item[0] = hdsp_ad_gain(hdsp); | 2316 | ucontrol->value.enumerated.item[0] = hdsp_ad_gain(hdsp); |
2296 | return 0; | 2317 | return 0; |
2297 | } | 2318 | } |
@@ -2301,7 +2322,7 @@ static int snd_hdsp_put_ad_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_el | |||
2301 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 2322 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
2302 | int change; | 2323 | int change; |
2303 | int val; | 2324 | int val; |
2304 | 2325 | ||
2305 | if (!snd_hdsp_use_is_exclusive(hdsp)) | 2326 | if (!snd_hdsp_use_is_exclusive(hdsp)) |
2306 | return -EBUSY; | 2327 | return -EBUSY; |
2307 | val = ucontrol->value.enumerated.item[0]; | 2328 | val = ucontrol->value.enumerated.item[0]; |
@@ -2335,7 +2356,7 @@ static int hdsp_phone_gain(struct hdsp *hdsp) | |||
2335 | case HDSP_PhoneGainMinus12dB: | 2356 | case HDSP_PhoneGainMinus12dB: |
2336 | return 2; | 2357 | return 2; |
2337 | default: | 2358 | default: |
2338 | return 0; | 2359 | return 0; |
2339 | } | 2360 | } |
2340 | } | 2361 | } |
2341 | 2362 | ||
@@ -2347,11 +2368,11 @@ static int hdsp_set_phone_gain(struct hdsp *hdsp, int mode) | |||
2347 | hdsp->control_register |= HDSP_PhoneGain0dB; | 2368 | hdsp->control_register |= HDSP_PhoneGain0dB; |
2348 | break; | 2369 | break; |
2349 | case 1: | 2370 | case 1: |
2350 | hdsp->control_register |= HDSP_PhoneGainMinus6dB; | 2371 | hdsp->control_register |= HDSP_PhoneGainMinus6dB; |
2351 | break; | 2372 | break; |
2352 | case 2: | 2373 | case 2: |
2353 | hdsp->control_register |= HDSP_PhoneGainMinus12dB; | 2374 | hdsp->control_register |= HDSP_PhoneGainMinus12dB; |
2354 | break; | 2375 | break; |
2355 | default: | 2376 | default: |
2356 | return -1; | 2377 | return -1; |
2357 | 2378 | ||
@@ -2363,7 +2384,7 @@ static int hdsp_set_phone_gain(struct hdsp *hdsp, int mode) | |||
2363 | static int snd_hdsp_info_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 2384 | static int snd_hdsp_info_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) |
2364 | { | 2385 | { |
2365 | static char *texts[] = {"0 dB", "-6 dB", "-12 dB"}; | 2386 | static char *texts[] = {"0 dB", "-6 dB", "-12 dB"}; |
2366 | 2387 | ||
2367 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 2388 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
2368 | uinfo->count = 1; | 2389 | uinfo->count = 1; |
2369 | uinfo->value.enumerated.items = 3; | 2390 | uinfo->value.enumerated.items = 3; |
@@ -2376,7 +2397,7 @@ static int snd_hdsp_info_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ct | |||
2376 | static int snd_hdsp_get_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 2397 | static int snd_hdsp_get_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
2377 | { | 2398 | { |
2378 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 2399 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
2379 | 2400 | ||
2380 | ucontrol->value.enumerated.item[0] = hdsp_phone_gain(hdsp); | 2401 | ucontrol->value.enumerated.item[0] = hdsp_phone_gain(hdsp); |
2381 | return 0; | 2402 | return 0; |
2382 | } | 2403 | } |
@@ -2386,7 +2407,7 @@ static int snd_hdsp_put_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ctl | |||
2386 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 2407 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
2387 | int change; | 2408 | int change; |
2388 | int val; | 2409 | int val; |
2389 | 2410 | ||
2390 | if (!snd_hdsp_use_is_exclusive(hdsp)) | 2411 | if (!snd_hdsp_use_is_exclusive(hdsp)) |
2391 | return -EBUSY; | 2412 | return -EBUSY; |
2392 | val = ucontrol->value.enumerated.item[0]; | 2413 | val = ucontrol->value.enumerated.item[0]; |
@@ -2432,7 +2453,7 @@ static int hdsp_set_xlr_breakout_cable(struct hdsp *hdsp, int mode) | |||
2432 | static int snd_hdsp_get_xlr_breakout_cable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 2453 | static int snd_hdsp_get_xlr_breakout_cable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
2433 | { | 2454 | { |
2434 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 2455 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
2435 | 2456 | ||
2436 | ucontrol->value.enumerated.item[0] = hdsp_xlr_breakout_cable(hdsp); | 2457 | ucontrol->value.enumerated.item[0] = hdsp_xlr_breakout_cable(hdsp); |
2437 | return 0; | 2458 | return 0; |
2438 | } | 2459 | } |
@@ -2442,7 +2463,7 @@ static int snd_hdsp_put_xlr_breakout_cable(struct snd_kcontrol *kcontrol, struct | |||
2442 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 2463 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
2443 | int change; | 2464 | int change; |
2444 | int val; | 2465 | int val; |
2445 | 2466 | ||
2446 | if (!snd_hdsp_use_is_exclusive(hdsp)) | 2467 | if (!snd_hdsp_use_is_exclusive(hdsp)) |
2447 | return -EBUSY; | 2468 | return -EBUSY; |
2448 | val = ucontrol->value.integer.value[0] & 1; | 2469 | val = ucontrol->value.integer.value[0] & 1; |
@@ -2488,7 +2509,7 @@ static int hdsp_set_aeb(struct hdsp *hdsp, int mode) | |||
2488 | static int snd_hdsp_get_aeb(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 2509 | static int snd_hdsp_get_aeb(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
2489 | { | 2510 | { |
2490 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 2511 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
2491 | 2512 | ||
2492 | ucontrol->value.enumerated.item[0] = hdsp_aeb(hdsp); | 2513 | ucontrol->value.enumerated.item[0] = hdsp_aeb(hdsp); |
2493 | return 0; | 2514 | return 0; |
2494 | } | 2515 | } |
@@ -2498,7 +2519,7 @@ static int snd_hdsp_put_aeb(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v | |||
2498 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 2519 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
2499 | int change; | 2520 | int change; |
2500 | int val; | 2521 | int val; |
2501 | 2522 | ||
2502 | if (!snd_hdsp_use_is_exclusive(hdsp)) | 2523 | if (!snd_hdsp_use_is_exclusive(hdsp)) |
2503 | return -EBUSY; | 2524 | return -EBUSY; |
2504 | val = ucontrol->value.integer.value[0] & 1; | 2525 | val = ucontrol->value.integer.value[0] & 1; |
@@ -2576,7 +2597,7 @@ static int snd_hdsp_info_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd | |||
2576 | { | 2597 | { |
2577 | static char *texts[] = {"Word", "IEC958", "ADAT1", "ADAT Sync", "ADAT2", "ADAT3" }; | 2598 | static char *texts[] = {"Word", "IEC958", "ADAT1", "ADAT Sync", "ADAT2", "ADAT3" }; |
2578 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 2599 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
2579 | 2600 | ||
2580 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 2601 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
2581 | uinfo->count = 1; | 2602 | uinfo->count = 1; |
2582 | 2603 | ||
@@ -2595,7 +2616,7 @@ static int snd_hdsp_info_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd | |||
2595 | uinfo->value.enumerated.items = 0; | 2616 | uinfo->value.enumerated.items = 0; |
2596 | break; | 2617 | break; |
2597 | } | 2618 | } |
2598 | 2619 | ||
2599 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | 2620 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) |
2600 | uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; | 2621 | uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; |
2601 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | 2622 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); |
@@ -2605,7 +2626,7 @@ static int snd_hdsp_info_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd | |||
2605 | static int snd_hdsp_get_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 2626 | static int snd_hdsp_get_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
2606 | { | 2627 | { |
2607 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 2628 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
2608 | 2629 | ||
2609 | ucontrol->value.enumerated.item[0] = hdsp_pref_sync_ref(hdsp); | 2630 | ucontrol->value.enumerated.item[0] = hdsp_pref_sync_ref(hdsp); |
2610 | return 0; | 2631 | return 0; |
2611 | } | 2632 | } |
@@ -2615,7 +2636,7 @@ static int snd_hdsp_put_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd_ | |||
2615 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 2636 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
2616 | int change, max; | 2637 | int change, max; |
2617 | unsigned int val; | 2638 | unsigned int val; |
2618 | 2639 | ||
2619 | if (!snd_hdsp_use_is_exclusive(hdsp)) | 2640 | if (!snd_hdsp_use_is_exclusive(hdsp)) |
2620 | return -EBUSY; | 2641 | return -EBUSY; |
2621 | 2642 | ||
@@ -2664,7 +2685,7 @@ static int hdsp_autosync_ref(struct hdsp *hdsp) | |||
2664 | case HDSP_SelSyncRef_SPDIF: | 2685 | case HDSP_SelSyncRef_SPDIF: |
2665 | return HDSP_AUTOSYNC_FROM_SPDIF; | 2686 | return HDSP_AUTOSYNC_FROM_SPDIF; |
2666 | case HDSP_SelSyncRefMask: | 2687 | case HDSP_SelSyncRefMask: |
2667 | return HDSP_AUTOSYNC_FROM_NONE; | 2688 | return HDSP_AUTOSYNC_FROM_NONE; |
2668 | case HDSP_SelSyncRef_ADAT1: | 2689 | case HDSP_SelSyncRef_ADAT1: |
2669 | return HDSP_AUTOSYNC_FROM_ADAT1; | 2690 | return HDSP_AUTOSYNC_FROM_ADAT1; |
2670 | case HDSP_SelSyncRef_ADAT2: | 2691 | case HDSP_SelSyncRef_ADAT2: |
@@ -2680,7 +2701,7 @@ static int hdsp_autosync_ref(struct hdsp *hdsp) | |||
2680 | static int snd_hdsp_info_autosync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 2701 | static int snd_hdsp_info_autosync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) |
2681 | { | 2702 | { |
2682 | static char *texts[] = {"Word", "ADAT Sync", "IEC958", "None", "ADAT1", "ADAT2", "ADAT3" }; | 2703 | static char *texts[] = {"Word", "ADAT Sync", "IEC958", "None", "ADAT1", "ADAT2", "ADAT3" }; |
2683 | 2704 | ||
2684 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 2705 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
2685 | uinfo->count = 1; | 2706 | uinfo->count = 1; |
2686 | uinfo->value.enumerated.items = 7; | 2707 | uinfo->value.enumerated.items = 7; |
@@ -2693,7 +2714,7 @@ static int snd_hdsp_info_autosync_ref(struct snd_kcontrol *kcontrol, struct snd_ | |||
2693 | static int snd_hdsp_get_autosync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 2714 | static int snd_hdsp_get_autosync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
2694 | { | 2715 | { |
2695 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 2716 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
2696 | 2717 | ||
2697 | ucontrol->value.enumerated.item[0] = hdsp_autosync_ref(hdsp); | 2718 | ucontrol->value.enumerated.item[0] = hdsp_autosync_ref(hdsp); |
2698 | return 0; | 2719 | return 0; |
2699 | } | 2720 | } |
@@ -2727,7 +2748,7 @@ static int hdsp_set_line_output(struct hdsp *hdsp, int out) | |||
2727 | static int snd_hdsp_get_line_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 2748 | static int snd_hdsp_get_line_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
2728 | { | 2749 | { |
2729 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 2750 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
2730 | 2751 | ||
2731 | spin_lock_irq(&hdsp->lock); | 2752 | spin_lock_irq(&hdsp->lock); |
2732 | ucontrol->value.integer.value[0] = hdsp_line_out(hdsp); | 2753 | ucontrol->value.integer.value[0] = hdsp_line_out(hdsp); |
2733 | spin_unlock_irq(&hdsp->lock); | 2754 | spin_unlock_irq(&hdsp->lock); |
@@ -2739,7 +2760,7 @@ static int snd_hdsp_put_line_out(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
2739 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 2760 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
2740 | int change; | 2761 | int change; |
2741 | unsigned int val; | 2762 | unsigned int val; |
2742 | 2763 | ||
2743 | if (!snd_hdsp_use_is_exclusive(hdsp)) | 2764 | if (!snd_hdsp_use_is_exclusive(hdsp)) |
2744 | return -EBUSY; | 2765 | return -EBUSY; |
2745 | val = ucontrol->value.integer.value[0] & 1; | 2766 | val = ucontrol->value.integer.value[0] & 1; |
@@ -2773,7 +2794,7 @@ static int hdsp_set_precise_pointer(struct hdsp *hdsp, int precise) | |||
2773 | static int snd_hdsp_get_precise_pointer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 2794 | static int snd_hdsp_get_precise_pointer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
2774 | { | 2795 | { |
2775 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 2796 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
2776 | 2797 | ||
2777 | spin_lock_irq(&hdsp->lock); | 2798 | spin_lock_irq(&hdsp->lock); |
2778 | ucontrol->value.integer.value[0] = hdsp->precise_ptr; | 2799 | ucontrol->value.integer.value[0] = hdsp->precise_ptr; |
2779 | spin_unlock_irq(&hdsp->lock); | 2800 | spin_unlock_irq(&hdsp->lock); |
@@ -2785,7 +2806,7 @@ static int snd_hdsp_put_precise_pointer(struct snd_kcontrol *kcontrol, struct sn | |||
2785 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 2806 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
2786 | int change; | 2807 | int change; |
2787 | unsigned int val; | 2808 | unsigned int val; |
2788 | 2809 | ||
2789 | if (!snd_hdsp_use_is_exclusive(hdsp)) | 2810 | if (!snd_hdsp_use_is_exclusive(hdsp)) |
2790 | return -EBUSY; | 2811 | return -EBUSY; |
2791 | val = ucontrol->value.integer.value[0] & 1; | 2812 | val = ucontrol->value.integer.value[0] & 1; |
@@ -2819,7 +2840,7 @@ static int hdsp_set_use_midi_tasklet(struct hdsp *hdsp, int use_tasklet) | |||
2819 | static int snd_hdsp_get_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 2840 | static int snd_hdsp_get_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
2820 | { | 2841 | { |
2821 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 2842 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
2822 | 2843 | ||
2823 | spin_lock_irq(&hdsp->lock); | 2844 | spin_lock_irq(&hdsp->lock); |
2824 | ucontrol->value.integer.value[0] = hdsp->use_midi_tasklet; | 2845 | ucontrol->value.integer.value[0] = hdsp->use_midi_tasklet; |
2825 | spin_unlock_irq(&hdsp->lock); | 2846 | spin_unlock_irq(&hdsp->lock); |
@@ -2831,7 +2852,7 @@ static int snd_hdsp_put_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct s | |||
2831 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 2852 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
2832 | int change; | 2853 | int change; |
2833 | unsigned int val; | 2854 | unsigned int val; |
2834 | 2855 | ||
2835 | if (!snd_hdsp_use_is_exclusive(hdsp)) | 2856 | if (!snd_hdsp_use_is_exclusive(hdsp)) |
2836 | return -EBUSY; | 2857 | return -EBUSY; |
2837 | val = ucontrol->value.integer.value[0] & 1; | 2858 | val = ucontrol->value.integer.value[0] & 1; |
@@ -2873,12 +2894,12 @@ static int snd_hdsp_get_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem | |||
2873 | 2894 | ||
2874 | source = ucontrol->value.integer.value[0]; | 2895 | source = ucontrol->value.integer.value[0]; |
2875 | destination = ucontrol->value.integer.value[1]; | 2896 | destination = ucontrol->value.integer.value[1]; |
2876 | 2897 | ||
2877 | if (source >= hdsp->max_channels) | 2898 | if (source >= hdsp->max_channels) |
2878 | addr = hdsp_playback_to_output_key(hdsp,source-hdsp->max_channels,destination); | 2899 | addr = hdsp_playback_to_output_key(hdsp,source-hdsp->max_channels,destination); |
2879 | else | 2900 | else |
2880 | addr = hdsp_input_to_output_key(hdsp,source, destination); | 2901 | addr = hdsp_input_to_output_key(hdsp,source, destination); |
2881 | 2902 | ||
2882 | spin_lock_irq(&hdsp->lock); | 2903 | spin_lock_irq(&hdsp->lock); |
2883 | ucontrol->value.integer.value[2] = hdsp_read_gain (hdsp, addr); | 2904 | ucontrol->value.integer.value[2] = hdsp_read_gain (hdsp, addr); |
2884 | spin_unlock_irq(&hdsp->lock); | 2905 | spin_unlock_irq(&hdsp->lock); |
@@ -2926,7 +2947,7 @@ static int snd_hdsp_put_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem | |||
2926 | 2947 | ||
2927 | static int snd_hdsp_info_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 2948 | static int snd_hdsp_info_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) |
2928 | { | 2949 | { |
2929 | static char *texts[] = {"No Lock", "Lock", "Sync" }; | 2950 | static char *texts[] = {"No Lock", "Lock", "Sync" }; |
2930 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 2951 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
2931 | uinfo->count = 1; | 2952 | uinfo->count = 1; |
2932 | uinfo->value.enumerated.items = 3; | 2953 | uinfo->value.enumerated.items = 3; |
@@ -2971,7 +2992,7 @@ static int hdsp_spdif_sync_check(struct hdsp *hdsp) | |||
2971 | int status = hdsp_read(hdsp, HDSP_statusRegister); | 2992 | int status = hdsp_read(hdsp, HDSP_statusRegister); |
2972 | if (status & HDSP_SPDIFErrorFlag) | 2993 | if (status & HDSP_SPDIFErrorFlag) |
2973 | return 0; | 2994 | return 0; |
2974 | else { | 2995 | else { |
2975 | if (status & HDSP_SPDIFSync) | 2996 | if (status & HDSP_SPDIFSync) |
2976 | return 2; | 2997 | return 2; |
2977 | else | 2998 | else |
@@ -3007,7 +3028,7 @@ static int hdsp_adatsync_sync_check(struct hdsp *hdsp) | |||
3007 | return 1; | 3028 | return 1; |
3008 | } else | 3029 | } else |
3009 | return 0; | 3030 | return 0; |
3010 | } | 3031 | } |
3011 | 3032 | ||
3012 | static int snd_hdsp_get_adatsync_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 3033 | static int snd_hdsp_get_adatsync_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
3013 | { | 3034 | { |
@@ -3025,17 +3046,17 @@ static int snd_hdsp_get_adatsync_sync_check(struct snd_kcontrol *kcontrol, struc | |||
3025 | } | 3046 | } |
3026 | 3047 | ||
3027 | static int hdsp_adat_sync_check(struct hdsp *hdsp, int idx) | 3048 | static int hdsp_adat_sync_check(struct hdsp *hdsp, int idx) |
3028 | { | 3049 | { |
3029 | int status = hdsp_read(hdsp, HDSP_statusRegister); | 3050 | int status = hdsp_read(hdsp, HDSP_statusRegister); |
3030 | 3051 | ||
3031 | if (status & (HDSP_Lock0>>idx)) { | 3052 | if (status & (HDSP_Lock0>>idx)) { |
3032 | if (status & (HDSP_Sync0>>idx)) | 3053 | if (status & (HDSP_Sync0>>idx)) |
3033 | return 2; | 3054 | return 2; |
3034 | else | 3055 | else |
3035 | return 1; | 3056 | return 1; |
3036 | } else | 3057 | } else |
3037 | return 0; | 3058 | return 0; |
3038 | } | 3059 | } |
3039 | 3060 | ||
3040 | static int snd_hdsp_get_adat_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 3061 | static int snd_hdsp_get_adat_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
3041 | { | 3062 | { |
@@ -3053,7 +3074,7 @@ static int snd_hdsp_get_adat_sync_check(struct snd_kcontrol *kcontrol, struct sn | |||
3053 | break; | 3074 | break; |
3054 | case Multiface: | 3075 | case Multiface: |
3055 | case H9632: | 3076 | case H9632: |
3056 | if (offset >= 1) | 3077 | if (offset >= 1) |
3057 | return -EINVAL; | 3078 | return -EINVAL; |
3058 | break; | 3079 | break; |
3059 | default: | 3080 | default: |
@@ -3115,7 +3136,7 @@ static int snd_hdsp_info_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ct | |||
3115 | static int snd_hdsp_get_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 3136 | static int snd_hdsp_get_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
3116 | { | 3137 | { |
3117 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 3138 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
3118 | 3139 | ||
3119 | ucontrol->value.enumerated.item[0] = hdsp_dds_offset(hdsp); | 3140 | ucontrol->value.enumerated.item[0] = hdsp_dds_offset(hdsp); |
3120 | return 0; | 3141 | return 0; |
3121 | } | 3142 | } |
@@ -3125,7 +3146,7 @@ static int snd_hdsp_put_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl | |||
3125 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 3146 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
3126 | int change; | 3147 | int change; |
3127 | int val; | 3148 | int val; |
3128 | 3149 | ||
3129 | if (!snd_hdsp_use_is_exclusive(hdsp)) | 3150 | if (!snd_hdsp_use_is_exclusive(hdsp)) |
3130 | return -EBUSY; | 3151 | return -EBUSY; |
3131 | val = ucontrol->value.enumerated.item[0]; | 3152 | val = ucontrol->value.enumerated.item[0]; |
@@ -3170,7 +3191,7 @@ static struct snd_kcontrol_new snd_hdsp_controls[] = { | |||
3170 | .get = snd_hdsp_control_spdif_mask_get, | 3191 | .get = snd_hdsp_control_spdif_mask_get, |
3171 | .private_value = IEC958_AES0_NONAUDIO | | 3192 | .private_value = IEC958_AES0_NONAUDIO | |
3172 | IEC958_AES0_PROFESSIONAL | | 3193 | IEC958_AES0_PROFESSIONAL | |
3173 | IEC958_AES0_CON_EMPHASIS, | 3194 | IEC958_AES0_CON_EMPHASIS, |
3174 | }, | 3195 | }, |
3175 | { | 3196 | { |
3176 | .access = SNDRV_CTL_ELEM_ACCESS_READ, | 3197 | .access = SNDRV_CTL_ELEM_ACCESS_READ, |
@@ -3188,7 +3209,7 @@ HDSP_SPDIF_OUT("IEC958 Output also on ADAT1", 0), | |||
3188 | HDSP_SPDIF_PROFESSIONAL("IEC958 Professional Bit", 0), | 3209 | HDSP_SPDIF_PROFESSIONAL("IEC958 Professional Bit", 0), |
3189 | HDSP_SPDIF_EMPHASIS("IEC958 Emphasis Bit", 0), | 3210 | HDSP_SPDIF_EMPHASIS("IEC958 Emphasis Bit", 0), |
3190 | HDSP_SPDIF_NON_AUDIO("IEC958 Non-audio Bit", 0), | 3211 | HDSP_SPDIF_NON_AUDIO("IEC958 Non-audio Bit", 0), |
3191 | /* 'Sample Clock Source' complies with the alsa control naming scheme */ | 3212 | /* 'Sample Clock Source' complies with the alsa control naming scheme */ |
3192 | HDSP_CLOCK_SOURCE("Sample Clock Source", 0), | 3213 | HDSP_CLOCK_SOURCE("Sample Clock Source", 0), |
3193 | { | 3214 | { |
3194 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 3215 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -3240,7 +3261,7 @@ static int snd_hdsp_create_controls(struct snd_card *card, struct hdsp *hdsp) | |||
3240 | return err; | 3261 | return err; |
3241 | } | 3262 | } |
3242 | } | 3263 | } |
3243 | 3264 | ||
3244 | /* DA, AD and Phone gain and XLR breakout cable controls for H9632 cards */ | 3265 | /* DA, AD and Phone gain and XLR breakout cable controls for H9632 cards */ |
3245 | if (hdsp->io_type == H9632) { | 3266 | if (hdsp->io_type == H9632) { |
3246 | for (idx = 0; idx < ARRAY_SIZE(snd_hdsp_9632_controls); idx++) { | 3267 | for (idx = 0; idx < ARRAY_SIZE(snd_hdsp_9632_controls); idx++) { |
@@ -3259,7 +3280,7 @@ static int snd_hdsp_create_controls(struct snd_card *card, struct hdsp *hdsp) | |||
3259 | } | 3280 | } |
3260 | 3281 | ||
3261 | /*------------------------------------------------------------ | 3282 | /*------------------------------------------------------------ |
3262 | /proc interface | 3283 | /proc interface |
3263 | ------------------------------------------------------------*/ | 3284 | ------------------------------------------------------------*/ |
3264 | 3285 | ||
3265 | static void | 3286 | static void |
@@ -3298,7 +3319,7 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) | |||
3298 | } | 3319 | } |
3299 | } | 3320 | } |
3300 | } | 3321 | } |
3301 | 3322 | ||
3302 | status = hdsp_read(hdsp, HDSP_statusRegister); | 3323 | status = hdsp_read(hdsp, HDSP_statusRegister); |
3303 | status2 = hdsp_read(hdsp, HDSP_status2Register); | 3324 | status2 = hdsp_read(hdsp, HDSP_status2Register); |
3304 | 3325 | ||
@@ -3362,17 +3383,17 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) | |||
3362 | break; | 3383 | break; |
3363 | case HDSP_CLOCK_SOURCE_INTERNAL_192KHZ: | 3384 | case HDSP_CLOCK_SOURCE_INTERNAL_192KHZ: |
3364 | clock_source = "Internal 192 kHz"; | 3385 | clock_source = "Internal 192 kHz"; |
3365 | break; | 3386 | break; |
3366 | default: | 3387 | default: |
3367 | clock_source = "Error"; | 3388 | clock_source = "Error"; |
3368 | } | 3389 | } |
3369 | snd_iprintf (buffer, "Sample Clock Source: %s\n", clock_source); | 3390 | snd_iprintf (buffer, "Sample Clock Source: %s\n", clock_source); |
3370 | 3391 | ||
3371 | if (hdsp_system_clock_mode(hdsp)) | 3392 | if (hdsp_system_clock_mode(hdsp)) |
3372 | system_clock_mode = "Slave"; | 3393 | system_clock_mode = "Slave"; |
3373 | else | 3394 | else |
3374 | system_clock_mode = "Master"; | 3395 | system_clock_mode = "Master"; |
3375 | 3396 | ||
3376 | switch (hdsp_pref_sync_ref (hdsp)) { | 3397 | switch (hdsp_pref_sync_ref (hdsp)) { |
3377 | case HDSP_SYNC_FROM_WORD: | 3398 | case HDSP_SYNC_FROM_WORD: |
3378 | pref_sync_ref = "Word Clock"; | 3399 | pref_sync_ref = "Word Clock"; |
@@ -3397,7 +3418,7 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) | |||
3397 | break; | 3418 | break; |
3398 | } | 3419 | } |
3399 | snd_iprintf (buffer, "Preferred Sync Reference: %s\n", pref_sync_ref); | 3420 | snd_iprintf (buffer, "Preferred Sync Reference: %s\n", pref_sync_ref); |
3400 | 3421 | ||
3401 | switch (hdsp_autosync_ref (hdsp)) { | 3422 | switch (hdsp_autosync_ref (hdsp)) { |
3402 | case HDSP_AUTOSYNC_FROM_WORD: | 3423 | case HDSP_AUTOSYNC_FROM_WORD: |
3403 | autosync_ref = "Word Clock"; | 3424 | autosync_ref = "Word Clock"; |
@@ -3410,7 +3431,7 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) | |||
3410 | break; | 3431 | break; |
3411 | case HDSP_AUTOSYNC_FROM_NONE: | 3432 | case HDSP_AUTOSYNC_FROM_NONE: |
3412 | autosync_ref = "None"; | 3433 | autosync_ref = "None"; |
3413 | break; | 3434 | break; |
3414 | case HDSP_AUTOSYNC_FROM_ADAT1: | 3435 | case HDSP_AUTOSYNC_FROM_ADAT1: |
3415 | autosync_ref = "ADAT1"; | 3436 | autosync_ref = "ADAT1"; |
3416 | break; | 3437 | break; |
@@ -3425,14 +3446,14 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) | |||
3425 | break; | 3446 | break; |
3426 | } | 3447 | } |
3427 | snd_iprintf (buffer, "AutoSync Reference: %s\n", autosync_ref); | 3448 | snd_iprintf (buffer, "AutoSync Reference: %s\n", autosync_ref); |
3428 | 3449 | ||
3429 | snd_iprintf (buffer, "AutoSync Frequency: %d\n", hdsp_external_sample_rate(hdsp)); | 3450 | snd_iprintf (buffer, "AutoSync Frequency: %d\n", hdsp_external_sample_rate(hdsp)); |
3430 | 3451 | ||
3431 | snd_iprintf (buffer, "System Clock Mode: %s\n", system_clock_mode); | 3452 | snd_iprintf (buffer, "System Clock Mode: %s\n", system_clock_mode); |
3432 | 3453 | ||
3433 | snd_iprintf (buffer, "System Clock Frequency: %d\n", hdsp->system_sample_rate); | 3454 | snd_iprintf (buffer, "System Clock Frequency: %d\n", hdsp->system_sample_rate); |
3434 | snd_iprintf (buffer, "System Clock Locked: %s\n", hdsp->clock_source_locked ? "Yes" : "No"); | 3455 | snd_iprintf (buffer, "System Clock Locked: %s\n", hdsp->clock_source_locked ? "Yes" : "No"); |
3435 | 3456 | ||
3436 | snd_iprintf(buffer, "\n"); | 3457 | snd_iprintf(buffer, "\n"); |
3437 | 3458 | ||
3438 | switch (hdsp_spdif_in(hdsp)) { | 3459 | switch (hdsp_spdif_in(hdsp)) { |
@@ -3452,7 +3473,7 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) | |||
3452 | snd_iprintf(buffer, "IEC958 input: ???\n"); | 3473 | snd_iprintf(buffer, "IEC958 input: ???\n"); |
3453 | break; | 3474 | break; |
3454 | } | 3475 | } |
3455 | 3476 | ||
3456 | if (hdsp->control_register & HDSP_SPDIFOpticalOut) | 3477 | if (hdsp->control_register & HDSP_SPDIFOpticalOut) |
3457 | snd_iprintf(buffer, "IEC958 output: Coaxial & ADAT1\n"); | 3478 | snd_iprintf(buffer, "IEC958 output: Coaxial & ADAT1\n"); |
3458 | else | 3479 | else |
@@ -3510,13 +3531,13 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) | |||
3510 | snd_iprintf (buffer, "SPDIF: No Lock\n"); | 3531 | snd_iprintf (buffer, "SPDIF: No Lock\n"); |
3511 | else | 3532 | else |
3512 | snd_iprintf (buffer, "SPDIF: %s\n", x ? "Sync" : "Lock"); | 3533 | snd_iprintf (buffer, "SPDIF: %s\n", x ? "Sync" : "Lock"); |
3513 | 3534 | ||
3514 | x = status2 & HDSP_wc_sync; | 3535 | x = status2 & HDSP_wc_sync; |
3515 | if (status2 & HDSP_wc_lock) | 3536 | if (status2 & HDSP_wc_lock) |
3516 | snd_iprintf (buffer, "Word Clock: %s\n", x ? "Sync" : "Lock"); | 3537 | snd_iprintf (buffer, "Word Clock: %s\n", x ? "Sync" : "Lock"); |
3517 | else | 3538 | else |
3518 | snd_iprintf (buffer, "Word Clock: No Lock\n"); | 3539 | snd_iprintf (buffer, "Word Clock: No Lock\n"); |
3519 | 3540 | ||
3520 | x = status & HDSP_TimecodeSync; | 3541 | x = status & HDSP_TimecodeSync; |
3521 | if (status & HDSP_TimecodeLock) | 3542 | if (status & HDSP_TimecodeLock) |
3522 | snd_iprintf(buffer, "ADAT Sync: %s\n", x ? "Sync" : "Lock"); | 3543 | snd_iprintf(buffer, "ADAT Sync: %s\n", x ? "Sync" : "Lock"); |
@@ -3524,11 +3545,11 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) | |||
3524 | snd_iprintf(buffer, "ADAT Sync: No Lock\n"); | 3545 | snd_iprintf(buffer, "ADAT Sync: No Lock\n"); |
3525 | 3546 | ||
3526 | snd_iprintf(buffer, "\n"); | 3547 | snd_iprintf(buffer, "\n"); |
3527 | 3548 | ||
3528 | /* Informations about H9632 specific controls */ | 3549 | /* Informations about H9632 specific controls */ |
3529 | if (hdsp->io_type == H9632) { | 3550 | if (hdsp->io_type == H9632) { |
3530 | char *tmp; | 3551 | char *tmp; |
3531 | 3552 | ||
3532 | switch (hdsp_ad_gain(hdsp)) { | 3553 | switch (hdsp_ad_gain(hdsp)) { |
3533 | case 0: | 3554 | case 0: |
3534 | tmp = "-10 dBV"; | 3555 | tmp = "-10 dBV"; |
@@ -3554,7 +3575,7 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) | |||
3554 | break; | 3575 | break; |
3555 | } | 3576 | } |
3556 | snd_iprintf(buffer, "DA Gain : %s\n", tmp); | 3577 | snd_iprintf(buffer, "DA Gain : %s\n", tmp); |
3557 | 3578 | ||
3558 | switch (hdsp_phone_gain(hdsp)) { | 3579 | switch (hdsp_phone_gain(hdsp)) { |
3559 | case 0: | 3580 | case 0: |
3560 | tmp = "0 dB"; | 3581 | tmp = "0 dB"; |
@@ -3568,8 +3589,8 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) | |||
3568 | } | 3589 | } |
3569 | snd_iprintf(buffer, "Phones Gain : %s\n", tmp); | 3590 | snd_iprintf(buffer, "Phones Gain : %s\n", tmp); |
3570 | 3591 | ||
3571 | snd_iprintf(buffer, "XLR Breakout Cable : %s\n", hdsp_xlr_breakout_cable(hdsp) ? "yes" : "no"); | 3592 | snd_iprintf(buffer, "XLR Breakout Cable : %s\n", hdsp_xlr_breakout_cable(hdsp) ? "yes" : "no"); |
3572 | 3593 | ||
3573 | if (hdsp->control_register & HDSP_AnalogExtensionBoard) | 3594 | if (hdsp->control_register & HDSP_AnalogExtensionBoard) |
3574 | snd_iprintf(buffer, "AEB : on (ADAT1 internal)\n"); | 3595 | snd_iprintf(buffer, "AEB : on (ADAT1 internal)\n"); |
3575 | else | 3596 | else |
@@ -3632,18 +3653,18 @@ static int snd_hdsp_set_defaults(struct hdsp *hdsp) | |||
3632 | 3653 | ||
3633 | /* set defaults: | 3654 | /* set defaults: |
3634 | 3655 | ||
3635 | SPDIF Input via Coax | 3656 | SPDIF Input via Coax |
3636 | Master clock mode | 3657 | Master clock mode |
3637 | maximum latency (7 => 2^7 = 8192 samples, 64Kbyte buffer, | 3658 | maximum latency (7 => 2^7 = 8192 samples, 64Kbyte buffer, |
3638 | which implies 2 4096 sample, 32Kbyte periods). | 3659 | which implies 2 4096 sample, 32Kbyte periods). |
3639 | Enable line out. | 3660 | Enable line out. |
3640 | */ | 3661 | */ |
3641 | 3662 | ||
3642 | hdsp->control_register = HDSP_ClockModeMaster | | 3663 | hdsp->control_register = HDSP_ClockModeMaster | |
3643 | HDSP_SPDIFInputCoaxial | | 3664 | HDSP_SPDIFInputCoaxial | |
3644 | hdsp_encode_latency(7) | | 3665 | hdsp_encode_latency(7) | |
3645 | HDSP_LineOut; | 3666 | HDSP_LineOut; |
3646 | 3667 | ||
3647 | 3668 | ||
3648 | hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); | 3669 | hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); |
3649 | 3670 | ||
@@ -3661,7 +3682,7 @@ static int snd_hdsp_set_defaults(struct hdsp *hdsp) | |||
3661 | hdsp_compute_period_size(hdsp); | 3682 | hdsp_compute_period_size(hdsp); |
3662 | 3683 | ||
3663 | /* silence everything */ | 3684 | /* silence everything */ |
3664 | 3685 | ||
3665 | for (i = 0; i < HDSP_MATRIX_MIXER_SIZE; ++i) | 3686 | for (i = 0; i < HDSP_MATRIX_MIXER_SIZE; ++i) |
3666 | hdsp->mixer_matrix[i] = MINUS_INFINITY_GAIN; | 3687 | hdsp->mixer_matrix[i] = MINUS_INFINITY_GAIN; |
3667 | 3688 | ||
@@ -3669,7 +3690,7 @@ static int snd_hdsp_set_defaults(struct hdsp *hdsp) | |||
3669 | if (hdsp_write_gain (hdsp, i, MINUS_INFINITY_GAIN)) | 3690 | if (hdsp_write_gain (hdsp, i, MINUS_INFINITY_GAIN)) |
3670 | return -EIO; | 3691 | return -EIO; |
3671 | } | 3692 | } |
3672 | 3693 | ||
3673 | /* H9632 specific defaults */ | 3694 | /* H9632 specific defaults */ |
3674 | if (hdsp->io_type == H9632) { | 3695 | if (hdsp->io_type == H9632) { |
3675 | hdsp->control_register |= (HDSP_DAGainPlus4dBu | HDSP_ADGainPlus4dBu | HDSP_PhoneGain0dB); | 3696 | hdsp->control_register |= (HDSP_DAGainPlus4dBu | HDSP_ADGainPlus4dBu | HDSP_PhoneGain0dB); |
@@ -3687,12 +3708,12 @@ static int snd_hdsp_set_defaults(struct hdsp *hdsp) | |||
3687 | static void hdsp_midi_tasklet(unsigned long arg) | 3708 | static void hdsp_midi_tasklet(unsigned long arg) |
3688 | { | 3709 | { |
3689 | struct hdsp *hdsp = (struct hdsp *)arg; | 3710 | struct hdsp *hdsp = (struct hdsp *)arg; |
3690 | 3711 | ||
3691 | if (hdsp->midi[0].pending) | 3712 | if (hdsp->midi[0].pending) |
3692 | snd_hdsp_midi_input_read (&hdsp->midi[0]); | 3713 | snd_hdsp_midi_input_read (&hdsp->midi[0]); |
3693 | if (hdsp->midi[1].pending) | 3714 | if (hdsp->midi[1].pending) |
3694 | snd_hdsp_midi_input_read (&hdsp->midi[1]); | 3715 | snd_hdsp_midi_input_read (&hdsp->midi[1]); |
3695 | } | 3716 | } |
3696 | 3717 | ||
3697 | static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id) | 3718 | static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id) |
3698 | { | 3719 | { |
@@ -3704,7 +3725,7 @@ static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id) | |||
3704 | unsigned int midi0status; | 3725 | unsigned int midi0status; |
3705 | unsigned int midi1status; | 3726 | unsigned int midi1status; |
3706 | int schedule = 0; | 3727 | int schedule = 0; |
3707 | 3728 | ||
3708 | status = hdsp_read(hdsp, HDSP_statusRegister); | 3729 | status = hdsp_read(hdsp, HDSP_statusRegister); |
3709 | 3730 | ||
3710 | audio = status & HDSP_audioIRQPending; | 3731 | audio = status & HDSP_audioIRQPending; |
@@ -3718,15 +3739,18 @@ static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id) | |||
3718 | 3739 | ||
3719 | midi0status = hdsp_read (hdsp, HDSP_midiStatusIn0) & 0xff; | 3740 | midi0status = hdsp_read (hdsp, HDSP_midiStatusIn0) & 0xff; |
3720 | midi1status = hdsp_read (hdsp, HDSP_midiStatusIn1) & 0xff; | 3741 | midi1status = hdsp_read (hdsp, HDSP_midiStatusIn1) & 0xff; |
3721 | 3742 | ||
3743 | if (!(hdsp->state & HDSP_InitializationComplete)) | ||
3744 | return IRQ_HANDLED; | ||
3745 | |||
3722 | if (audio) { | 3746 | if (audio) { |
3723 | if (hdsp->capture_substream) | 3747 | if (hdsp->capture_substream) |
3724 | snd_pcm_period_elapsed(hdsp->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream); | 3748 | snd_pcm_period_elapsed(hdsp->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream); |
3725 | 3749 | ||
3726 | if (hdsp->playback_substream) | 3750 | if (hdsp->playback_substream) |
3727 | snd_pcm_period_elapsed(hdsp->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream); | 3751 | snd_pcm_period_elapsed(hdsp->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream); |
3728 | } | 3752 | } |
3729 | 3753 | ||
3730 | if (midi0 && midi0status) { | 3754 | if (midi0 && midi0status) { |
3731 | if (hdsp->use_midi_tasklet) { | 3755 | if (hdsp->use_midi_tasklet) { |
3732 | /* we disable interrupts for this input until processing is done */ | 3756 | /* we disable interrupts for this input until processing is done */ |
@@ -3769,10 +3793,10 @@ static char *hdsp_channel_buffer_location(struct hdsp *hdsp, | |||
3769 | 3793 | ||
3770 | if (snd_BUG_ON(channel < 0 || channel >= hdsp->max_channels)) | 3794 | if (snd_BUG_ON(channel < 0 || channel >= hdsp->max_channels)) |
3771 | return NULL; | 3795 | return NULL; |
3772 | 3796 | ||
3773 | if ((mapped_channel = hdsp->channel_map[channel]) < 0) | 3797 | if ((mapped_channel = hdsp->channel_map[channel]) < 0) |
3774 | return NULL; | 3798 | return NULL; |
3775 | 3799 | ||
3776 | if (stream == SNDRV_PCM_STREAM_CAPTURE) | 3800 | if (stream == SNDRV_PCM_STREAM_CAPTURE) |
3777 | return hdsp->capture_buffer + (mapped_channel * HDSP_CHANNEL_BUFFER_BYTES); | 3801 | return hdsp->capture_buffer + (mapped_channel * HDSP_CHANNEL_BUFFER_BYTES); |
3778 | else | 3802 | else |
@@ -3965,7 +3989,7 @@ static int snd_hdsp_trigger(struct snd_pcm_substream *substream, int cmd) | |||
3965 | struct hdsp *hdsp = snd_pcm_substream_chip(substream); | 3989 | struct hdsp *hdsp = snd_pcm_substream_chip(substream); |
3966 | struct snd_pcm_substream *other; | 3990 | struct snd_pcm_substream *other; |
3967 | int running; | 3991 | int running; |
3968 | 3992 | ||
3969 | if (hdsp_check_for_iobox (hdsp)) | 3993 | if (hdsp_check_for_iobox (hdsp)) |
3970 | return -EIO; | 3994 | return -EIO; |
3971 | 3995 | ||
@@ -4059,10 +4083,10 @@ static struct snd_pcm_hardware snd_hdsp_playback_subinfo = | |||
4059 | .formats = SNDRV_PCM_FMTBIT_S32_LE, | 4083 | .formats = SNDRV_PCM_FMTBIT_S32_LE, |
4060 | #endif | 4084 | #endif |
4061 | .rates = (SNDRV_PCM_RATE_32000 | | 4085 | .rates = (SNDRV_PCM_RATE_32000 | |
4062 | SNDRV_PCM_RATE_44100 | | 4086 | SNDRV_PCM_RATE_44100 | |
4063 | SNDRV_PCM_RATE_48000 | | 4087 | SNDRV_PCM_RATE_48000 | |
4064 | SNDRV_PCM_RATE_64000 | | 4088 | SNDRV_PCM_RATE_64000 | |
4065 | SNDRV_PCM_RATE_88200 | | 4089 | SNDRV_PCM_RATE_88200 | |
4066 | SNDRV_PCM_RATE_96000), | 4090 | SNDRV_PCM_RATE_96000), |
4067 | .rate_min = 32000, | 4091 | .rate_min = 32000, |
4068 | .rate_max = 96000, | 4092 | .rate_max = 96000, |
@@ -4088,10 +4112,10 @@ static struct snd_pcm_hardware snd_hdsp_capture_subinfo = | |||
4088 | .formats = SNDRV_PCM_FMTBIT_S32_LE, | 4112 | .formats = SNDRV_PCM_FMTBIT_S32_LE, |
4089 | #endif | 4113 | #endif |
4090 | .rates = (SNDRV_PCM_RATE_32000 | | 4114 | .rates = (SNDRV_PCM_RATE_32000 | |
4091 | SNDRV_PCM_RATE_44100 | | 4115 | SNDRV_PCM_RATE_44100 | |
4092 | SNDRV_PCM_RATE_48000 | | 4116 | SNDRV_PCM_RATE_48000 | |
4093 | SNDRV_PCM_RATE_64000 | | 4117 | SNDRV_PCM_RATE_64000 | |
4094 | SNDRV_PCM_RATE_88200 | | 4118 | SNDRV_PCM_RATE_88200 | |
4095 | SNDRV_PCM_RATE_96000), | 4119 | SNDRV_PCM_RATE_96000), |
4096 | .rate_min = 32000, | 4120 | .rate_min = 32000, |
4097 | .rate_max = 96000, | 4121 | .rate_max = 96000, |
@@ -4170,7 +4194,7 @@ static int snd_hdsp_hw_rule_in_channels_rate(struct snd_pcm_hw_params *params, | |||
4170 | .max = hdsp->qs_in_channels, | 4194 | .max = hdsp->qs_in_channels, |
4171 | .integer = 1, | 4195 | .integer = 1, |
4172 | }; | 4196 | }; |
4173 | return snd_interval_refine(c, &t); | 4197 | return snd_interval_refine(c, &t); |
4174 | } else if (r->min > 48000 && r->max <= 96000) { | 4198 | } else if (r->min > 48000 && r->max <= 96000) { |
4175 | struct snd_interval t = { | 4199 | struct snd_interval t = { |
4176 | .min = hdsp->ds_in_channels, | 4200 | .min = hdsp->ds_in_channels, |
@@ -4201,7 +4225,7 @@ static int snd_hdsp_hw_rule_out_channels_rate(struct snd_pcm_hw_params *params, | |||
4201 | .max = hdsp->qs_out_channels, | 4225 | .max = hdsp->qs_out_channels, |
4202 | .integer = 1, | 4226 | .integer = 1, |
4203 | }; | 4227 | }; |
4204 | return snd_interval_refine(c, &t); | 4228 | return snd_interval_refine(c, &t); |
4205 | } else if (r->min > 48000 && r->max <= 96000) { | 4229 | } else if (r->min > 48000 && r->max <= 96000) { |
4206 | struct snd_interval t = { | 4230 | struct snd_interval t = { |
4207 | .min = hdsp->ds_out_channels, | 4231 | .min = hdsp->ds_out_channels, |
@@ -4318,8 +4342,8 @@ static int snd_hdsp_playback_open(struct snd_pcm_substream *substream) | |||
4318 | if (hdsp->io_type == H9632) { | 4342 | if (hdsp->io_type == H9632) { |
4319 | runtime->hw.channels_min = hdsp->qs_out_channels; | 4343 | runtime->hw.channels_min = hdsp->qs_out_channels; |
4320 | runtime->hw.channels_max = hdsp->ss_out_channels; | 4344 | runtime->hw.channels_max = hdsp->ss_out_channels; |
4321 | } | 4345 | } |
4322 | 4346 | ||
4323 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | 4347 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, |
4324 | snd_hdsp_hw_rule_out_channels, hdsp, | 4348 | snd_hdsp_hw_rule_out_channels, hdsp, |
4325 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); | 4349 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); |
@@ -4413,13 +4437,6 @@ static int snd_hdsp_capture_release(struct snd_pcm_substream *substream) | |||
4413 | return 0; | 4437 | return 0; |
4414 | } | 4438 | } |
4415 | 4439 | ||
4416 | static int snd_hdsp_hwdep_dummy_op(struct snd_hwdep *hw, struct file *file) | ||
4417 | { | ||
4418 | /* we have nothing to initialize but the call is required */ | ||
4419 | return 0; | ||
4420 | } | ||
4421 | |||
4422 | |||
4423 | /* helper functions for copying meter values */ | 4440 | /* helper functions for copying meter values */ |
4424 | static inline int copy_u32_le(void __user *dest, void __iomem *src) | 4441 | static inline int copy_u32_le(void __user *dest, void __iomem *src) |
4425 | { | 4442 | { |
@@ -4536,7 +4553,7 @@ static int hdsp_get_peak(struct hdsp *hdsp, struct hdsp_peak_rms __user *peak_rm | |||
4536 | hdsp->iobase + HDSP_playbackRmsLevel + i * 8 + 4, | 4553 | hdsp->iobase + HDSP_playbackRmsLevel + i * 8 + 4, |
4537 | hdsp->iobase + HDSP_playbackRmsLevel + i * 8)) | 4554 | hdsp->iobase + HDSP_playbackRmsLevel + i * 8)) |
4538 | return -EFAULT; | 4555 | return -EFAULT; |
4539 | if (copy_u64_le(&peak_rms->input_rms[i], | 4556 | if (copy_u64_le(&peak_rms->input_rms[i], |
4540 | hdsp->iobase + HDSP_inputRmsLevel + i * 8 + 4, | 4557 | hdsp->iobase + HDSP_inputRmsLevel + i * 8 + 4, |
4541 | hdsp->iobase + HDSP_inputRmsLevel + i * 8)) | 4558 | hdsp->iobase + HDSP_inputRmsLevel + i * 8)) |
4542 | return -EFAULT; | 4559 | return -EFAULT; |
@@ -4546,7 +4563,7 @@ static int hdsp_get_peak(struct hdsp *hdsp, struct hdsp_peak_rms __user *peak_rm | |||
4546 | 4563 | ||
4547 | static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigned int cmd, unsigned long arg) | 4564 | static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigned int cmd, unsigned long arg) |
4548 | { | 4565 | { |
4549 | struct hdsp *hdsp = (struct hdsp *)hw->private_data; | 4566 | struct hdsp *hdsp = (struct hdsp *)hw->private_data; |
4550 | void __user *argp = (void __user *)arg; | 4567 | void __user *argp = (void __user *)arg; |
4551 | int err; | 4568 | int err; |
4552 | 4569 | ||
@@ -4580,7 +4597,7 @@ static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigne | |||
4580 | struct hdsp_config_info info; | 4597 | struct hdsp_config_info info; |
4581 | unsigned long flags; | 4598 | unsigned long flags; |
4582 | int i; | 4599 | int i; |
4583 | 4600 | ||
4584 | err = hdsp_check_for_iobox(hdsp); | 4601 | err = hdsp_check_for_iobox(hdsp); |
4585 | if (err < 0) | 4602 | if (err < 0) |
4586 | return err; | 4603 | return err; |
@@ -4614,7 +4631,7 @@ static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigne | |||
4614 | info.ad_gain = (unsigned char)hdsp_ad_gain(hdsp); | 4631 | info.ad_gain = (unsigned char)hdsp_ad_gain(hdsp); |
4615 | info.phone_gain = (unsigned char)hdsp_phone_gain(hdsp); | 4632 | info.phone_gain = (unsigned char)hdsp_phone_gain(hdsp); |
4616 | info.xlr_breakout_cable = (unsigned char)hdsp_xlr_breakout_cable(hdsp); | 4633 | info.xlr_breakout_cable = (unsigned char)hdsp_xlr_breakout_cable(hdsp); |
4617 | 4634 | ||
4618 | } | 4635 | } |
4619 | if (hdsp->io_type == H9632 || hdsp->io_type == H9652) | 4636 | if (hdsp->io_type == H9632 || hdsp->io_type == H9652) |
4620 | info.analog_extension_board = (unsigned char)hdsp_aeb(hdsp); | 4637 | info.analog_extension_board = (unsigned char)hdsp_aeb(hdsp); |
@@ -4625,7 +4642,7 @@ static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigne | |||
4625 | } | 4642 | } |
4626 | case SNDRV_HDSP_IOCTL_GET_9632_AEB: { | 4643 | case SNDRV_HDSP_IOCTL_GET_9632_AEB: { |
4627 | struct hdsp_9632_aeb h9632_aeb; | 4644 | struct hdsp_9632_aeb h9632_aeb; |
4628 | 4645 | ||
4629 | if (hdsp->io_type != H9632) return -EINVAL; | 4646 | if (hdsp->io_type != H9632) return -EINVAL; |
4630 | h9632_aeb.aebi = hdsp->ss_in_channels - H9632_SS_CHANNELS; | 4647 | h9632_aeb.aebi = hdsp->ss_in_channels - H9632_SS_CHANNELS; |
4631 | h9632_aeb.aebo = hdsp->ss_out_channels - H9632_SS_CHANNELS; | 4648 | h9632_aeb.aebo = hdsp->ss_out_channels - H9632_SS_CHANNELS; |
@@ -4636,7 +4653,7 @@ static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigne | |||
4636 | case SNDRV_HDSP_IOCTL_GET_VERSION: { | 4653 | case SNDRV_HDSP_IOCTL_GET_VERSION: { |
4637 | struct hdsp_version hdsp_version; | 4654 | struct hdsp_version hdsp_version; |
4638 | int err; | 4655 | int err; |
4639 | 4656 | ||
4640 | if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return -EINVAL; | 4657 | if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return -EINVAL; |
4641 | if (hdsp->io_type == Undefined) { | 4658 | if (hdsp->io_type == Undefined) { |
4642 | if ((err = hdsp_get_iobox_version(hdsp)) < 0) | 4659 | if ((err = hdsp_get_iobox_version(hdsp)) < 0) |
@@ -4652,7 +4669,7 @@ static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigne | |||
4652 | struct hdsp_firmware __user *firmware; | 4669 | struct hdsp_firmware __user *firmware; |
4653 | u32 __user *firmware_data; | 4670 | u32 __user *firmware_data; |
4654 | int err; | 4671 | int err; |
4655 | 4672 | ||
4656 | if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return -EINVAL; | 4673 | if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return -EINVAL; |
4657 | /* SNDRV_HDSP_IOCTL_GET_VERSION must have been called */ | 4674 | /* SNDRV_HDSP_IOCTL_GET_VERSION must have been called */ |
4658 | if (hdsp->io_type == Undefined) return -EINVAL; | 4675 | if (hdsp->io_type == Undefined) return -EINVAL; |
@@ -4665,25 +4682,25 @@ static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigne | |||
4665 | 4682 | ||
4666 | if (get_user(firmware_data, &firmware->firmware_data)) | 4683 | if (get_user(firmware_data, &firmware->firmware_data)) |
4667 | return -EFAULT; | 4684 | return -EFAULT; |
4668 | 4685 | ||
4669 | if (hdsp_check_for_iobox (hdsp)) | 4686 | if (hdsp_check_for_iobox (hdsp)) |
4670 | return -EIO; | 4687 | return -EIO; |
4671 | 4688 | ||
4672 | if (copy_from_user(hdsp->firmware_cache, firmware_data, sizeof(hdsp->firmware_cache)) != 0) | 4689 | if (copy_from_user(hdsp->firmware_cache, firmware_data, sizeof(hdsp->firmware_cache)) != 0) |
4673 | return -EFAULT; | 4690 | return -EFAULT; |
4674 | 4691 | ||
4675 | hdsp->state |= HDSP_FirmwareCached; | 4692 | hdsp->state |= HDSP_FirmwareCached; |
4676 | 4693 | ||
4677 | if ((err = snd_hdsp_load_firmware_from_cache(hdsp)) < 0) | 4694 | if ((err = snd_hdsp_load_firmware_from_cache(hdsp)) < 0) |
4678 | return err; | 4695 | return err; |
4679 | 4696 | ||
4680 | if (!(hdsp->state & HDSP_InitializationComplete)) { | 4697 | if (!(hdsp->state & HDSP_InitializationComplete)) { |
4681 | if ((err = snd_hdsp_enable_io(hdsp)) < 0) | 4698 | if ((err = snd_hdsp_enable_io(hdsp)) < 0) |
4682 | return err; | 4699 | return err; |
4683 | 4700 | ||
4684 | snd_hdsp_initialize_channels(hdsp); | 4701 | snd_hdsp_initialize_channels(hdsp); |
4685 | snd_hdsp_initialize_midi_flush(hdsp); | 4702 | snd_hdsp_initialize_midi_flush(hdsp); |
4686 | 4703 | ||
4687 | if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) { | 4704 | if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) { |
4688 | snd_printk(KERN_ERR "Hammerfall-DSP: error creating alsa devices\n"); | 4705 | snd_printk(KERN_ERR "Hammerfall-DSP: error creating alsa devices\n"); |
4689 | return err; | 4706 | return err; |
@@ -4730,18 +4747,16 @@ static int snd_hdsp_create_hwdep(struct snd_card *card, struct hdsp *hdsp) | |||
4730 | { | 4747 | { |
4731 | struct snd_hwdep *hw; | 4748 | struct snd_hwdep *hw; |
4732 | int err; | 4749 | int err; |
4733 | 4750 | ||
4734 | if ((err = snd_hwdep_new(card, "HDSP hwdep", 0, &hw)) < 0) | 4751 | if ((err = snd_hwdep_new(card, "HDSP hwdep", 0, &hw)) < 0) |
4735 | return err; | 4752 | return err; |
4736 | 4753 | ||
4737 | hdsp->hwdep = hw; | 4754 | hdsp->hwdep = hw; |
4738 | hw->private_data = hdsp; | 4755 | hw->private_data = hdsp; |
4739 | strcpy(hw->name, "HDSP hwdep interface"); | 4756 | strcpy(hw->name, "HDSP hwdep interface"); |
4740 | 4757 | ||
4741 | hw->ops.open = snd_hdsp_hwdep_dummy_op; | ||
4742 | hw->ops.ioctl = snd_hdsp_hwdep_ioctl; | 4758 | hw->ops.ioctl = snd_hdsp_hwdep_ioctl; |
4743 | hw->ops.release = snd_hdsp_hwdep_dummy_op; | 4759 | |
4744 | |||
4745 | return 0; | 4760 | return 0; |
4746 | } | 4761 | } |
4747 | 4762 | ||
@@ -4774,24 +4789,24 @@ static void snd_hdsp_9652_enable_mixer (struct hdsp *hdsp) | |||
4774 | static int snd_hdsp_enable_io (struct hdsp *hdsp) | 4789 | static int snd_hdsp_enable_io (struct hdsp *hdsp) |
4775 | { | 4790 | { |
4776 | int i; | 4791 | int i; |
4777 | 4792 | ||
4778 | if (hdsp_fifo_wait (hdsp, 0, 100)) { | 4793 | if (hdsp_fifo_wait (hdsp, 0, 100)) { |
4779 | snd_printk(KERN_ERR "Hammerfall-DSP: enable_io fifo_wait failed\n"); | 4794 | snd_printk(KERN_ERR "Hammerfall-DSP: enable_io fifo_wait failed\n"); |
4780 | return -EIO; | 4795 | return -EIO; |
4781 | } | 4796 | } |
4782 | 4797 | ||
4783 | for (i = 0; i < hdsp->max_channels; ++i) { | 4798 | for (i = 0; i < hdsp->max_channels; ++i) { |
4784 | hdsp_write (hdsp, HDSP_inputEnable + (4 * i), 1); | 4799 | hdsp_write (hdsp, HDSP_inputEnable + (4 * i), 1); |
4785 | hdsp_write (hdsp, HDSP_outputEnable + (4 * i), 1); | 4800 | hdsp_write (hdsp, HDSP_outputEnable + (4 * i), 1); |
4786 | } | 4801 | } |
4787 | 4802 | ||
4788 | return 0; | 4803 | return 0; |
4789 | } | 4804 | } |
4790 | 4805 | ||
4791 | static void snd_hdsp_initialize_channels(struct hdsp *hdsp) | 4806 | static void snd_hdsp_initialize_channels(struct hdsp *hdsp) |
4792 | { | 4807 | { |
4793 | int status, aebi_channels, aebo_channels; | 4808 | int status, aebi_channels, aebo_channels; |
4794 | 4809 | ||
4795 | switch (hdsp->io_type) { | 4810 | switch (hdsp->io_type) { |
4796 | case Digiface: | 4811 | case Digiface: |
4797 | hdsp->card_name = "RME Hammerfall DSP + Digiface"; | 4812 | hdsp->card_name = "RME Hammerfall DSP + Digiface"; |
@@ -4804,7 +4819,7 @@ static void snd_hdsp_initialize_channels(struct hdsp *hdsp) | |||
4804 | hdsp->ss_in_channels = hdsp->ss_out_channels = H9652_SS_CHANNELS; | 4819 | hdsp->ss_in_channels = hdsp->ss_out_channels = H9652_SS_CHANNELS; |
4805 | hdsp->ds_in_channels = hdsp->ds_out_channels = H9652_DS_CHANNELS; | 4820 | hdsp->ds_in_channels = hdsp->ds_out_channels = H9652_DS_CHANNELS; |
4806 | break; | 4821 | break; |
4807 | 4822 | ||
4808 | case H9632: | 4823 | case H9632: |
4809 | status = hdsp_read(hdsp, HDSP_statusRegister); | 4824 | status = hdsp_read(hdsp, HDSP_statusRegister); |
4810 | /* HDSP_AEBx bits are low when AEB are connected */ | 4825 | /* HDSP_AEBx bits are low when AEB are connected */ |
@@ -4824,7 +4839,7 @@ static void snd_hdsp_initialize_channels(struct hdsp *hdsp) | |||
4824 | hdsp->ss_in_channels = hdsp->ss_out_channels = MULTIFACE_SS_CHANNELS; | 4839 | hdsp->ss_in_channels = hdsp->ss_out_channels = MULTIFACE_SS_CHANNELS; |
4825 | hdsp->ds_in_channels = hdsp->ds_out_channels = MULTIFACE_DS_CHANNELS; | 4840 | hdsp->ds_in_channels = hdsp->ds_out_channels = MULTIFACE_DS_CHANNELS; |
4826 | break; | 4841 | break; |
4827 | 4842 | ||
4828 | default: | 4843 | default: |
4829 | /* should never get here */ | 4844 | /* should never get here */ |
4830 | break; | 4845 | break; |
@@ -4840,12 +4855,12 @@ static void snd_hdsp_initialize_midi_flush (struct hdsp *hdsp) | |||
4840 | static int snd_hdsp_create_alsa_devices(struct snd_card *card, struct hdsp *hdsp) | 4855 | static int snd_hdsp_create_alsa_devices(struct snd_card *card, struct hdsp *hdsp) |
4841 | { | 4856 | { |
4842 | int err; | 4857 | int err; |
4843 | 4858 | ||
4844 | if ((err = snd_hdsp_create_pcm(card, hdsp)) < 0) { | 4859 | if ((err = snd_hdsp_create_pcm(card, hdsp)) < 0) { |
4845 | snd_printk(KERN_ERR "Hammerfall-DSP: Error creating pcm interface\n"); | 4860 | snd_printk(KERN_ERR "Hammerfall-DSP: Error creating pcm interface\n"); |
4846 | return err; | 4861 | return err; |
4847 | } | 4862 | } |
4848 | 4863 | ||
4849 | 4864 | ||
4850 | if ((err = snd_hdsp_create_midi(card, hdsp, 0)) < 0) { | 4865 | if ((err = snd_hdsp_create_midi(card, hdsp, 0)) < 0) { |
4851 | snd_printk(KERN_ERR "Hammerfall-DSP: Error creating first midi interface\n"); | 4866 | snd_printk(KERN_ERR "Hammerfall-DSP: Error creating first midi interface\n"); |
@@ -4876,19 +4891,19 @@ static int snd_hdsp_create_alsa_devices(struct snd_card *card, struct hdsp *hdsp | |||
4876 | snd_printk(KERN_ERR "Hammerfall-DSP: Error setting default values\n"); | 4891 | snd_printk(KERN_ERR "Hammerfall-DSP: Error setting default values\n"); |
4877 | return err; | 4892 | return err; |
4878 | } | 4893 | } |
4879 | 4894 | ||
4880 | if (!(hdsp->state & HDSP_InitializationComplete)) { | 4895 | if (!(hdsp->state & HDSP_InitializationComplete)) { |
4881 | strcpy(card->shortname, "Hammerfall DSP"); | 4896 | strcpy(card->shortname, "Hammerfall DSP"); |
4882 | sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name, | 4897 | sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name, |
4883 | hdsp->port, hdsp->irq); | 4898 | hdsp->port, hdsp->irq); |
4884 | 4899 | ||
4885 | if ((err = snd_card_register(card)) < 0) { | 4900 | if ((err = snd_card_register(card)) < 0) { |
4886 | snd_printk(KERN_ERR "Hammerfall-DSP: error registering card\n"); | 4901 | snd_printk(KERN_ERR "Hammerfall-DSP: error registering card\n"); |
4887 | return err; | 4902 | return err; |
4888 | } | 4903 | } |
4889 | hdsp->state |= HDSP_InitializationComplete; | 4904 | hdsp->state |= HDSP_InitializationComplete; |
4890 | } | 4905 | } |
4891 | 4906 | ||
4892 | return 0; | 4907 | return 0; |
4893 | } | 4908 | } |
4894 | 4909 | ||
@@ -4899,7 +4914,7 @@ static int hdsp_request_fw_loader(struct hdsp *hdsp) | |||
4899 | const char *fwfile; | 4914 | const char *fwfile; |
4900 | const struct firmware *fw; | 4915 | const struct firmware *fw; |
4901 | int err; | 4916 | int err; |
4902 | 4917 | ||
4903 | if (hdsp->io_type == H9652 || hdsp->io_type == H9632) | 4918 | if (hdsp->io_type == H9652 || hdsp->io_type == H9632) |
4904 | return 0; | 4919 | return 0; |
4905 | if (hdsp->io_type == Undefined) { | 4920 | if (hdsp->io_type == Undefined) { |
@@ -4908,7 +4923,7 @@ static int hdsp_request_fw_loader(struct hdsp *hdsp) | |||
4908 | if (hdsp->io_type == H9652 || hdsp->io_type == H9632) | 4923 | if (hdsp->io_type == H9652 || hdsp->io_type == H9632) |
4909 | return 0; | 4924 | return 0; |
4910 | } | 4925 | } |
4911 | 4926 | ||
4912 | /* caution: max length of firmware filename is 30! */ | 4927 | /* caution: max length of firmware filename is 30! */ |
4913 | switch (hdsp->io_type) { | 4928 | switch (hdsp->io_type) { |
4914 | case Multiface: | 4929 | case Multiface: |
@@ -4942,12 +4957,12 @@ static int hdsp_request_fw_loader(struct hdsp *hdsp) | |||
4942 | memcpy(hdsp->firmware_cache, fw->data, sizeof(hdsp->firmware_cache)); | 4957 | memcpy(hdsp->firmware_cache, fw->data, sizeof(hdsp->firmware_cache)); |
4943 | 4958 | ||
4944 | release_firmware(fw); | 4959 | release_firmware(fw); |
4945 | 4960 | ||
4946 | hdsp->state |= HDSP_FirmwareCached; | 4961 | hdsp->state |= HDSP_FirmwareCached; |
4947 | 4962 | ||
4948 | if ((err = snd_hdsp_load_firmware_from_cache(hdsp)) < 0) | 4963 | if ((err = snd_hdsp_load_firmware_from_cache(hdsp)) < 0) |
4949 | return err; | 4964 | return err; |
4950 | 4965 | ||
4951 | if (!(hdsp->state & HDSP_InitializationComplete)) { | 4966 | if (!(hdsp->state & HDSP_InitializationComplete)) { |
4952 | if ((err = snd_hdsp_enable_io(hdsp)) < 0) | 4967 | if ((err = snd_hdsp_enable_io(hdsp)) < 0) |
4953 | return err; | 4968 | return err; |
@@ -4994,14 +5009,14 @@ static int __devinit snd_hdsp_create(struct snd_card *card, | |||
4994 | hdsp->max_channels = 26; | 5009 | hdsp->max_channels = 26; |
4995 | 5010 | ||
4996 | hdsp->card = card; | 5011 | hdsp->card = card; |
4997 | 5012 | ||
4998 | spin_lock_init(&hdsp->lock); | 5013 | spin_lock_init(&hdsp->lock); |
4999 | 5014 | ||
5000 | tasklet_init(&hdsp->midi_tasklet, hdsp_midi_tasklet, (unsigned long)hdsp); | 5015 | tasklet_init(&hdsp->midi_tasklet, hdsp_midi_tasklet, (unsigned long)hdsp); |
5001 | 5016 | ||
5002 | pci_read_config_word(hdsp->pci, PCI_CLASS_REVISION, &hdsp->firmware_rev); | 5017 | pci_read_config_word(hdsp->pci, PCI_CLASS_REVISION, &hdsp->firmware_rev); |
5003 | hdsp->firmware_rev &= 0xff; | 5018 | hdsp->firmware_rev &= 0xff; |
5004 | 5019 | ||
5005 | /* From Martin Bjoernsen : | 5020 | /* From Martin Bjoernsen : |
5006 | "It is important that the card's latency timer register in | 5021 | "It is important that the card's latency timer register in |
5007 | the PCI configuration space is set to a value much larger | 5022 | the PCI configuration space is set to a value much larger |
@@ -5010,7 +5025,7 @@ static int __devinit snd_hdsp_create(struct snd_card *card, | |||
5010 | to its maximum 255 to avoid problems with some computers." | 5025 | to its maximum 255 to avoid problems with some computers." |
5011 | */ | 5026 | */ |
5012 | pci_write_config_byte(hdsp->pci, PCI_LATENCY_TIMER, 0xFF); | 5027 | pci_write_config_byte(hdsp->pci, PCI_LATENCY_TIMER, 0xFF); |
5013 | 5028 | ||
5014 | strcpy(card->driver, "H-DSP"); | 5029 | strcpy(card->driver, "H-DSP"); |
5015 | strcpy(card->mixername, "Xilinx FPGA"); | 5030 | strcpy(card->mixername, "Xilinx FPGA"); |
5016 | 5031 | ||
@@ -5024,7 +5039,7 @@ static int __devinit snd_hdsp_create(struct snd_card *card, | |||
5024 | } else { | 5039 | } else { |
5025 | hdsp->card_name = "RME HDSP 9632"; | 5040 | hdsp->card_name = "RME HDSP 9632"; |
5026 | hdsp->max_channels = 16; | 5041 | hdsp->max_channels = 16; |
5027 | is_9632 = 1; | 5042 | is_9632 = 1; |
5028 | } | 5043 | } |
5029 | 5044 | ||
5030 | if ((err = pci_enable_device(pci)) < 0) | 5045 | if ((err = pci_enable_device(pci)) < 0) |
@@ -5053,12 +5068,12 @@ static int __devinit snd_hdsp_create(struct snd_card *card, | |||
5053 | 5068 | ||
5054 | if ((err = snd_hdsp_initialize_memory(hdsp)) < 0) | 5069 | if ((err = snd_hdsp_initialize_memory(hdsp)) < 0) |
5055 | return err; | 5070 | return err; |
5056 | 5071 | ||
5057 | if (!is_9652 && !is_9632) { | 5072 | if (!is_9652 && !is_9632) { |
5058 | /* we wait 2 seconds to let freshly inserted cardbus cards do their hardware init */ | 5073 | /* we wait a maximum of 10 seconds to let freshly |
5059 | ssleep(2); | 5074 | * inserted cardbus cards do their hardware init */ |
5075 | err = hdsp_wait_for_iobox(hdsp, 1000, 10); | ||
5060 | 5076 | ||
5061 | err = hdsp_check_for_iobox(hdsp); | ||
5062 | if (err < 0) | 5077 | if (err < 0) |
5063 | return err; | 5078 | return err; |
5064 | 5079 | ||
@@ -5080,35 +5095,35 @@ static int __devinit snd_hdsp_create(struct snd_card *card, | |||
5080 | return err; | 5095 | return err; |
5081 | return 0; | 5096 | return 0; |
5082 | } else { | 5097 | } else { |
5083 | snd_printk(KERN_INFO "Hammerfall-DSP: Firmware already present, initializing card.\n"); | 5098 | snd_printk(KERN_INFO "Hammerfall-DSP: Firmware already present, initializing card.\n"); |
5084 | if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1) | 5099 | if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1) |
5085 | hdsp->io_type = Multiface; | 5100 | hdsp->io_type = Multiface; |
5086 | else | 5101 | else |
5087 | hdsp->io_type = Digiface; | 5102 | hdsp->io_type = Digiface; |
5088 | } | 5103 | } |
5089 | } | 5104 | } |
5090 | 5105 | ||
5091 | if ((err = snd_hdsp_enable_io(hdsp)) != 0) | 5106 | if ((err = snd_hdsp_enable_io(hdsp)) != 0) |
5092 | return err; | 5107 | return err; |
5093 | 5108 | ||
5094 | if (is_9652) | 5109 | if (is_9652) |
5095 | hdsp->io_type = H9652; | 5110 | hdsp->io_type = H9652; |
5096 | 5111 | ||
5097 | if (is_9632) | 5112 | if (is_9632) |
5098 | hdsp->io_type = H9632; | 5113 | hdsp->io_type = H9632; |
5099 | 5114 | ||
5100 | if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) | 5115 | if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) |
5101 | return err; | 5116 | return err; |
5102 | 5117 | ||
5103 | snd_hdsp_initialize_channels(hdsp); | 5118 | snd_hdsp_initialize_channels(hdsp); |
5104 | snd_hdsp_initialize_midi_flush(hdsp); | 5119 | snd_hdsp_initialize_midi_flush(hdsp); |
5105 | 5120 | ||
5106 | hdsp->state |= HDSP_FirmwareLoaded; | 5121 | hdsp->state |= HDSP_FirmwareLoaded; |
5107 | 5122 | ||
5108 | if ((err = snd_hdsp_create_alsa_devices(card, hdsp)) < 0) | 5123 | if ((err = snd_hdsp_create_alsa_devices(card, hdsp)) < 0) |
5109 | return err; | 5124 | return err; |
5110 | 5125 | ||
5111 | return 0; | 5126 | return 0; |
5112 | } | 5127 | } |
5113 | 5128 | ||
5114 | static int snd_hdsp_free(struct hdsp *hdsp) | 5129 | static int snd_hdsp_free(struct hdsp *hdsp) |
@@ -5124,13 +5139,13 @@ static int snd_hdsp_free(struct hdsp *hdsp) | |||
5124 | free_irq(hdsp->irq, (void *)hdsp); | 5139 | free_irq(hdsp->irq, (void *)hdsp); |
5125 | 5140 | ||
5126 | snd_hdsp_free_buffers(hdsp); | 5141 | snd_hdsp_free_buffers(hdsp); |
5127 | 5142 | ||
5128 | if (hdsp->iobase) | 5143 | if (hdsp->iobase) |
5129 | iounmap(hdsp->iobase); | 5144 | iounmap(hdsp->iobase); |
5130 | 5145 | ||
5131 | if (hdsp->port) | 5146 | if (hdsp->port) |
5132 | pci_release_regions(hdsp->pci); | 5147 | pci_release_regions(hdsp->pci); |
5133 | 5148 | ||
5134 | pci_disable_device(hdsp->pci); | 5149 | pci_disable_device(hdsp->pci); |
5135 | return 0; | 5150 | return 0; |
5136 | } | 5151 | } |
@@ -5158,8 +5173,10 @@ static int __devinit snd_hdsp_probe(struct pci_dev *pci, | |||
5158 | return -ENOENT; | 5173 | return -ENOENT; |
5159 | } | 5174 | } |
5160 | 5175 | ||
5161 | if (!(card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(struct hdsp)))) | 5176 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, |
5162 | return -ENOMEM; | 5177 | sizeof(struct hdsp), &card); |
5178 | if (err < 0) | ||
5179 | return err; | ||
5163 | 5180 | ||
5164 | hdsp = (struct hdsp *) card->private_data; | 5181 | hdsp = (struct hdsp *) card->private_data; |
5165 | card->private_free = snd_hdsp_card_free; | 5182 | card->private_free = snd_hdsp_card_free; |
@@ -5173,7 +5190,7 @@ static int __devinit snd_hdsp_probe(struct pci_dev *pci, | |||
5173 | } | 5190 | } |
5174 | 5191 | ||
5175 | strcpy(card->shortname, "Hammerfall DSP"); | 5192 | strcpy(card->shortname, "Hammerfall DSP"); |
5176 | sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name, | 5193 | sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name, |
5177 | hdsp->port, hdsp->irq); | 5194 | hdsp->port, hdsp->irq); |
5178 | 5195 | ||
5179 | if ((err = snd_card_register(card)) < 0) { | 5196 | if ((err = snd_card_register(card)) < 0) { |
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 71231cf1b2b0..bac2dc0c5d85 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c | |||
@@ -4100,13 +4100,6 @@ static int snd_hdspm_capture_release(struct snd_pcm_substream *substream) | |||
4100 | return 0; | 4100 | return 0; |
4101 | } | 4101 | } |
4102 | 4102 | ||
4103 | static int snd_hdspm_hwdep_dummy_op(struct snd_hwdep * hw, struct file *file) | ||
4104 | { | ||
4105 | /* we have nothing to initialize but the call is required */ | ||
4106 | return 0; | ||
4107 | } | ||
4108 | |||
4109 | |||
4110 | static int snd_hdspm_hwdep_ioctl(struct snd_hwdep * hw, struct file *file, | 4103 | static int snd_hdspm_hwdep_ioctl(struct snd_hwdep * hw, struct file *file, |
4111 | unsigned int cmd, unsigned long arg) | 4104 | unsigned int cmd, unsigned long arg) |
4112 | { | 4105 | { |
@@ -4213,9 +4206,7 @@ static int __devinit snd_hdspm_create_hwdep(struct snd_card *card, | |||
4213 | hw->private_data = hdspm; | 4206 | hw->private_data = hdspm; |
4214 | strcpy(hw->name, "HDSPM hwdep interface"); | 4207 | strcpy(hw->name, "HDSPM hwdep interface"); |
4215 | 4208 | ||
4216 | hw->ops.open = snd_hdspm_hwdep_dummy_op; | ||
4217 | hw->ops.ioctl = snd_hdspm_hwdep_ioctl; | 4209 | hw->ops.ioctl = snd_hdspm_hwdep_ioctl; |
4218 | hw->ops.release = snd_hdspm_hwdep_dummy_op; | ||
4219 | 4210 | ||
4220 | return 0; | 4211 | return 0; |
4221 | } | 4212 | } |
@@ -4503,10 +4494,10 @@ static int __devinit snd_hdspm_probe(struct pci_dev *pci, | |||
4503 | return -ENOENT; | 4494 | return -ENOENT; |
4504 | } | 4495 | } |
4505 | 4496 | ||
4506 | card = snd_card_new(index[dev], id[dev], | 4497 | err = snd_card_create(index[dev], id[dev], |
4507 | THIS_MODULE, sizeof(struct hdspm)); | 4498 | THIS_MODULE, sizeof(struct hdspm), &card); |
4508 | if (!card) | 4499 | if (err < 0) |
4509 | return -ENOMEM; | 4500 | return err; |
4510 | 4501 | ||
4511 | hdspm = card->private_data; | 4502 | hdspm = card->private_data; |
4512 | card->private_free = snd_hdspm_card_free; | 4503 | card->private_free = snd_hdspm_card_free; |
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c index 2570907134d7..bc539abb2105 100644 --- a/sound/pci/rme9652/rme9652.c +++ b/sound/pci/rme9652/rme9652.c | |||
@@ -2594,11 +2594,11 @@ static int __devinit snd_rme9652_probe(struct pci_dev *pci, | |||
2594 | return -ENOENT; | 2594 | return -ENOENT; |
2595 | } | 2595 | } |
2596 | 2596 | ||
2597 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, | 2597 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, |
2598 | sizeof(struct snd_rme9652)); | 2598 | sizeof(struct snd_rme9652), &card); |
2599 | 2599 | ||
2600 | if (!card) | 2600 | if (err < 0) |
2601 | return -ENOMEM; | 2601 | return err; |
2602 | 2602 | ||
2603 | rme9652 = (struct snd_rme9652 *) card->private_data; | 2603 | rme9652 = (struct snd_rme9652 *) card->private_data; |
2604 | card->private_free = snd_rme9652_card_free; | 2604 | card->private_free = snd_rme9652_card_free; |
diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c index df2007e3be7c..baf6d8e3dabc 100644 --- a/sound/pci/sis7019.c +++ b/sound/pci/sis7019.c | |||
@@ -1387,9 +1387,8 @@ static int __devinit snd_sis7019_probe(struct pci_dev *pci, | |||
1387 | if (!enable) | 1387 | if (!enable) |
1388 | goto error_out; | 1388 | goto error_out; |
1389 | 1389 | ||
1390 | rc = -ENOMEM; | 1390 | rc = snd_card_create(index, id, THIS_MODULE, sizeof(*sis), &card); |
1391 | card = snd_card_new(index, id, THIS_MODULE, sizeof(*sis)); | 1391 | if (rc < 0) |
1392 | if (!card) | ||
1393 | goto error_out; | 1392 | goto error_out; |
1394 | 1393 | ||
1395 | strcpy(card->driver, "SiS7019"); | 1394 | strcpy(card->driver, "SiS7019"); |
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index cd408b86c839..d989215f3556 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c | |||
@@ -273,7 +273,8 @@ static inline void snd_sonicvibes_setdmaa(struct sonicvibes * sonic, | |||
273 | outl(count, sonic->dmaa_port + SV_DMA_COUNT0); | 273 | outl(count, sonic->dmaa_port + SV_DMA_COUNT0); |
274 | outb(0x18, sonic->dmaa_port + SV_DMA_MODE); | 274 | outb(0x18, sonic->dmaa_port + SV_DMA_MODE); |
275 | #if 0 | 275 | #if 0 |
276 | printk("program dmaa: addr = 0x%x, paddr = 0x%x\n", addr, inl(sonic->dmaa_port + SV_DMA_ADDR0)); | 276 | printk(KERN_DEBUG "program dmaa: addr = 0x%x, paddr = 0x%x\n", |
277 | addr, inl(sonic->dmaa_port + SV_DMA_ADDR0)); | ||
277 | #endif | 278 | #endif |
278 | } | 279 | } |
279 | 280 | ||
@@ -288,7 +289,8 @@ static inline void snd_sonicvibes_setdmac(struct sonicvibes * sonic, | |||
288 | outl(count, sonic->dmac_port + SV_DMA_COUNT0); | 289 | outl(count, sonic->dmac_port + SV_DMA_COUNT0); |
289 | outb(0x14, sonic->dmac_port + SV_DMA_MODE); | 290 | outb(0x14, sonic->dmac_port + SV_DMA_MODE); |
290 | #if 0 | 291 | #if 0 |
291 | printk("program dmac: addr = 0x%x, paddr = 0x%x\n", addr, inl(sonic->dmac_port + SV_DMA_ADDR0)); | 292 | printk(KERN_DEBUG "program dmac: addr = 0x%x, paddr = 0x%x\n", |
293 | addr, inl(sonic->dmac_port + SV_DMA_ADDR0)); | ||
292 | #endif | 294 | #endif |
293 | } | 295 | } |
294 | 296 | ||
@@ -355,71 +357,104 @@ static unsigned char snd_sonicvibes_in(struct sonicvibes * sonic, unsigned char | |||
355 | #if 0 | 357 | #if 0 |
356 | static void snd_sonicvibes_debug(struct sonicvibes * sonic) | 358 | static void snd_sonicvibes_debug(struct sonicvibes * sonic) |
357 | { | 359 | { |
358 | printk("SV REGS: INDEX = 0x%02x ", inb(SV_REG(sonic, INDEX))); | 360 | printk(KERN_DEBUG |
361 | "SV REGS: INDEX = 0x%02x ", inb(SV_REG(sonic, INDEX))); | ||
359 | printk(" STATUS = 0x%02x\n", inb(SV_REG(sonic, STATUS))); | 362 | printk(" STATUS = 0x%02x\n", inb(SV_REG(sonic, STATUS))); |
360 | printk(" 0x00: left input = 0x%02x ", snd_sonicvibes_in(sonic, 0x00)); | 363 | printk(KERN_DEBUG |
364 | " 0x00: left input = 0x%02x ", snd_sonicvibes_in(sonic, 0x00)); | ||
361 | printk(" 0x20: synth rate low = 0x%02x\n", snd_sonicvibes_in(sonic, 0x20)); | 365 | printk(" 0x20: synth rate low = 0x%02x\n", snd_sonicvibes_in(sonic, 0x20)); |
362 | printk(" 0x01: right input = 0x%02x ", snd_sonicvibes_in(sonic, 0x01)); | 366 | printk(KERN_DEBUG |
367 | " 0x01: right input = 0x%02x ", snd_sonicvibes_in(sonic, 0x01)); | ||
363 | printk(" 0x21: synth rate high = 0x%02x\n", snd_sonicvibes_in(sonic, 0x21)); | 368 | printk(" 0x21: synth rate high = 0x%02x\n", snd_sonicvibes_in(sonic, 0x21)); |
364 | printk(" 0x02: left AUX1 = 0x%02x ", snd_sonicvibes_in(sonic, 0x02)); | 369 | printk(KERN_DEBUG |
370 | " 0x02: left AUX1 = 0x%02x ", snd_sonicvibes_in(sonic, 0x02)); | ||
365 | printk(" 0x22: ADC clock = 0x%02x\n", snd_sonicvibes_in(sonic, 0x22)); | 371 | printk(" 0x22: ADC clock = 0x%02x\n", snd_sonicvibes_in(sonic, 0x22)); |
366 | printk(" 0x03: right AUX1 = 0x%02x ", snd_sonicvibes_in(sonic, 0x03)); | 372 | printk(KERN_DEBUG |
373 | " 0x03: right AUX1 = 0x%02x ", snd_sonicvibes_in(sonic, 0x03)); | ||
367 | printk(" 0x23: ADC alt rate = 0x%02x\n", snd_sonicvibes_in(sonic, 0x23)); | 374 | printk(" 0x23: ADC alt rate = 0x%02x\n", snd_sonicvibes_in(sonic, 0x23)); |
368 | printk(" 0x04: left CD = 0x%02x ", snd_sonicvibes_in(sonic, 0x04)); | 375 | printk(KERN_DEBUG |
376 | " 0x04: left CD = 0x%02x ", snd_sonicvibes_in(sonic, 0x04)); | ||
369 | printk(" 0x24: ADC pll M = 0x%02x\n", snd_sonicvibes_in(sonic, 0x24)); | 377 | printk(" 0x24: ADC pll M = 0x%02x\n", snd_sonicvibes_in(sonic, 0x24)); |
370 | printk(" 0x05: right CD = 0x%02x ", snd_sonicvibes_in(sonic, 0x05)); | 378 | printk(KERN_DEBUG |
379 | " 0x05: right CD = 0x%02x ", snd_sonicvibes_in(sonic, 0x05)); | ||
371 | printk(" 0x25: ADC pll N = 0x%02x\n", snd_sonicvibes_in(sonic, 0x25)); | 380 | printk(" 0x25: ADC pll N = 0x%02x\n", snd_sonicvibes_in(sonic, 0x25)); |
372 | printk(" 0x06: left line = 0x%02x ", snd_sonicvibes_in(sonic, 0x06)); | 381 | printk(KERN_DEBUG |
382 | " 0x06: left line = 0x%02x ", snd_sonicvibes_in(sonic, 0x06)); | ||
373 | printk(" 0x26: Synth pll M = 0x%02x\n", snd_sonicvibes_in(sonic, 0x26)); | 383 | printk(" 0x26: Synth pll M = 0x%02x\n", snd_sonicvibes_in(sonic, 0x26)); |
374 | printk(" 0x07: right line = 0x%02x ", snd_sonicvibes_in(sonic, 0x07)); | 384 | printk(KERN_DEBUG |
385 | " 0x07: right line = 0x%02x ", snd_sonicvibes_in(sonic, 0x07)); | ||
375 | printk(" 0x27: Synth pll N = 0x%02x\n", snd_sonicvibes_in(sonic, 0x27)); | 386 | printk(" 0x27: Synth pll N = 0x%02x\n", snd_sonicvibes_in(sonic, 0x27)); |
376 | printk(" 0x08: MIC = 0x%02x ", snd_sonicvibes_in(sonic, 0x08)); | 387 | printk(KERN_DEBUG |
388 | " 0x08: MIC = 0x%02x ", snd_sonicvibes_in(sonic, 0x08)); | ||
377 | printk(" 0x28: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x28)); | 389 | printk(" 0x28: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x28)); |
378 | printk(" 0x09: Game port = 0x%02x ", snd_sonicvibes_in(sonic, 0x09)); | 390 | printk(KERN_DEBUG |
391 | " 0x09: Game port = 0x%02x ", snd_sonicvibes_in(sonic, 0x09)); | ||
379 | printk(" 0x29: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x29)); | 392 | printk(" 0x29: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x29)); |
380 | printk(" 0x0a: left synth = 0x%02x ", snd_sonicvibes_in(sonic, 0x0a)); | 393 | printk(KERN_DEBUG |
394 | " 0x0a: left synth = 0x%02x ", snd_sonicvibes_in(sonic, 0x0a)); | ||
381 | printk(" 0x2a: MPU401 = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2a)); | 395 | printk(" 0x2a: MPU401 = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2a)); |
382 | printk(" 0x0b: right synth = 0x%02x ", snd_sonicvibes_in(sonic, 0x0b)); | 396 | printk(KERN_DEBUG |
397 | " 0x0b: right synth = 0x%02x ", snd_sonicvibes_in(sonic, 0x0b)); | ||
383 | printk(" 0x2b: drive ctrl = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2b)); | 398 | printk(" 0x2b: drive ctrl = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2b)); |
384 | printk(" 0x0c: left AUX2 = 0x%02x ", snd_sonicvibes_in(sonic, 0x0c)); | 399 | printk(KERN_DEBUG |
400 | " 0x0c: left AUX2 = 0x%02x ", snd_sonicvibes_in(sonic, 0x0c)); | ||
385 | printk(" 0x2c: SRS space = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2c)); | 401 | printk(" 0x2c: SRS space = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2c)); |
386 | printk(" 0x0d: right AUX2 = 0x%02x ", snd_sonicvibes_in(sonic, 0x0d)); | 402 | printk(KERN_DEBUG |
403 | " 0x0d: right AUX2 = 0x%02x ", snd_sonicvibes_in(sonic, 0x0d)); | ||
387 | printk(" 0x2d: SRS center = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2d)); | 404 | printk(" 0x2d: SRS center = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2d)); |
388 | printk(" 0x0e: left analog = 0x%02x ", snd_sonicvibes_in(sonic, 0x0e)); | 405 | printk(KERN_DEBUG |
406 | " 0x0e: left analog = 0x%02x ", snd_sonicvibes_in(sonic, 0x0e)); | ||
389 | printk(" 0x2e: wave source = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2e)); | 407 | printk(" 0x2e: wave source = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2e)); |
390 | printk(" 0x0f: right analog = 0x%02x ", snd_sonicvibes_in(sonic, 0x0f)); | 408 | printk(KERN_DEBUG |
409 | " 0x0f: right analog = 0x%02x ", snd_sonicvibes_in(sonic, 0x0f)); | ||
391 | printk(" 0x2f: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2f)); | 410 | printk(" 0x2f: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2f)); |
392 | printk(" 0x10: left PCM = 0x%02x ", snd_sonicvibes_in(sonic, 0x10)); | 411 | printk(KERN_DEBUG |
412 | " 0x10: left PCM = 0x%02x ", snd_sonicvibes_in(sonic, 0x10)); | ||
393 | printk(" 0x30: analog power = 0x%02x\n", snd_sonicvibes_in(sonic, 0x30)); | 413 | printk(" 0x30: analog power = 0x%02x\n", snd_sonicvibes_in(sonic, 0x30)); |
394 | printk(" 0x11: right PCM = 0x%02x ", snd_sonicvibes_in(sonic, 0x11)); | 414 | printk(KERN_DEBUG |
415 | " 0x11: right PCM = 0x%02x ", snd_sonicvibes_in(sonic, 0x11)); | ||
395 | printk(" 0x31: analog power = 0x%02x\n", snd_sonicvibes_in(sonic, 0x31)); | 416 | printk(" 0x31: analog power = 0x%02x\n", snd_sonicvibes_in(sonic, 0x31)); |
396 | printk(" 0x12: DMA data format = 0x%02x ", snd_sonicvibes_in(sonic, 0x12)); | 417 | printk(KERN_DEBUG |
418 | " 0x12: DMA data format = 0x%02x ", snd_sonicvibes_in(sonic, 0x12)); | ||
397 | printk(" 0x32: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x32)); | 419 | printk(" 0x32: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x32)); |
398 | printk(" 0x13: P/C enable = 0x%02x ", snd_sonicvibes_in(sonic, 0x13)); | 420 | printk(KERN_DEBUG |
421 | " 0x13: P/C enable = 0x%02x ", snd_sonicvibes_in(sonic, 0x13)); | ||
399 | printk(" 0x33: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x33)); | 422 | printk(" 0x33: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x33)); |
400 | printk(" 0x14: U/D button = 0x%02x ", snd_sonicvibes_in(sonic, 0x14)); | 423 | printk(KERN_DEBUG |
424 | " 0x14: U/D button = 0x%02x ", snd_sonicvibes_in(sonic, 0x14)); | ||
401 | printk(" 0x34: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x34)); | 425 | printk(" 0x34: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x34)); |
402 | printk(" 0x15: revision = 0x%02x ", snd_sonicvibes_in(sonic, 0x15)); | 426 | printk(KERN_DEBUG |
427 | " 0x15: revision = 0x%02x ", snd_sonicvibes_in(sonic, 0x15)); | ||
403 | printk(" 0x35: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x35)); | 428 | printk(" 0x35: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x35)); |
404 | printk(" 0x16: ADC output ctrl = 0x%02x ", snd_sonicvibes_in(sonic, 0x16)); | 429 | printk(KERN_DEBUG |
430 | " 0x16: ADC output ctrl = 0x%02x ", snd_sonicvibes_in(sonic, 0x16)); | ||
405 | printk(" 0x36: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x36)); | 431 | printk(" 0x36: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x36)); |
406 | printk(" 0x17: --- = 0x%02x ", snd_sonicvibes_in(sonic, 0x17)); | 432 | printk(KERN_DEBUG |
433 | " 0x17: --- = 0x%02x ", snd_sonicvibes_in(sonic, 0x17)); | ||
407 | printk(" 0x37: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x37)); | 434 | printk(" 0x37: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x37)); |
408 | printk(" 0x18: DMA A upper cnt = 0x%02x ", snd_sonicvibes_in(sonic, 0x18)); | 435 | printk(KERN_DEBUG |
436 | " 0x18: DMA A upper cnt = 0x%02x ", snd_sonicvibes_in(sonic, 0x18)); | ||
409 | printk(" 0x38: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x38)); | 437 | printk(" 0x38: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x38)); |
410 | printk(" 0x19: DMA A lower cnt = 0x%02x ", snd_sonicvibes_in(sonic, 0x19)); | 438 | printk(KERN_DEBUG |
439 | " 0x19: DMA A lower cnt = 0x%02x ", snd_sonicvibes_in(sonic, 0x19)); | ||
411 | printk(" 0x39: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x39)); | 440 | printk(" 0x39: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x39)); |
412 | printk(" 0x1a: --- = 0x%02x ", snd_sonicvibes_in(sonic, 0x1a)); | 441 | printk(KERN_DEBUG |
442 | " 0x1a: --- = 0x%02x ", snd_sonicvibes_in(sonic, 0x1a)); | ||
413 | printk(" 0x3a: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3a)); | 443 | printk(" 0x3a: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3a)); |
414 | printk(" 0x1b: --- = 0x%02x ", snd_sonicvibes_in(sonic, 0x1b)); | 444 | printk(KERN_DEBUG |
445 | " 0x1b: --- = 0x%02x ", snd_sonicvibes_in(sonic, 0x1b)); | ||
415 | printk(" 0x3b: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3b)); | 446 | printk(" 0x3b: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3b)); |
416 | printk(" 0x1c: DMA C upper cnt = 0x%02x ", snd_sonicvibes_in(sonic, 0x1c)); | 447 | printk(KERN_DEBUG |
448 | " 0x1c: DMA C upper cnt = 0x%02x ", snd_sonicvibes_in(sonic, 0x1c)); | ||
417 | printk(" 0x3c: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3c)); | 449 | printk(" 0x3c: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3c)); |
418 | printk(" 0x1d: DMA C upper cnt = 0x%02x ", snd_sonicvibes_in(sonic, 0x1d)); | 450 | printk(KERN_DEBUG |
451 | " 0x1d: DMA C upper cnt = 0x%02x ", snd_sonicvibes_in(sonic, 0x1d)); | ||
419 | printk(" 0x3d: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3d)); | 452 | printk(" 0x3d: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3d)); |
420 | printk(" 0x1e: PCM rate low = 0x%02x ", snd_sonicvibes_in(sonic, 0x1e)); | 453 | printk(KERN_DEBUG |
454 | " 0x1e: PCM rate low = 0x%02x ", snd_sonicvibes_in(sonic, 0x1e)); | ||
421 | printk(" 0x3e: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3e)); | 455 | printk(" 0x3e: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3e)); |
422 | printk(" 0x1f: PCM rate high = 0x%02x ", snd_sonicvibes_in(sonic, 0x1f)); | 456 | printk(KERN_DEBUG |
457 | " 0x1f: PCM rate high = 0x%02x ", snd_sonicvibes_in(sonic, 0x1f)); | ||
423 | printk(" 0x3f: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3f)); | 458 | printk(" 0x3f: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3f)); |
424 | } | 459 | } |
425 | 460 | ||
@@ -476,8 +511,8 @@ static void snd_sonicvibes_pll(unsigned int rate, | |||
476 | *res_m = m; | 511 | *res_m = m; |
477 | *res_n = n; | 512 | *res_n = n; |
478 | #if 0 | 513 | #if 0 |
479 | printk("metric = %i, xm = %i, xn = %i\n", metric, xm, xn); | 514 | printk(KERN_DEBUG "metric = %i, xm = %i, xn = %i\n", metric, xm, xn); |
480 | printk("pll: m = 0x%x, r = 0x%x, n = 0x%x\n", reg, m, r, n); | 515 | printk(KERN_DEBUG "pll: m = 0x%x, r = 0x%x, n = 0x%x\n", reg, m, r, n); |
481 | #endif | 516 | #endif |
482 | } | 517 | } |
483 | 518 | ||
@@ -1423,9 +1458,9 @@ static int __devinit snd_sonic_probe(struct pci_dev *pci, | |||
1423 | return -ENOENT; | 1458 | return -ENOENT; |
1424 | } | 1459 | } |
1425 | 1460 | ||
1426 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 1461 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); |
1427 | if (card == NULL) | 1462 | if (err < 0) |
1428 | return -ENOMEM; | 1463 | return err; |
1429 | for (idx = 0; idx < 5; idx++) { | 1464 | for (idx = 0; idx < 5; idx++) { |
1430 | if (pci_resource_start(pci, idx) == 0 || | 1465 | if (pci_resource_start(pci, idx) == 0 || |
1431 | !(pci_resource_flags(pci, idx) & IORESOURCE_IO)) { | 1466 | !(pci_resource_flags(pci, idx) & IORESOURCE_IO)) { |
diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c index d94b16ffb385..21cef97d478d 100644 --- a/sound/pci/trident/trident.c +++ b/sound/pci/trident/trident.c | |||
@@ -89,9 +89,9 @@ static int __devinit snd_trident_probe(struct pci_dev *pci, | |||
89 | return -ENOENT; | 89 | return -ENOENT; |
90 | } | 90 | } |
91 | 91 | ||
92 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 92 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); |
93 | if (card == NULL) | 93 | if (err < 0) |
94 | return -ENOMEM; | 94 | return err; |
95 | 95 | ||
96 | if ((err = snd_trident_create(card, pci, | 96 | if ((err = snd_trident_create(card, pci, |
97 | pcm_channels[dev], | 97 | pcm_channels[dev], |
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index c612b435ca2b..a9da9c184660 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c | |||
@@ -68,40 +68,40 @@ static void snd_trident_print_voice_regs(struct snd_trident *trident, int voice) | |||
68 | { | 68 | { |
69 | unsigned int val, tmp; | 69 | unsigned int val, tmp; |
70 | 70 | ||
71 | printk("Trident voice %i:\n", voice); | 71 | printk(KERN_DEBUG "Trident voice %i:\n", voice); |
72 | outb(voice, TRID_REG(trident, T4D_LFO_GC_CIR)); | 72 | outb(voice, TRID_REG(trident, T4D_LFO_GC_CIR)); |
73 | val = inl(TRID_REG(trident, CH_LBA)); | 73 | val = inl(TRID_REG(trident, CH_LBA)); |
74 | printk("LBA: 0x%x\n", val); | 74 | printk(KERN_DEBUG "LBA: 0x%x\n", val); |
75 | val = inl(TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC)); | 75 | val = inl(TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC)); |
76 | printk("GVSel: %i\n", val >> 31); | 76 | printk(KERN_DEBUG "GVSel: %i\n", val >> 31); |
77 | printk("Pan: 0x%x\n", (val >> 24) & 0x7f); | 77 | printk(KERN_DEBUG "Pan: 0x%x\n", (val >> 24) & 0x7f); |
78 | printk("Vol: 0x%x\n", (val >> 16) & 0xff); | 78 | printk(KERN_DEBUG "Vol: 0x%x\n", (val >> 16) & 0xff); |
79 | printk("CTRL: 0x%x\n", (val >> 12) & 0x0f); | 79 | printk(KERN_DEBUG "CTRL: 0x%x\n", (val >> 12) & 0x0f); |
80 | printk("EC: 0x%x\n", val & 0x0fff); | 80 | printk(KERN_DEBUG "EC: 0x%x\n", val & 0x0fff); |
81 | if (trident->device != TRIDENT_DEVICE_ID_NX) { | 81 | if (trident->device != TRIDENT_DEVICE_ID_NX) { |
82 | val = inl(TRID_REG(trident, CH_DX_CSO_ALPHA_FMS)); | 82 | val = inl(TRID_REG(trident, CH_DX_CSO_ALPHA_FMS)); |
83 | printk("CSO: 0x%x\n", val >> 16); | 83 | printk(KERN_DEBUG "CSO: 0x%x\n", val >> 16); |
84 | printk("Alpha: 0x%x\n", (val >> 4) & 0x0fff); | 84 | printk("Alpha: 0x%x\n", (val >> 4) & 0x0fff); |
85 | printk("FMS: 0x%x\n", val & 0x0f); | 85 | printk(KERN_DEBUG "FMS: 0x%x\n", val & 0x0f); |
86 | val = inl(TRID_REG(trident, CH_DX_ESO_DELTA)); | 86 | val = inl(TRID_REG(trident, CH_DX_ESO_DELTA)); |
87 | printk("ESO: 0x%x\n", val >> 16); | 87 | printk(KERN_DEBUG "ESO: 0x%x\n", val >> 16); |
88 | printk("Delta: 0x%x\n", val & 0xffff); | 88 | printk(KERN_DEBUG "Delta: 0x%x\n", val & 0xffff); |
89 | val = inl(TRID_REG(trident, CH_DX_FMC_RVOL_CVOL)); | 89 | val = inl(TRID_REG(trident, CH_DX_FMC_RVOL_CVOL)); |
90 | } else { // TRIDENT_DEVICE_ID_NX | 90 | } else { // TRIDENT_DEVICE_ID_NX |
91 | val = inl(TRID_REG(trident, CH_NX_DELTA_CSO)); | 91 | val = inl(TRID_REG(trident, CH_NX_DELTA_CSO)); |
92 | tmp = (val >> 24) & 0xff; | 92 | tmp = (val >> 24) & 0xff; |
93 | printk("CSO: 0x%x\n", val & 0x00ffffff); | 93 | printk(KERN_DEBUG "CSO: 0x%x\n", val & 0x00ffffff); |
94 | val = inl(TRID_REG(trident, CH_NX_DELTA_ESO)); | 94 | val = inl(TRID_REG(trident, CH_NX_DELTA_ESO)); |
95 | tmp |= (val >> 16) & 0xff00; | 95 | tmp |= (val >> 16) & 0xff00; |
96 | printk("Delta: 0x%x\n", tmp); | 96 | printk(KERN_DEBUG "Delta: 0x%x\n", tmp); |
97 | printk("ESO: 0x%x\n", val & 0x00ffffff); | 97 | printk(KERN_DEBUG "ESO: 0x%x\n", val & 0x00ffffff); |
98 | val = inl(TRID_REG(trident, CH_NX_ALPHA_FMS_FMC_RVOL_CVOL)); | 98 | val = inl(TRID_REG(trident, CH_NX_ALPHA_FMS_FMC_RVOL_CVOL)); |
99 | printk("Alpha: 0x%x\n", val >> 20); | 99 | printk(KERN_DEBUG "Alpha: 0x%x\n", val >> 20); |
100 | printk("FMS: 0x%x\n", (val >> 16) & 0x0f); | 100 | printk(KERN_DEBUG "FMS: 0x%x\n", (val >> 16) & 0x0f); |
101 | } | 101 | } |
102 | printk("FMC: 0x%x\n", (val >> 14) & 3); | 102 | printk(KERN_DEBUG "FMC: 0x%x\n", (val >> 14) & 3); |
103 | printk("RVol: 0x%x\n", (val >> 7) & 0x7f); | 103 | printk(KERN_DEBUG "RVol: 0x%x\n", (val >> 7) & 0x7f); |
104 | printk("CVol: 0x%x\n", val & 0x7f); | 104 | printk(KERN_DEBUG "CVol: 0x%x\n", val & 0x7f); |
105 | } | 105 | } |
106 | #endif | 106 | #endif |
107 | 107 | ||
@@ -496,12 +496,17 @@ void snd_trident_write_voice_regs(struct snd_trident * trident, | |||
496 | outl(regs[4], TRID_REG(trident, CH_START + 16)); | 496 | outl(regs[4], TRID_REG(trident, CH_START + 16)); |
497 | 497 | ||
498 | #if 0 | 498 | #if 0 |
499 | printk("written %i channel:\n", voice->number); | 499 | printk(KERN_DEBUG "written %i channel:\n", voice->number); |
500 | printk(" regs[0] = 0x%x/0x%x\n", regs[0], inl(TRID_REG(trident, CH_START + 0))); | 500 | printk(KERN_DEBUG " regs[0] = 0x%x/0x%x\n", |
501 | printk(" regs[1] = 0x%x/0x%x\n", regs[1], inl(TRID_REG(trident, CH_START + 4))); | 501 | regs[0], inl(TRID_REG(trident, CH_START + 0))); |
502 | printk(" regs[2] = 0x%x/0x%x\n", regs[2], inl(TRID_REG(trident, CH_START + 8))); | 502 | printk(KERN_DEBUG " regs[1] = 0x%x/0x%x\n", |
503 | printk(" regs[3] = 0x%x/0x%x\n", regs[3], inl(TRID_REG(trident, CH_START + 12))); | 503 | regs[1], inl(TRID_REG(trident, CH_START + 4))); |
504 | printk(" regs[4] = 0x%x/0x%x\n", regs[4], inl(TRID_REG(trident, CH_START + 16))); | 504 | printk(KERN_DEBUG " regs[2] = 0x%x/0x%x\n", |
505 | regs[2], inl(TRID_REG(trident, CH_START + 8))); | ||
506 | printk(KERN_DEBUG " regs[3] = 0x%x/0x%x\n", | ||
507 | regs[3], inl(TRID_REG(trident, CH_START + 12))); | ||
508 | printk(KERN_DEBUG " regs[4] = 0x%x/0x%x\n", | ||
509 | regs[4], inl(TRID_REG(trident, CH_START + 16))); | ||
505 | #endif | 510 | #endif |
506 | } | 511 | } |
507 | 512 | ||
@@ -583,7 +588,7 @@ static void snd_trident_write_vol_reg(struct snd_trident * trident, | |||
583 | outb(voice->Vol >> 2, TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC + 2)); | 588 | outb(voice->Vol >> 2, TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC + 2)); |
584 | break; | 589 | break; |
585 | case TRIDENT_DEVICE_ID_SI7018: | 590 | case TRIDENT_DEVICE_ID_SI7018: |
586 | // printk("voice->Vol = 0x%x\n", voice->Vol); | 591 | /* printk(KERN_DEBUG "voice->Vol = 0x%x\n", voice->Vol); */ |
587 | outw((voice->CTRL << 12) | voice->Vol, | 592 | outw((voice->CTRL << 12) | voice->Vol, |
588 | TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC)); | 593 | TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC)); |
589 | break; | 594 | break; |
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 1aafe956ee2b..809b233dd4a3 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c | |||
@@ -466,7 +466,10 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre | |||
466 | flag = VIA_TBL_BIT_FLAG; /* period boundary */ | 466 | flag = VIA_TBL_BIT_FLAG; /* period boundary */ |
467 | } else | 467 | } else |
468 | flag = 0; /* period continues to the next */ | 468 | flag = 0; /* period continues to the next */ |
469 | // printk("via: tbl %d: at %d size %d (rest %d)\n", idx, ofs, r, rest); | 469 | /* |
470 | printk(KERN_DEBUG "via: tbl %d: at %d size %d " | ||
471 | "(rest %d)\n", idx, ofs, r, rest); | ||
472 | */ | ||
470 | ((u32 *)dev->table.area)[(idx<<1) + 1] = cpu_to_le32(r | flag); | 473 | ((u32 *)dev->table.area)[(idx<<1) + 1] = cpu_to_le32(r | flag); |
471 | dev->idx_table[idx].offset = ofs; | 474 | dev->idx_table[idx].offset = ofs; |
472 | dev->idx_table[idx].size = r; | 475 | dev->idx_table[idx].size = r; |
@@ -2360,14 +2363,14 @@ static struct snd_pci_quirk dxs_whitelist[] __devinitdata = { | |||
2360 | SND_PCI_QUIRK(0x1019, 0x0996, "ESC Mobo", VIA_DXS_48K), | 2363 | SND_PCI_QUIRK(0x1019, 0x0996, "ESC Mobo", VIA_DXS_48K), |
2361 | SND_PCI_QUIRK(0x1019, 0x0a81, "ECS K7VTA3 v8.0", VIA_DXS_NO_VRA), | 2364 | SND_PCI_QUIRK(0x1019, 0x0a81, "ECS K7VTA3 v8.0", VIA_DXS_NO_VRA), |
2362 | SND_PCI_QUIRK(0x1019, 0x0a85, "ECS L7VMM2", VIA_DXS_NO_VRA), | 2365 | SND_PCI_QUIRK(0x1019, 0x0a85, "ECS L7VMM2", VIA_DXS_NO_VRA), |
2363 | SND_PCI_QUIRK(0x1019, 0, "ESC K8", VIA_DXS_SRC), | 2366 | SND_PCI_QUIRK_VENDOR(0x1019, "ESC K8", VIA_DXS_SRC), |
2364 | SND_PCI_QUIRK(0x1019, 0xaa01, "ESC K8T890-A", VIA_DXS_SRC), | 2367 | SND_PCI_QUIRK(0x1019, 0xaa01, "ESC K8T890-A", VIA_DXS_SRC), |
2365 | SND_PCI_QUIRK(0x1025, 0x0033, "Acer Inspire 1353LM", VIA_DXS_NO_VRA), | 2368 | SND_PCI_QUIRK(0x1025, 0x0033, "Acer Inspire 1353LM", VIA_DXS_NO_VRA), |
2366 | SND_PCI_QUIRK(0x1025, 0x0046, "Acer Aspire 1524 WLMi", VIA_DXS_SRC), | 2369 | SND_PCI_QUIRK(0x1025, 0x0046, "Acer Aspire 1524 WLMi", VIA_DXS_SRC), |
2367 | SND_PCI_QUIRK(0x1043, 0, "ASUS A7/A8", VIA_DXS_NO_VRA), | 2370 | SND_PCI_QUIRK_VENDOR(0x1043, "ASUS A7/A8", VIA_DXS_NO_VRA), |
2368 | SND_PCI_QUIRK(0x1071, 0, "Diverse Notebook", VIA_DXS_NO_VRA), | 2371 | SND_PCI_QUIRK_VENDOR(0x1071, "Diverse Notebook", VIA_DXS_NO_VRA), |
2369 | SND_PCI_QUIRK(0x10cf, 0x118e, "FSC Laptop", VIA_DXS_ENABLE), | 2372 | SND_PCI_QUIRK(0x10cf, 0x118e, "FSC Laptop", VIA_DXS_ENABLE), |
2370 | SND_PCI_QUIRK(0x1106, 0, "ASRock", VIA_DXS_SRC), | 2373 | SND_PCI_QUIRK_VENDOR(0x1106, "ASRock", VIA_DXS_SRC), |
2371 | SND_PCI_QUIRK(0x1297, 0xa231, "Shuttle AK31v2", VIA_DXS_SRC), | 2374 | SND_PCI_QUIRK(0x1297, 0xa231, "Shuttle AK31v2", VIA_DXS_SRC), |
2372 | SND_PCI_QUIRK(0x1297, 0xa232, "Shuttle", VIA_DXS_SRC), | 2375 | SND_PCI_QUIRK(0x1297, 0xa232, "Shuttle", VIA_DXS_SRC), |
2373 | SND_PCI_QUIRK(0x1297, 0xc160, "Shuttle Sk41G", VIA_DXS_SRC), | 2376 | SND_PCI_QUIRK(0x1297, 0xc160, "Shuttle Sk41G", VIA_DXS_SRC), |
@@ -2375,7 +2378,7 @@ static struct snd_pci_quirk dxs_whitelist[] __devinitdata = { | |||
2375 | SND_PCI_QUIRK(0x1462, 0x3800, "MSI KT266", VIA_DXS_ENABLE), | 2378 | SND_PCI_QUIRK(0x1462, 0x3800, "MSI KT266", VIA_DXS_ENABLE), |
2376 | SND_PCI_QUIRK(0x1462, 0x7120, "MSI KT4V", VIA_DXS_ENABLE), | 2379 | SND_PCI_QUIRK(0x1462, 0x7120, "MSI KT4V", VIA_DXS_ENABLE), |
2377 | SND_PCI_QUIRK(0x1462, 0x7142, "MSI K8MM-V", VIA_DXS_ENABLE), | 2380 | SND_PCI_QUIRK(0x1462, 0x7142, "MSI K8MM-V", VIA_DXS_ENABLE), |
2378 | SND_PCI_QUIRK(0x1462, 0, "MSI Mobo", VIA_DXS_SRC), | 2381 | SND_PCI_QUIRK_VENDOR(0x1462, "MSI Mobo", VIA_DXS_SRC), |
2379 | SND_PCI_QUIRK(0x147b, 0x1401, "ABIT KD7(-RAID)", VIA_DXS_ENABLE), | 2382 | SND_PCI_QUIRK(0x147b, 0x1401, "ABIT KD7(-RAID)", VIA_DXS_ENABLE), |
2380 | SND_PCI_QUIRK(0x147b, 0x1411, "ABIT VA-20", VIA_DXS_ENABLE), | 2383 | SND_PCI_QUIRK(0x147b, 0x1411, "ABIT VA-20", VIA_DXS_ENABLE), |
2381 | SND_PCI_QUIRK(0x147b, 0x1413, "ABIT KV8 Pro", VIA_DXS_ENABLE), | 2384 | SND_PCI_QUIRK(0x147b, 0x1413, "ABIT KV8 Pro", VIA_DXS_ENABLE), |
@@ -2389,11 +2392,11 @@ static struct snd_pci_quirk dxs_whitelist[] __devinitdata = { | |||
2389 | SND_PCI_QUIRK(0x161f, 0x2032, "m680x machines", VIA_DXS_48K), | 2392 | SND_PCI_QUIRK(0x161f, 0x2032, "m680x machines", VIA_DXS_48K), |
2390 | SND_PCI_QUIRK(0x1631, 0xe004, "PB EasyNote 3174", VIA_DXS_ENABLE), | 2393 | SND_PCI_QUIRK(0x1631, 0xe004, "PB EasyNote 3174", VIA_DXS_ENABLE), |
2391 | SND_PCI_QUIRK(0x1695, 0x3005, "EPoX EP-8K9A", VIA_DXS_ENABLE), | 2394 | SND_PCI_QUIRK(0x1695, 0x3005, "EPoX EP-8K9A", VIA_DXS_ENABLE), |
2392 | SND_PCI_QUIRK(0x1695, 0, "EPoX mobo", VIA_DXS_SRC), | 2395 | SND_PCI_QUIRK_VENDOR(0x1695, "EPoX mobo", VIA_DXS_SRC), |
2393 | SND_PCI_QUIRK(0x16f3, 0, "Jetway K8", VIA_DXS_SRC), | 2396 | SND_PCI_QUIRK_VENDOR(0x16f3, "Jetway K8", VIA_DXS_SRC), |
2394 | SND_PCI_QUIRK(0x1734, 0, "FSC Laptop", VIA_DXS_SRC), | 2397 | SND_PCI_QUIRK_VENDOR(0x1734, "FSC Laptop", VIA_DXS_SRC), |
2395 | SND_PCI_QUIRK(0x1849, 0x3059, "ASRock K7VM2", VIA_DXS_NO_VRA), | 2398 | SND_PCI_QUIRK(0x1849, 0x3059, "ASRock K7VM2", VIA_DXS_NO_VRA), |
2396 | SND_PCI_QUIRK(0x1849, 0, "ASRock mobo", VIA_DXS_SRC), | 2399 | SND_PCI_QUIRK_VENDOR(0x1849, "ASRock mobo", VIA_DXS_SRC), |
2397 | SND_PCI_QUIRK(0x1919, 0x200a, "Soltek SL-K8", VIA_DXS_NO_VRA), | 2400 | SND_PCI_QUIRK(0x1919, 0x200a, "Soltek SL-K8", VIA_DXS_NO_VRA), |
2398 | SND_PCI_QUIRK(0x4005, 0x4710, "MSI K7T266", VIA_DXS_SRC), | 2401 | SND_PCI_QUIRK(0x4005, 0x4710, "MSI K7T266", VIA_DXS_SRC), |
2399 | { } /* terminator */ | 2402 | { } /* terminator */ |
@@ -2433,9 +2436,9 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci, | |||
2433 | unsigned int i; | 2436 | unsigned int i; |
2434 | int err; | 2437 | int err; |
2435 | 2438 | ||
2436 | card = snd_card_new(index, id, THIS_MODULE, 0); | 2439 | err = snd_card_create(index, id, THIS_MODULE, 0, &card); |
2437 | if (card == NULL) | 2440 | if (err < 0) |
2438 | return -ENOMEM; | 2441 | return err; |
2439 | 2442 | ||
2440 | card_type = pci_id->driver_data; | 2443 | card_type = pci_id->driver_data; |
2441 | switch (card_type) { | 2444 | switch (card_type) { |
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index 5bd79d2a5a15..0d54e3503c1e 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c | |||
@@ -328,7 +328,10 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre | |||
328 | flag = VIA_TBL_BIT_FLAG; /* period boundary */ | 328 | flag = VIA_TBL_BIT_FLAG; /* period boundary */ |
329 | } else | 329 | } else |
330 | flag = 0; /* period continues to the next */ | 330 | flag = 0; /* period continues to the next */ |
331 | // printk("via: tbl %d: at %d size %d (rest %d)\n", idx, ofs, r, rest); | 331 | /* |
332 | printk(KERN_DEBUG "via: tbl %d: at %d size %d " | ||
333 | "(rest %d)\n", idx, ofs, r, rest); | ||
334 | */ | ||
332 | ((u32 *)dev->table.area)[(idx<<1) + 1] = cpu_to_le32(r | flag); | 335 | ((u32 *)dev->table.area)[(idx<<1) + 1] = cpu_to_le32(r | flag); |
333 | dev->idx_table[idx].offset = ofs; | 336 | dev->idx_table[idx].offset = ofs; |
334 | dev->idx_table[idx].size = r; | 337 | dev->idx_table[idx].size = r; |
@@ -1167,9 +1170,9 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci, | |||
1167 | unsigned int i; | 1170 | unsigned int i; |
1168 | int err; | 1171 | int err; |
1169 | 1172 | ||
1170 | card = snd_card_new(index, id, THIS_MODULE, 0); | 1173 | err = snd_card_create(index, id, THIS_MODULE, 0, &card); |
1171 | if (card == NULL) | 1174 | if (err < 0) |
1172 | return -ENOMEM; | 1175 | return err; |
1173 | 1176 | ||
1174 | card_type = pci_id->driver_data; | 1177 | card_type = pci_id->driver_data; |
1175 | switch (card_type) { | 1178 | switch (card_type) { |
diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c index acc352f4a441..fc9136c3e0d7 100644 --- a/sound/pci/vx222/vx222.c +++ b/sound/pci/vx222/vx222.c | |||
@@ -204,9 +204,9 @@ static int __devinit snd_vx222_probe(struct pci_dev *pci, | |||
204 | return -ENOENT; | 204 | return -ENOENT; |
205 | } | 205 | } |
206 | 206 | ||
207 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 207 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); |
208 | if (card == NULL) | 208 | if (err < 0) |
209 | return -ENOMEM; | 209 | return err; |
210 | 210 | ||
211 | switch ((int)pci_id->driver_data) { | 211 | switch ((int)pci_id->driver_data) { |
212 | case VX_PCI_VX222_OLD: | 212 | case VX_PCI_VX222_OLD: |
diff --git a/sound/pci/vx222/vx222_ops.c b/sound/pci/vx222/vx222_ops.c index 7e87f398ff0b..c0efe4491116 100644 --- a/sound/pci/vx222/vx222_ops.c +++ b/sound/pci/vx222/vx222_ops.c | |||
@@ -107,7 +107,9 @@ static unsigned char vx2_inb(struct vx_core *chip, int offset) | |||
107 | static void vx2_outb(struct vx_core *chip, int offset, unsigned char val) | 107 | static void vx2_outb(struct vx_core *chip, int offset, unsigned char val) |
108 | { | 108 | { |
109 | outb(val, vx2_reg_addr(chip, offset)); | 109 | outb(val, vx2_reg_addr(chip, offset)); |
110 | //printk("outb: %x -> %x\n", val, vx2_reg_addr(chip, offset)); | 110 | /* |
111 | printk(KERN_DEBUG "outb: %x -> %x\n", val, vx2_reg_addr(chip, offset)); | ||
112 | */ | ||
111 | } | 113 | } |
112 | 114 | ||
113 | /** | 115 | /** |
@@ -126,7 +128,9 @@ static unsigned int vx2_inl(struct vx_core *chip, int offset) | |||
126 | */ | 128 | */ |
127 | static void vx2_outl(struct vx_core *chip, int offset, unsigned int val) | 129 | static void vx2_outl(struct vx_core *chip, int offset, unsigned int val) |
128 | { | 130 | { |
129 | // printk("outl: %x -> %x\n", val, vx2_reg_addr(chip, offset)); | 131 | /* |
132 | printk(KERN_DEBUG "outl: %x -> %x\n", val, vx2_reg_addr(chip, offset)); | ||
133 | */ | ||
130 | outl(val, vx2_reg_addr(chip, offset)); | 134 | outl(val, vx2_reg_addr(chip, offset)); |
131 | } | 135 | } |
132 | 136 | ||
diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c index 2631a554845e..4af66661f9b0 100644 --- a/sound/pci/ymfpci/ymfpci.c +++ b/sound/pci/ymfpci/ymfpci.c | |||
@@ -187,9 +187,9 @@ static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci, | |||
187 | return -ENOENT; | 187 | return -ENOENT; |
188 | } | 188 | } |
189 | 189 | ||
190 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 190 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); |
191 | if (card == NULL) | 191 | if (err < 0) |
192 | return -ENOMEM; | 192 | return err; |
193 | 193 | ||
194 | switch (pci_id->device) { | 194 | switch (pci_id->device) { |
195 | case 0x0004: str = "YMF724"; model = "DS-1"; break; | 195 | case 0x0004: str = "YMF724"; model = "DS-1"; break; |
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index 90d0d62bd0b4..2f0925236a1b 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c | |||
@@ -318,7 +318,12 @@ static void snd_ymfpci_pcm_interrupt(struct snd_ymfpci *chip, struct snd_ymfpci_ | |||
318 | ypcm->period_pos += delta; | 318 | ypcm->period_pos += delta; |
319 | ypcm->last_pos = pos; | 319 | ypcm->last_pos = pos; |
320 | if (ypcm->period_pos >= ypcm->period_size) { | 320 | if (ypcm->period_pos >= ypcm->period_size) { |
321 | // printk("done - active_bank = 0x%x, start = 0x%x\n", chip->active_bank, voice->bank[chip->active_bank].start); | 321 | /* |
322 | printk(KERN_DEBUG | ||
323 | "done - active_bank = 0x%x, start = 0x%x\n", | ||
324 | chip->active_bank, | ||
325 | voice->bank[chip->active_bank].start); | ||
326 | */ | ||
322 | ypcm->period_pos %= ypcm->period_size; | 327 | ypcm->period_pos %= ypcm->period_size; |
323 | spin_unlock(&chip->reg_lock); | 328 | spin_unlock(&chip->reg_lock); |
324 | snd_pcm_period_elapsed(ypcm->substream); | 329 | snd_pcm_period_elapsed(ypcm->substream); |
@@ -366,7 +371,12 @@ static void snd_ymfpci_pcm_capture_interrupt(struct snd_pcm_substream *substream | |||
366 | ypcm->last_pos = pos; | 371 | ypcm->last_pos = pos; |
367 | if (ypcm->period_pos >= ypcm->period_size) { | 372 | if (ypcm->period_pos >= ypcm->period_size) { |
368 | ypcm->period_pos %= ypcm->period_size; | 373 | ypcm->period_pos %= ypcm->period_size; |
369 | // printk("done - active_bank = 0x%x, start = 0x%x\n", chip->active_bank, voice->bank[chip->active_bank].start); | 374 | /* |
375 | printk(KERN_DEBUG | ||
376 | "done - active_bank = 0x%x, start = 0x%x\n", | ||
377 | chip->active_bank, | ||
378 | voice->bank[chip->active_bank].start); | ||
379 | */ | ||
370 | spin_unlock(&chip->reg_lock); | 380 | spin_unlock(&chip->reg_lock); |
371 | snd_pcm_period_elapsed(substream); | 381 | snd_pcm_period_elapsed(substream); |
372 | spin_lock(&chip->reg_lock); | 382 | spin_lock(&chip->reg_lock); |
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c index 819aaaac432f..7dea74b71cf1 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c | |||
@@ -91,7 +91,7 @@ static int snd_pdacf_dev_free(struct snd_device *device) | |||
91 | */ | 91 | */ |
92 | static int snd_pdacf_probe(struct pcmcia_device *link) | 92 | static int snd_pdacf_probe(struct pcmcia_device *link) |
93 | { | 93 | { |
94 | int i; | 94 | int i, err; |
95 | struct snd_pdacf *pdacf; | 95 | struct snd_pdacf *pdacf; |
96 | struct snd_card *card; | 96 | struct snd_card *card; |
97 | static struct snd_device_ops ops = { | 97 | static struct snd_device_ops ops = { |
@@ -112,20 +112,23 @@ static int snd_pdacf_probe(struct pcmcia_device *link) | |||
112 | return -ENODEV; /* disabled explicitly */ | 112 | return -ENODEV; /* disabled explicitly */ |
113 | 113 | ||
114 | /* ok, create a card instance */ | 114 | /* ok, create a card instance */ |
115 | card = snd_card_new(index[i], id[i], THIS_MODULE, 0); | 115 | err = snd_card_create(index[i], id[i], THIS_MODULE, 0, &card); |
116 | if (card == NULL) { | 116 | if (err < 0) { |
117 | snd_printk(KERN_ERR "pdacf: cannot create a card instance\n"); | 117 | snd_printk(KERN_ERR "pdacf: cannot create a card instance\n"); |
118 | return -ENOMEM; | 118 | return err; |
119 | } | 119 | } |
120 | 120 | ||
121 | pdacf = snd_pdacf_create(card); | 121 | pdacf = snd_pdacf_create(card); |
122 | if (! pdacf) | 122 | if (!pdacf) { |
123 | return -EIO; | 123 | snd_card_free(card); |
124 | return -ENOMEM; | ||
125 | } | ||
124 | 126 | ||
125 | if (snd_device_new(card, SNDRV_DEV_LOWLEVEL, pdacf, &ops) < 0) { | 127 | err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, pdacf, &ops); |
128 | if (err < 0) { | ||
126 | kfree(pdacf); | 129 | kfree(pdacf); |
127 | snd_card_free(card); | 130 | snd_card_free(card); |
128 | return -ENODEV; | 131 | return err; |
129 | } | 132 | } |
130 | 133 | ||
131 | snd_card_set_dev(card, &handle_to_dev(link)); | 134 | snd_card_set_dev(card, &handle_to_dev(link)); |
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c index dfa40b0ed86d..5d2afa0b0ce4 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c | |||
@@ -82,14 +82,21 @@ static void pdacf_ak4117_write(void *private_data, unsigned char reg, unsigned c | |||
82 | #if 0 | 82 | #if 0 |
83 | void pdacf_dump(struct snd_pdacf *chip) | 83 | void pdacf_dump(struct snd_pdacf *chip) |
84 | { | 84 | { |
85 | printk("PDAUDIOCF DUMP (0x%lx):\n", chip->port); | 85 | printk(KERN_DEBUG "PDAUDIOCF DUMP (0x%lx):\n", chip->port); |
86 | printk("WPD : 0x%x\n", inw(chip->port + PDAUDIOCF_REG_WDP)); | 86 | printk(KERN_DEBUG "WPD : 0x%x\n", |
87 | printk("RDP : 0x%x\n", inw(chip->port + PDAUDIOCF_REG_RDP)); | 87 | inw(chip->port + PDAUDIOCF_REG_WDP)); |
88 | printk("TCR : 0x%x\n", inw(chip->port + PDAUDIOCF_REG_TCR)); | 88 | printk(KERN_DEBUG "RDP : 0x%x\n", |
89 | printk("SCR : 0x%x\n", inw(chip->port + PDAUDIOCF_REG_SCR)); | 89 | inw(chip->port + PDAUDIOCF_REG_RDP)); |
90 | printk("ISR : 0x%x\n", inw(chip->port + PDAUDIOCF_REG_ISR)); | 90 | printk(KERN_DEBUG "TCR : 0x%x\n", |
91 | printk("IER : 0x%x\n", inw(chip->port + PDAUDIOCF_REG_IER)); | 91 | inw(chip->port + PDAUDIOCF_REG_TCR)); |
92 | printk("AK_IFR : 0x%x\n", inw(chip->port + PDAUDIOCF_REG_AK_IFR)); | 92 | printk(KERN_DEBUG "SCR : 0x%x\n", |
93 | inw(chip->port + PDAUDIOCF_REG_SCR)); | ||
94 | printk(KERN_DEBUG "ISR : 0x%x\n", | ||
95 | inw(chip->port + PDAUDIOCF_REG_ISR)); | ||
96 | printk(KERN_DEBUG "IER : 0x%x\n", | ||
97 | inw(chip->port + PDAUDIOCF_REG_IER)); | ||
98 | printk(KERN_DEBUG "AK_IFR : 0x%x\n", | ||
99 | inw(chip->port + PDAUDIOCF_REG_AK_IFR)); | ||
93 | } | 100 | } |
94 | #endif | 101 | #endif |
95 | 102 | ||
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c b/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c index ea903c8e90dd..dcd32201bc8c 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c | |||
@@ -269,7 +269,7 @@ void pdacf_tasklet(unsigned long private_data) | |||
269 | 269 | ||
270 | rdp = inw(chip->port + PDAUDIOCF_REG_RDP); | 270 | rdp = inw(chip->port + PDAUDIOCF_REG_RDP); |
271 | wdp = inw(chip->port + PDAUDIOCF_REG_WDP); | 271 | wdp = inw(chip->port + PDAUDIOCF_REG_WDP); |
272 | // printk("TASKLET: rdp = %x, wdp = %x\n", rdp, wdp); | 272 | /* printk(KERN_DEBUG "TASKLET: rdp = %x, wdp = %x\n", rdp, wdp); */ |
273 | size = wdp - rdp; | 273 | size = wdp - rdp; |
274 | if (size < 0) | 274 | if (size < 0) |
275 | size += 0x10000; | 275 | size += 0x10000; |
@@ -321,5 +321,5 @@ void pdacf_tasklet(unsigned long private_data) | |||
321 | spin_lock(&chip->reg_lock); | 321 | spin_lock(&chip->reg_lock); |
322 | } | 322 | } |
323 | spin_unlock(&chip->reg_lock); | 323 | spin_unlock(&chip->reg_lock); |
324 | // printk("TASKLET: end\n"); | 324 | /* printk(KERN_DEBUG "TASKLET: end\n"); */ |
325 | } | 325 | } |
diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c index 706602a40600..7445cc8a47d3 100644 --- a/sound/pcmcia/vx/vxpocket.c +++ b/sound/pcmcia/vx/vxpocket.c | |||
@@ -130,23 +130,26 @@ static struct snd_vx_hardware vxp440_hw = { | |||
130 | /* | 130 | /* |
131 | * create vxpocket instance | 131 | * create vxpocket instance |
132 | */ | 132 | */ |
133 | static struct snd_vxpocket *snd_vxpocket_new(struct snd_card *card, int ibl, | 133 | static int snd_vxpocket_new(struct snd_card *card, int ibl, |
134 | struct pcmcia_device *link) | 134 | struct pcmcia_device *link, |
135 | struct snd_vxpocket **chip_ret) | ||
135 | { | 136 | { |
136 | struct vx_core *chip; | 137 | struct vx_core *chip; |
137 | struct snd_vxpocket *vxp; | 138 | struct snd_vxpocket *vxp; |
138 | static struct snd_device_ops ops = { | 139 | static struct snd_device_ops ops = { |
139 | .dev_free = snd_vxpocket_dev_free, | 140 | .dev_free = snd_vxpocket_dev_free, |
140 | }; | 141 | }; |
142 | int err; | ||
141 | 143 | ||
142 | chip = snd_vx_create(card, &vxpocket_hw, &snd_vxpocket_ops, | 144 | chip = snd_vx_create(card, &vxpocket_hw, &snd_vxpocket_ops, |
143 | sizeof(struct snd_vxpocket) - sizeof(struct vx_core)); | 145 | sizeof(struct snd_vxpocket) - sizeof(struct vx_core)); |
144 | if (! chip) | 146 | if (!chip) |
145 | return NULL; | 147 | return -ENOMEM; |
146 | 148 | ||
147 | if (snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops) < 0) { | 149 | err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); |
150 | if (err < 0) { | ||
148 | kfree(chip); | 151 | kfree(chip); |
149 | return NULL; | 152 | return err; |
150 | } | 153 | } |
151 | chip->ibl.size = ibl; | 154 | chip->ibl.size = ibl; |
152 | 155 | ||
@@ -169,7 +172,8 @@ static struct snd_vxpocket *snd_vxpocket_new(struct snd_card *card, int ibl, | |||
169 | link->conf.ConfigIndex = 1; | 172 | link->conf.ConfigIndex = 1; |
170 | link->conf.Present = PRESENT_OPTION; | 173 | link->conf.Present = PRESENT_OPTION; |
171 | 174 | ||
172 | return vxp; | 175 | *chip_ret = vxp; |
176 | return 0; | ||
173 | } | 177 | } |
174 | 178 | ||
175 | 179 | ||
@@ -292,7 +296,7 @@ static int vxpocket_probe(struct pcmcia_device *p_dev) | |||
292 | { | 296 | { |
293 | struct snd_card *card; | 297 | struct snd_card *card; |
294 | struct snd_vxpocket *vxp; | 298 | struct snd_vxpocket *vxp; |
295 | int i; | 299 | int i, err; |
296 | 300 | ||
297 | /* find an empty slot from the card list */ | 301 | /* find an empty slot from the card list */ |
298 | for (i = 0; i < SNDRV_CARDS; i++) { | 302 | for (i = 0; i < SNDRV_CARDS; i++) { |
@@ -307,16 +311,16 @@ static int vxpocket_probe(struct pcmcia_device *p_dev) | |||
307 | return -ENODEV; /* disabled explicitly */ | 311 | return -ENODEV; /* disabled explicitly */ |
308 | 312 | ||
309 | /* ok, create a card instance */ | 313 | /* ok, create a card instance */ |
310 | card = snd_card_new(index[i], id[i], THIS_MODULE, 0); | 314 | err = snd_card_create(index[i], id[i], THIS_MODULE, 0, &card); |
311 | if (card == NULL) { | 315 | if (err < 0) { |
312 | snd_printk(KERN_ERR "vxpocket: cannot create a card instance\n"); | 316 | snd_printk(KERN_ERR "vxpocket: cannot create a card instance\n"); |
313 | return -ENOMEM; | 317 | return err; |
314 | } | 318 | } |
315 | 319 | ||
316 | vxp = snd_vxpocket_new(card, ibl[i], p_dev); | 320 | err = snd_vxpocket_new(card, ibl[i], p_dev, &vxp); |
317 | if (! vxp) { | 321 | if (err < 0) { |
318 | snd_card_free(card); | 322 | snd_card_free(card); |
319 | return -ENODEV; | 323 | return err; |
320 | } | 324 | } |
321 | card->private_data = vxp; | 325 | card->private_data = vxp; |
322 | 326 | ||
diff --git a/sound/ppc/Kconfig b/sound/ppc/Kconfig index 777de2b17178..bd2338ab2ced 100644 --- a/sound/ppc/Kconfig +++ b/sound/ppc/Kconfig | |||
@@ -13,6 +13,7 @@ config SND_POWERMAC | |||
13 | tristate "PowerMac (AWACS, DACA, Burgundy, Tumbler, Keywest)" | 13 | tristate "PowerMac (AWACS, DACA, Burgundy, Tumbler, Keywest)" |
14 | depends on I2C && INPUT && PPC_PMAC | 14 | depends on I2C && INPUT && PPC_PMAC |
15 | select SND_PCM | 15 | select SND_PCM |
16 | select SND_VMASTER | ||
16 | help | 17 | help |
17 | Say Y here to include support for the integrated sound device. | 18 | Say Y here to include support for the integrated sound device. |
18 | 19 | ||
diff --git a/sound/ppc/awacs.c b/sound/ppc/awacs.c index 7bd33e6552ab..80df9b1f651e 100644 --- a/sound/ppc/awacs.c +++ b/sound/ppc/awacs.c | |||
@@ -608,9 +608,12 @@ static struct snd_kcontrol_new snd_pmac_screamer_mixers_beige[] __initdata = { | |||
608 | AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_LINE, 0), | 608 | AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_LINE, 0), |
609 | }; | 609 | }; |
610 | 610 | ||
611 | static struct snd_kcontrol_new snd_pmac_screamer_mixers_imac[] __initdata = { | 611 | static struct snd_kcontrol_new snd_pmac_screamer_mixers_lo[] __initdata = { |
612 | AWACS_VOLUME("Line out Playback Volume", 2, 6, 1), | 612 | AWACS_VOLUME("Line out Playback Volume", 2, 6, 1), |
613 | AWACS_VOLUME("Master Playback Volume", 5, 6, 1), | 613 | }; |
614 | |||
615 | static struct snd_kcontrol_new snd_pmac_screamer_mixers_imac[] __initdata = { | ||
616 | AWACS_VOLUME("Play-through Playback Volume", 5, 6, 1), | ||
614 | AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0), | 617 | AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0), |
615 | }; | 618 | }; |
616 | 619 | ||
@@ -627,6 +630,10 @@ static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac7500[] __initdata = { | |||
627 | AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0), | 630 | AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0), |
628 | }; | 631 | }; |
629 | 632 | ||
633 | static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac5500[] __initdata = { | ||
634 | AWACS_VOLUME("Headphone Playback Volume", 2, 6, 1), | ||
635 | }; | ||
636 | |||
630 | static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac[] __initdata = { | 637 | static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac[] __initdata = { |
631 | AWACS_VOLUME("Master Playback Volume", 2, 6, 1), | 638 | AWACS_VOLUME("Master Playback Volume", 2, 6, 1), |
632 | AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0), | 639 | AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0), |
@@ -645,12 +652,19 @@ static struct snd_kcontrol_new snd_pmac_screamer_mixers2[] __initdata = { | |||
645 | AWACS_SWITCH("Mic Capture Switch", 0, SHIFT_MUX_LINE, 0), | 652 | AWACS_SWITCH("Mic Capture Switch", 0, SHIFT_MUX_LINE, 0), |
646 | }; | 653 | }; |
647 | 654 | ||
655 | static struct snd_kcontrol_new snd_pmac_awacs_mixers2_pmac5500[] __initdata = { | ||
656 | AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0), | ||
657 | }; | ||
658 | |||
648 | static struct snd_kcontrol_new snd_pmac_awacs_master_sw __initdata = | 659 | static struct snd_kcontrol_new snd_pmac_awacs_master_sw __initdata = |
649 | AWACS_SWITCH("Master Playback Switch", 1, SHIFT_HDMUTE, 1); | 660 | AWACS_SWITCH("Master Playback Switch", 1, SHIFT_HDMUTE, 1); |
650 | 661 | ||
651 | static struct snd_kcontrol_new snd_pmac_awacs_master_sw_imac __initdata = | 662 | static struct snd_kcontrol_new snd_pmac_awacs_master_sw_imac __initdata = |
652 | AWACS_SWITCH("Line out Playback Switch", 1, SHIFT_HDMUTE, 1); | 663 | AWACS_SWITCH("Line out Playback Switch", 1, SHIFT_HDMUTE, 1); |
653 | 664 | ||
665 | static struct snd_kcontrol_new snd_pmac_awacs_master_sw_pmac5500 __initdata = | ||
666 | AWACS_SWITCH("Headphone Playback Switch", 1, SHIFT_HDMUTE, 1); | ||
667 | |||
654 | static struct snd_kcontrol_new snd_pmac_awacs_mic_boost[] __initdata = { | 668 | static struct snd_kcontrol_new snd_pmac_awacs_mic_boost[] __initdata = { |
655 | AWACS_SWITCH("Mic Boost Capture Switch", 0, SHIFT_GAINLINE, 0), | 669 | AWACS_SWITCH("Mic Boost Capture Switch", 0, SHIFT_GAINLINE, 0), |
656 | }; | 670 | }; |
@@ -766,12 +780,16 @@ static void snd_pmac_awacs_resume(struct snd_pmac *chip) | |||
766 | } | 780 | } |
767 | #endif /* CONFIG_PM */ | 781 | #endif /* CONFIG_PM */ |
768 | 782 | ||
769 | #define IS_PM7500 (machine_is_compatible("AAPL,7500")) | 783 | #define IS_PM7500 (machine_is_compatible("AAPL,7500") \ |
784 | || machine_is_compatible("AAPL,8500") \ | ||
785 | || machine_is_compatible("AAPL,9500")) | ||
786 | #define IS_PM5500 (machine_is_compatible("AAPL,e411")) | ||
770 | #define IS_BEIGE (machine_is_compatible("AAPL,Gossamer")) | 787 | #define IS_BEIGE (machine_is_compatible("AAPL,Gossamer")) |
771 | #define IS_IMAC1 (machine_is_compatible("PowerMac2,1")) | 788 | #define IS_IMAC1 (machine_is_compatible("PowerMac2,1")) |
772 | #define IS_IMAC2 (machine_is_compatible("PowerMac2,2") \ | 789 | #define IS_IMAC2 (machine_is_compatible("PowerMac2,2") \ |
773 | || machine_is_compatible("PowerMac4,1")) | 790 | || machine_is_compatible("PowerMac4,1")) |
774 | #define IS_G4AGP (machine_is_compatible("PowerMac3,1")) | 791 | #define IS_G4AGP (machine_is_compatible("PowerMac3,1")) |
792 | #define IS_LOMBARD (machine_is_compatible("PowerBook1,1")) | ||
775 | 793 | ||
776 | static int imac1, imac2; | 794 | static int imac1, imac2; |
777 | 795 | ||
@@ -858,10 +876,14 @@ int __init | |||
858 | snd_pmac_awacs_init(struct snd_pmac *chip) | 876 | snd_pmac_awacs_init(struct snd_pmac *chip) |
859 | { | 877 | { |
860 | int pm7500 = IS_PM7500; | 878 | int pm7500 = IS_PM7500; |
879 | int pm5500 = IS_PM5500; | ||
861 | int beige = IS_BEIGE; | 880 | int beige = IS_BEIGE; |
862 | int g4agp = IS_G4AGP; | 881 | int g4agp = IS_G4AGP; |
882 | int lombard = IS_LOMBARD; | ||
863 | int imac; | 883 | int imac; |
864 | int err, vol; | 884 | int err, vol; |
885 | struct snd_kcontrol *vmaster_sw, *vmaster_vol; | ||
886 | struct snd_kcontrol *master_vol, *speaker_vol; | ||
865 | 887 | ||
866 | imac1 = IS_IMAC1; | 888 | imac1 = IS_IMAC1; |
867 | imac2 = IS_IMAC2; | 889 | imac2 = IS_IMAC2; |
@@ -915,7 +937,7 @@ snd_pmac_awacs_init(struct snd_pmac *chip) | |||
915 | /* set headphone-jack detection bit */ | 937 | /* set headphone-jack detection bit */ |
916 | switch (chip->model) { | 938 | switch (chip->model) { |
917 | case PMAC_AWACS: | 939 | case PMAC_AWACS: |
918 | chip->hp_stat_mask = pm7500 ? MASK_HDPCONN | 940 | chip->hp_stat_mask = pm7500 || pm5500 ? MASK_HDPCONN |
919 | : MASK_LOCONN; | 941 | : MASK_LOCONN; |
920 | break; | 942 | break; |
921 | case PMAC_SCREAMER: | 943 | case PMAC_SCREAMER: |
@@ -954,7 +976,7 @@ snd_pmac_awacs_init(struct snd_pmac *chip) | |||
954 | return err; | 976 | return err; |
955 | if (beige || g4agp) | 977 | if (beige || g4agp) |
956 | ; | 978 | ; |
957 | else if (chip->model == PMAC_SCREAMER) | 979 | else if (chip->model == PMAC_SCREAMER || pm5500) |
958 | err = build_mixers(chip, ARRAY_SIZE(snd_pmac_screamer_mixers2), | 980 | err = build_mixers(chip, ARRAY_SIZE(snd_pmac_screamer_mixers2), |
959 | snd_pmac_screamer_mixers2); | 981 | snd_pmac_screamer_mixers2); |
960 | else if (!pm7500) | 982 | else if (!pm7500) |
@@ -962,19 +984,35 @@ snd_pmac_awacs_init(struct snd_pmac *chip) | |||
962 | snd_pmac_awacs_mixers2); | 984 | snd_pmac_awacs_mixers2); |
963 | if (err < 0) | 985 | if (err < 0) |
964 | return err; | 986 | return err; |
987 | if (pm5500) { | ||
988 | err = build_mixers(chip, | ||
989 | ARRAY_SIZE(snd_pmac_awacs_mixers2_pmac5500), | ||
990 | snd_pmac_awacs_mixers2_pmac5500); | ||
991 | if (err < 0) | ||
992 | return err; | ||
993 | } | ||
965 | if (pm7500) | 994 | if (pm7500) |
966 | err = build_mixers(chip, | 995 | err = build_mixers(chip, |
967 | ARRAY_SIZE(snd_pmac_awacs_mixers_pmac7500), | 996 | ARRAY_SIZE(snd_pmac_awacs_mixers_pmac7500), |
968 | snd_pmac_awacs_mixers_pmac7500); | 997 | snd_pmac_awacs_mixers_pmac7500); |
998 | else if (pm5500) | ||
999 | err = snd_ctl_add(chip->card, | ||
1000 | (master_vol = snd_ctl_new1(snd_pmac_awacs_mixers_pmac5500, | ||
1001 | chip))); | ||
969 | else if (beige) | 1002 | else if (beige) |
970 | err = build_mixers(chip, | 1003 | err = build_mixers(chip, |
971 | ARRAY_SIZE(snd_pmac_screamer_mixers_beige), | 1004 | ARRAY_SIZE(snd_pmac_screamer_mixers_beige), |
972 | snd_pmac_screamer_mixers_beige); | 1005 | snd_pmac_screamer_mixers_beige); |
973 | else if (imac) | 1006 | else if (imac || lombard) { |
1007 | err = snd_ctl_add(chip->card, | ||
1008 | (master_vol = snd_ctl_new1(snd_pmac_screamer_mixers_lo, | ||
1009 | chip))); | ||
1010 | if (err < 0) | ||
1011 | return err; | ||
974 | err = build_mixers(chip, | 1012 | err = build_mixers(chip, |
975 | ARRAY_SIZE(snd_pmac_screamer_mixers_imac), | 1013 | ARRAY_SIZE(snd_pmac_screamer_mixers_imac), |
976 | snd_pmac_screamer_mixers_imac); | 1014 | snd_pmac_screamer_mixers_imac); |
977 | else if (g4agp) | 1015 | } else if (g4agp) |
978 | err = build_mixers(chip, | 1016 | err = build_mixers(chip, |
979 | ARRAY_SIZE(snd_pmac_screamer_mixers_g4agp), | 1017 | ARRAY_SIZE(snd_pmac_screamer_mixers_g4agp), |
980 | snd_pmac_screamer_mixers_g4agp); | 1018 | snd_pmac_screamer_mixers_g4agp); |
@@ -984,8 +1022,10 @@ snd_pmac_awacs_init(struct snd_pmac *chip) | |||
984 | snd_pmac_awacs_mixers_pmac); | 1022 | snd_pmac_awacs_mixers_pmac); |
985 | if (err < 0) | 1023 | if (err < 0) |
986 | return err; | 1024 | return err; |
987 | chip->master_sw_ctl = snd_ctl_new1((pm7500 || imac || g4agp) | 1025 | chip->master_sw_ctl = snd_ctl_new1((pm7500 || imac || g4agp || lombard) |
988 | ? &snd_pmac_awacs_master_sw_imac | 1026 | ? &snd_pmac_awacs_master_sw_imac |
1027 | : pm5500 | ||
1028 | ? &snd_pmac_awacs_master_sw_pmac5500 | ||
989 | : &snd_pmac_awacs_master_sw, chip); | 1029 | : &snd_pmac_awacs_master_sw, chip); |
990 | err = snd_ctl_add(chip->card, chip->master_sw_ctl); | 1030 | err = snd_ctl_add(chip->card, chip->master_sw_ctl); |
991 | if (err < 0) | 1031 | if (err < 0) |
@@ -1017,8 +1057,9 @@ snd_pmac_awacs_init(struct snd_pmac *chip) | |||
1017 | #endif /* PMAC_AMP_AVAIL */ | 1057 | #endif /* PMAC_AMP_AVAIL */ |
1018 | { | 1058 | { |
1019 | /* route A = headphone, route C = speaker */ | 1059 | /* route A = headphone, route C = speaker */ |
1020 | err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_speaker_vol), | 1060 | err = snd_ctl_add(chip->card, |
1021 | snd_pmac_awacs_speaker_vol); | 1061 | (speaker_vol = snd_ctl_new1(snd_pmac_awacs_speaker_vol, |
1062 | chip))); | ||
1022 | if (err < 0) | 1063 | if (err < 0) |
1023 | return err; | 1064 | return err; |
1024 | chip->speaker_sw_ctl = snd_ctl_new1(imac1 | 1065 | chip->speaker_sw_ctl = snd_ctl_new1(imac1 |
@@ -1031,6 +1072,33 @@ snd_pmac_awacs_init(struct snd_pmac *chip) | |||
1031 | return err; | 1072 | return err; |
1032 | } | 1073 | } |
1033 | 1074 | ||
1075 | if (pm5500 || imac || lombard) { | ||
1076 | vmaster_sw = snd_ctl_make_virtual_master( | ||
1077 | "Master Playback Switch", (unsigned int *) NULL); | ||
1078 | err = snd_ctl_add_slave_uncached(vmaster_sw, | ||
1079 | chip->master_sw_ctl); | ||
1080 | if (err < 0) | ||
1081 | return err; | ||
1082 | err = snd_ctl_add_slave_uncached(vmaster_sw, | ||
1083 | chip->speaker_sw_ctl); | ||
1084 | if (err < 0) | ||
1085 | return err; | ||
1086 | err = snd_ctl_add(chip->card, vmaster_sw); | ||
1087 | if (err < 0) | ||
1088 | return err; | ||
1089 | vmaster_vol = snd_ctl_make_virtual_master( | ||
1090 | "Master Playback Volume", (unsigned int *) NULL); | ||
1091 | err = snd_ctl_add_slave(vmaster_vol, master_vol); | ||
1092 | if (err < 0) | ||
1093 | return err; | ||
1094 | err = snd_ctl_add_slave(vmaster_vol, speaker_vol); | ||
1095 | if (err < 0) | ||
1096 | return err; | ||
1097 | err = snd_ctl_add(chip->card, vmaster_vol); | ||
1098 | if (err < 0) | ||
1099 | return err; | ||
1100 | } | ||
1101 | |||
1034 | if (beige || g4agp) | 1102 | if (beige || g4agp) |
1035 | err = build_mixers(chip, | 1103 | err = build_mixers(chip, |
1036 | ARRAY_SIZE(snd_pmac_screamer_mic_boost_beige), | 1104 | ARRAY_SIZE(snd_pmac_screamer_mic_boost_beige), |
diff --git a/sound/ppc/burgundy.c b/sound/ppc/burgundy.c index f860d39af36b..45a76297c38d 100644 --- a/sound/ppc/burgundy.c +++ b/sound/ppc/burgundy.c | |||
@@ -35,7 +35,7 @@ snd_pmac_burgundy_busy_wait(struct snd_pmac *chip) | |||
35 | int timeout = 50; | 35 | int timeout = 50; |
36 | while ((in_le32(&chip->awacs->codec_ctrl) & MASK_NEWECMD) && timeout--) | 36 | while ((in_le32(&chip->awacs->codec_ctrl) & MASK_NEWECMD) && timeout--) |
37 | udelay(1); | 37 | udelay(1); |
38 | if (! timeout) | 38 | if (timeout < 0) |
39 | printk(KERN_DEBUG "burgundy_busy_wait: timeout\n"); | 39 | printk(KERN_DEBUG "burgundy_busy_wait: timeout\n"); |
40 | } | 40 | } |
41 | 41 | ||
diff --git a/sound/ppc/daca.c b/sound/ppc/daca.c index 8a5b29031933..f8d478c2da62 100644 --- a/sound/ppc/daca.c +++ b/sound/ppc/daca.c | |||
@@ -82,7 +82,7 @@ static int daca_set_volume(struct pmac_daca *mix) | |||
82 | data[1] |= mix->deemphasis ? 0x40 : 0; | 82 | data[1] |= mix->deemphasis ? 0x40 : 0; |
83 | if (i2c_smbus_write_block_data(mix->i2c.client, DACA_REG_AVOL, | 83 | if (i2c_smbus_write_block_data(mix->i2c.client, DACA_REG_AVOL, |
84 | 2, data) < 0) { | 84 | 2, data) < 0) { |
85 | snd_printk("failed to set volume \n"); | 85 | snd_printk(KERN_ERR "failed to set volume \n"); |
86 | return -EINVAL; | 86 | return -EINVAL; |
87 | } | 87 | } |
88 | return 0; | 88 | return 0; |
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c index af76ee862d27..9b4e9c316695 100644 --- a/sound/ppc/pmac.c +++ b/sound/ppc/pmac.c | |||
@@ -299,7 +299,7 @@ static int snd_pmac_pcm_trigger(struct snd_pmac *chip, struct pmac_stream *rec, | |||
299 | case SNDRV_PCM_TRIGGER_SUSPEND: | 299 | case SNDRV_PCM_TRIGGER_SUSPEND: |
300 | spin_lock(&chip->reg_lock); | 300 | spin_lock(&chip->reg_lock); |
301 | rec->running = 0; | 301 | rec->running = 0; |
302 | /*printk("stopped!!\n");*/ | 302 | /*printk(KERN_DEBUG "stopped!!\n");*/ |
303 | snd_pmac_dma_stop(rec); | 303 | snd_pmac_dma_stop(rec); |
304 | for (i = 0, cp = rec->cmd.cmds; i < rec->nperiods; i++, cp++) | 304 | for (i = 0, cp = rec->cmd.cmds; i < rec->nperiods; i++, cp++) |
305 | out_le16(&cp->command, DBDMA_STOP); | 305 | out_le16(&cp->command, DBDMA_STOP); |
@@ -334,7 +334,7 @@ static snd_pcm_uframes_t snd_pmac_pcm_pointer(struct snd_pmac *chip, | |||
334 | } | 334 | } |
335 | #endif | 335 | #endif |
336 | count += rec->cur_period * rec->period_size; | 336 | count += rec->cur_period * rec->period_size; |
337 | /*printk("pointer=%d\n", count);*/ | 337 | /*printk(KERN_DEBUG "pointer=%d\n", count);*/ |
338 | return bytes_to_frames(subs->runtime, count); | 338 | return bytes_to_frames(subs->runtime, count); |
339 | } | 339 | } |
340 | 340 | ||
@@ -486,7 +486,7 @@ static void snd_pmac_pcm_update(struct snd_pmac *chip, struct pmac_stream *rec) | |||
486 | if (! (stat & ACTIVE)) | 486 | if (! (stat & ACTIVE)) |
487 | break; | 487 | break; |
488 | 488 | ||
489 | /*printk("update frag %d\n", rec->cur_period);*/ | 489 | /*printk(KERN_DEBUG "update frag %d\n", rec->cur_period);*/ |
490 | st_le16(&cp->xfer_status, 0); | 490 | st_le16(&cp->xfer_status, 0); |
491 | st_le16(&cp->req_count, rec->period_size); | 491 | st_le16(&cp->req_count, rec->period_size); |
492 | /*st_le16(&cp->res_count, 0);*/ | 492 | /*st_le16(&cp->res_count, 0);*/ |
@@ -806,7 +806,7 @@ snd_pmac_ctrl_intr(int irq, void *devid) | |||
806 | struct snd_pmac *chip = devid; | 806 | struct snd_pmac *chip = devid; |
807 | int ctrl = in_le32(&chip->awacs->control); | 807 | int ctrl = in_le32(&chip->awacs->control); |
808 | 808 | ||
809 | /*printk("pmac: control interrupt.. 0x%x\n", ctrl);*/ | 809 | /*printk(KERN_DEBUG "pmac: control interrupt.. 0x%x\n", ctrl);*/ |
810 | if (ctrl & MASK_PORTCHG) { | 810 | if (ctrl & MASK_PORTCHG) { |
811 | /* do something when headphone is plugged/unplugged? */ | 811 | /* do something when headphone is plugged/unplugged? */ |
812 | if (chip->update_automute) | 812 | if (chip->update_automute) |
@@ -1033,7 +1033,8 @@ static int __init snd_pmac_detect(struct snd_pmac *chip) | |||
1033 | } | 1033 | } |
1034 | if (of_device_is_compatible(sound, "tumbler")) { | 1034 | if (of_device_is_compatible(sound, "tumbler")) { |
1035 | chip->model = PMAC_TUMBLER; | 1035 | chip->model = PMAC_TUMBLER; |
1036 | chip->can_capture = machine_is_compatible("PowerMac4,2"); | 1036 | chip->can_capture = machine_is_compatible("PowerMac4,2") |
1037 | || machine_is_compatible("PowerBook4,1"); | ||
1037 | chip->can_duplex = 0; | 1038 | chip->can_duplex = 0; |
1038 | // chip->can_byte_swap = 0; /* FIXME: check this */ | 1039 | // chip->can_byte_swap = 0; /* FIXME: check this */ |
1039 | chip->num_freqs = ARRAY_SIZE(tumbler_freqs); | 1040 | chip->num_freqs = ARRAY_SIZE(tumbler_freqs); |
diff --git a/sound/ppc/powermac.c b/sound/ppc/powermac.c index c936225771ba..5a929069dce9 100644 --- a/sound/ppc/powermac.c +++ b/sound/ppc/powermac.c | |||
@@ -58,9 +58,9 @@ static int __init snd_pmac_probe(struct platform_device *devptr) | |||
58 | char *name_ext; | 58 | char *name_ext; |
59 | int err; | 59 | int err; |
60 | 60 | ||
61 | card = snd_card_new(index, id, THIS_MODULE, 0); | 61 | err = snd_card_create(index, id, THIS_MODULE, 0, &card); |
62 | if (card == NULL) | 62 | if (err < 0) |
63 | return -ENOMEM; | 63 | return err; |
64 | 64 | ||
65 | if ((err = snd_pmac_new(card, &chip)) < 0) | 65 | if ((err = snd_pmac_new(card, &chip)) < 0) |
66 | goto __error; | 66 | goto __error; |
@@ -110,7 +110,7 @@ static int __init snd_pmac_probe(struct platform_device *devptr) | |||
110 | goto __error; | 110 | goto __error; |
111 | break; | 111 | break; |
112 | default: | 112 | default: |
113 | snd_printk("unsupported hardware %d\n", chip->model); | 113 | snd_printk(KERN_ERR "unsupported hardware %d\n", chip->model); |
114 | err = -EINVAL; | 114 | err = -EINVAL; |
115 | goto __error; | 115 | goto __error; |
116 | } | 116 | } |
diff --git a/sound/ppc/snd_ps3.c b/sound/ppc/snd_ps3.c index ff321110ec02..f361c26506aa 100644 --- a/sound/ppc/snd_ps3.c +++ b/sound/ppc/snd_ps3.c | |||
@@ -969,11 +969,9 @@ static int __init snd_ps3_driver_probe(struct ps3_system_bus_device *dev) | |||
969 | } | 969 | } |
970 | 970 | ||
971 | /* create card instance */ | 971 | /* create card instance */ |
972 | the_card.card = snd_card_new(index, id, THIS_MODULE, 0); | 972 | ret = snd_card_create(index, id, THIS_MODULE, 0, &the_card.card); |
973 | if (!the_card.card) { | 973 | if (ret < 0) |
974 | ret = -ENXIO; | ||
975 | goto clean_irq; | 974 | goto clean_irq; |
976 | } | ||
977 | 975 | ||
978 | strcpy(the_card.card->driver, "PS3"); | 976 | strcpy(the_card.card->driver, "PS3"); |
979 | strcpy(the_card.card->shortname, "PS3"); | 977 | strcpy(the_card.card->shortname, "PS3"); |
diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c index 3eb223385416..40222fcc0878 100644 --- a/sound/ppc/tumbler.c +++ b/sound/ppc/tumbler.c | |||
@@ -41,7 +41,7 @@ | |||
41 | #undef DEBUG | 41 | #undef DEBUG |
42 | 42 | ||
43 | #ifdef DEBUG | 43 | #ifdef DEBUG |
44 | #define DBG(fmt...) printk(fmt) | 44 | #define DBG(fmt...) printk(KERN_DEBUG fmt) |
45 | #else | 45 | #else |
46 | #define DBG(fmt...) | 46 | #define DBG(fmt...) |
47 | #endif | 47 | #endif |
@@ -240,7 +240,7 @@ static int tumbler_set_master_volume(struct pmac_tumbler *mix) | |||
240 | 240 | ||
241 | if (i2c_smbus_write_i2c_block_data(mix->i2c.client, TAS_REG_VOL, 6, | 241 | if (i2c_smbus_write_i2c_block_data(mix->i2c.client, TAS_REG_VOL, 6, |
242 | block) < 0) { | 242 | block) < 0) { |
243 | snd_printk("failed to set volume \n"); | 243 | snd_printk(KERN_ERR "failed to set volume \n"); |
244 | return -EINVAL; | 244 | return -EINVAL; |
245 | } | 245 | } |
246 | return 0; | 246 | return 0; |
@@ -350,7 +350,7 @@ static int tumbler_set_drc(struct pmac_tumbler *mix) | |||
350 | 350 | ||
351 | if (i2c_smbus_write_i2c_block_data(mix->i2c.client, TAS_REG_DRC, | 351 | if (i2c_smbus_write_i2c_block_data(mix->i2c.client, TAS_REG_DRC, |
352 | 2, val) < 0) { | 352 | 2, val) < 0) { |
353 | snd_printk("failed to set DRC\n"); | 353 | snd_printk(KERN_ERR "failed to set DRC\n"); |
354 | return -EINVAL; | 354 | return -EINVAL; |
355 | } | 355 | } |
356 | return 0; | 356 | return 0; |
@@ -386,7 +386,7 @@ static int snapper_set_drc(struct pmac_tumbler *mix) | |||
386 | 386 | ||
387 | if (i2c_smbus_write_i2c_block_data(mix->i2c.client, TAS_REG_DRC, | 387 | if (i2c_smbus_write_i2c_block_data(mix->i2c.client, TAS_REG_DRC, |
388 | 6, val) < 0) { | 388 | 6, val) < 0) { |
389 | snd_printk("failed to set DRC\n"); | 389 | snd_printk(KERN_ERR "failed to set DRC\n"); |
390 | return -EINVAL; | 390 | return -EINVAL; |
391 | } | 391 | } |
392 | return 0; | 392 | return 0; |
@@ -506,7 +506,8 @@ static int tumbler_set_mono_volume(struct pmac_tumbler *mix, | |||
506 | block[i] = (vol >> ((info->bytes - i - 1) * 8)) & 0xff; | 506 | block[i] = (vol >> ((info->bytes - i - 1) * 8)) & 0xff; |
507 | if (i2c_smbus_write_i2c_block_data(mix->i2c.client, info->reg, | 507 | if (i2c_smbus_write_i2c_block_data(mix->i2c.client, info->reg, |
508 | info->bytes, block) < 0) { | 508 | info->bytes, block) < 0) { |
509 | snd_printk("failed to set mono volume %d\n", info->index); | 509 | snd_printk(KERN_ERR "failed to set mono volume %d\n", |
510 | info->index); | ||
510 | return -EINVAL; | 511 | return -EINVAL; |
511 | } | 512 | } |
512 | return 0; | 513 | return 0; |
@@ -643,7 +644,7 @@ static int snapper_set_mix_vol1(struct pmac_tumbler *mix, int idx, int ch, int r | |||
643 | } | 644 | } |
644 | if (i2c_smbus_write_i2c_block_data(mix->i2c.client, reg, | 645 | if (i2c_smbus_write_i2c_block_data(mix->i2c.client, reg, |
645 | 9, block) < 0) { | 646 | 9, block) < 0) { |
646 | snd_printk("failed to set mono volume %d\n", reg); | 647 | snd_printk(KERN_ERR "failed to set mono volume %d\n", reg); |
647 | return -EINVAL; | 648 | return -EINVAL; |
648 | } | 649 | } |
649 | return 0; | 650 | return 0; |
diff --git a/sound/sh/Kconfig b/sound/sh/Kconfig index cfc143985802..aed0f90c3919 100644 --- a/sound/sh/Kconfig +++ b/sound/sh/Kconfig | |||
@@ -15,6 +15,7 @@ config SND_AICA | |||
15 | tristate "Dreamcast Yamaha AICA sound" | 15 | tristate "Dreamcast Yamaha AICA sound" |
16 | depends on SH_DREAMCAST | 16 | depends on SH_DREAMCAST |
17 | select SND_PCM | 17 | select SND_PCM |
18 | select G2_DMA | ||
18 | help | 19 | help |
19 | ALSA Sound driver for the SEGA Dreamcast console. | 20 | ALSA Sound driver for the SEGA Dreamcast console. |
20 | 21 | ||
diff --git a/sound/sh/aica.c b/sound/sh/aica.c index 7c920f3e7fe3..f551233c5a08 100644 --- a/sound/sh/aica.c +++ b/sound/sh/aica.c | |||
@@ -609,11 +609,11 @@ static int __devinit snd_aica_probe(struct platform_device *devptr) | |||
609 | dreamcastcard = kmalloc(sizeof(struct snd_card_aica), GFP_KERNEL); | 609 | dreamcastcard = kmalloc(sizeof(struct snd_card_aica), GFP_KERNEL); |
610 | if (unlikely(!dreamcastcard)) | 610 | if (unlikely(!dreamcastcard)) |
611 | return -ENOMEM; | 611 | return -ENOMEM; |
612 | dreamcastcard->card = | 612 | err = snd_card_create(index, SND_AICA_DRIVER, THIS_MODULE, 0, |
613 | snd_card_new(index, SND_AICA_DRIVER, THIS_MODULE, 0); | 613 | &dreamcastcard->card); |
614 | if (unlikely(!dreamcastcard->card)) { | 614 | if (unlikely(err < 0)) { |
615 | kfree(dreamcastcard); | 615 | kfree(dreamcastcard); |
616 | return -ENODEV; | 616 | return err; |
617 | } | 617 | } |
618 | strcpy(dreamcastcard->card->driver, "snd_aica"); | 618 | strcpy(dreamcastcard->card->driver, "snd_aica"); |
619 | strcpy(dreamcastcard->card->shortname, SND_AICA_DRIVER); | 619 | strcpy(dreamcastcard->card->shortname, SND_AICA_DRIVER); |
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index ef025c66cc66..3d2bb6fc6dcc 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig | |||
@@ -6,6 +6,7 @@ menuconfig SND_SOC | |||
6 | tristate "ALSA for SoC audio support" | 6 | tristate "ALSA for SoC audio support" |
7 | select SND_PCM | 7 | select SND_PCM |
8 | select AC97_BUS if SND_SOC_AC97_BUS | 8 | select AC97_BUS if SND_SOC_AC97_BUS |
9 | select SND_JACK if INPUT=y || INPUT=SND | ||
9 | ---help--- | 10 | ---help--- |
10 | 11 | ||
11 | If you want ASoC support, you should say Y here and also to the | 12 | If you want ASoC support, you should say Y here and also to the |
diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 86a9b1f5b0f3..0237879fd412 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile | |||
@@ -1,4 +1,4 @@ | |||
1 | snd-soc-core-objs := soc-core.o soc-dapm.o | 1 | snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o |
2 | 2 | ||
3 | obj-$(CONFIG_SND_SOC) += snd-soc-core.o | 3 | obj-$(CONFIG_SND_SOC) += snd-soc-core.o |
4 | obj-$(CONFIG_SND_SOC) += codecs/ | 4 | obj-$(CONFIG_SND_SOC) += codecs/ |
diff --git a/sound/soc/atmel/atmel-pcm.c b/sound/soc/atmel/atmel-pcm.c index 3dcdc4e3cfa0..9ef6b96373f5 100644 --- a/sound/soc/atmel/atmel-pcm.c +++ b/sound/soc/atmel/atmel-pcm.c | |||
@@ -347,7 +347,7 @@ static int atmel_pcm_mmap(struct snd_pcm_substream *substream, | |||
347 | vma->vm_end - vma->vm_start, vma->vm_page_prot); | 347 | vma->vm_end - vma->vm_start, vma->vm_page_prot); |
348 | } | 348 | } |
349 | 349 | ||
350 | struct snd_pcm_ops atmel_pcm_ops = { | 350 | static struct snd_pcm_ops atmel_pcm_ops = { |
351 | .open = atmel_pcm_open, | 351 | .open = atmel_pcm_open, |
352 | .close = atmel_pcm_close, | 352 | .close = atmel_pcm_close, |
353 | .ioctl = snd_pcm_lib_ioctl, | 353 | .ioctl = snd_pcm_lib_ioctl, |
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index ff0054b76502..e588e63f18d2 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c | |||
@@ -697,6 +697,15 @@ static int atmel_ssc_resume(struct snd_soc_dai *cpu_dai) | |||
697 | #define ATMEL_SSC_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\ | 697 | #define ATMEL_SSC_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\ |
698 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) | 698 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) |
699 | 699 | ||
700 | static struct snd_soc_dai_ops atmel_ssc_dai_ops = { | ||
701 | .startup = atmel_ssc_startup, | ||
702 | .shutdown = atmel_ssc_shutdown, | ||
703 | .prepare = atmel_ssc_prepare, | ||
704 | .hw_params = atmel_ssc_hw_params, | ||
705 | .set_fmt = atmel_ssc_set_dai_fmt, | ||
706 | .set_clkdiv = atmel_ssc_set_dai_clkdiv, | ||
707 | }; | ||
708 | |||
700 | struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = { | 709 | struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = { |
701 | { .name = "atmel-ssc0", | 710 | { .name = "atmel-ssc0", |
702 | .id = 0, | 711 | .id = 0, |
@@ -712,13 +721,7 @@ struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = { | |||
712 | .channels_max = 2, | 721 | .channels_max = 2, |
713 | .rates = ATMEL_SSC_RATES, | 722 | .rates = ATMEL_SSC_RATES, |
714 | .formats = ATMEL_SSC_FORMATS,}, | 723 | .formats = ATMEL_SSC_FORMATS,}, |
715 | .ops = { | 724 | .ops = &atmel_ssc_dai_ops, |
716 | .startup = atmel_ssc_startup, | ||
717 | .shutdown = atmel_ssc_shutdown, | ||
718 | .prepare = atmel_ssc_prepare, | ||
719 | .hw_params = atmel_ssc_hw_params, | ||
720 | .set_fmt = atmel_ssc_set_dai_fmt, | ||
721 | .set_clkdiv = atmel_ssc_set_dai_clkdiv,}, | ||
722 | .private_data = &ssc_info[0], | 725 | .private_data = &ssc_info[0], |
723 | }, | 726 | }, |
724 | #if NUM_SSC_DEVICES == 3 | 727 | #if NUM_SSC_DEVICES == 3 |
@@ -736,13 +739,7 @@ struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = { | |||
736 | .channels_max = 2, | 739 | .channels_max = 2, |
737 | .rates = ATMEL_SSC_RATES, | 740 | .rates = ATMEL_SSC_RATES, |
738 | .formats = ATMEL_SSC_FORMATS,}, | 741 | .formats = ATMEL_SSC_FORMATS,}, |
739 | .ops = { | 742 | .ops = &atmel_ssc_dai_ops, |
740 | .startup = atmel_ssc_startup, | ||
741 | .shutdown = atmel_ssc_shutdown, | ||
742 | .prepare = atmel_ssc_prepare, | ||
743 | .hw_params = atmel_ssc_hw_params, | ||
744 | .set_fmt = atmel_ssc_set_dai_fmt, | ||
745 | .set_clkdiv = atmel_ssc_set_dai_clkdiv,}, | ||
746 | .private_data = &ssc_info[1], | 743 | .private_data = &ssc_info[1], |
747 | }, | 744 | }, |
748 | { .name = "atmel-ssc2", | 745 | { .name = "atmel-ssc2", |
@@ -759,13 +756,7 @@ struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = { | |||
759 | .channels_max = 2, | 756 | .channels_max = 2, |
760 | .rates = ATMEL_SSC_RATES, | 757 | .rates = ATMEL_SSC_RATES, |
761 | .formats = ATMEL_SSC_FORMATS,}, | 758 | .formats = ATMEL_SSC_FORMATS,}, |
762 | .ops = { | 759 | .ops = &atmel_ssc_dai_ops, |
763 | .startup = atmel_ssc_startup, | ||
764 | .shutdown = atmel_ssc_shutdown, | ||
765 | .prepare = atmel_ssc_prepare, | ||
766 | .hw_params = atmel_ssc_hw_params, | ||
767 | .set_fmt = atmel_ssc_set_dai_fmt, | ||
768 | .set_clkdiv = atmel_ssc_set_dai_clkdiv,}, | ||
769 | .private_data = &ssc_info[2], | 760 | .private_data = &ssc_info[2], |
770 | }, | 761 | }, |
771 | #endif | 762 | #endif |
diff --git a/sound/soc/atmel/playpaq_wm8510.c b/sound/soc/atmel/playpaq_wm8510.c index 43dd8cee83c6..70657534e6b1 100644 --- a/sound/soc/atmel/playpaq_wm8510.c +++ b/sound/soc/atmel/playpaq_wm8510.c | |||
@@ -164,38 +164,38 @@ static int playpaq_wm8510_hw_params(struct snd_pcm_substream *substream, | |||
164 | */ | 164 | */ |
165 | switch (params_rate(params)) { | 165 | switch (params_rate(params)) { |
166 | case 48000: | 166 | case 48000: |
167 | pll_out = 12288000; | 167 | pll_out = 24576000; |
168 | mclk_div = WM8510_MCLKDIV_1; | 168 | mclk_div = WM8510_MCLKDIV_2; |
169 | bclk = WM8510_BCLKDIV_8; | 169 | bclk = WM8510_BCLKDIV_8; |
170 | break; | 170 | break; |
171 | 171 | ||
172 | case 44100: | 172 | case 44100: |
173 | pll_out = 11289600; | 173 | pll_out = 22579200; |
174 | mclk_div = WM8510_MCLKDIV_1; | 174 | mclk_div = WM8510_MCLKDIV_2; |
175 | bclk = WM8510_BCLKDIV_8; | 175 | bclk = WM8510_BCLKDIV_8; |
176 | break; | 176 | break; |
177 | 177 | ||
178 | case 22050: | 178 | case 22050: |
179 | pll_out = 11289600; | 179 | pll_out = 22579200; |
180 | mclk_div = WM8510_MCLKDIV_2; | 180 | mclk_div = WM8510_MCLKDIV_4; |
181 | bclk = WM8510_BCLKDIV_8; | 181 | bclk = WM8510_BCLKDIV_8; |
182 | break; | 182 | break; |
183 | 183 | ||
184 | case 16000: | 184 | case 16000: |
185 | pll_out = 12288000; | 185 | pll_out = 24576000; |
186 | mclk_div = WM8510_MCLKDIV_3; | 186 | mclk_div = WM8510_MCLKDIV_6; |
187 | bclk = WM8510_BCLKDIV_8; | 187 | bclk = WM8510_BCLKDIV_8; |
188 | break; | 188 | break; |
189 | 189 | ||
190 | case 11025: | 190 | case 11025: |
191 | pll_out = 11289600; | 191 | pll_out = 22579200; |
192 | mclk_div = WM8510_MCLKDIV_4; | 192 | mclk_div = WM8510_MCLKDIV_8; |
193 | bclk = WM8510_BCLKDIV_8; | 193 | bclk = WM8510_BCLKDIV_8; |
194 | break; | 194 | break; |
195 | 195 | ||
196 | case 8000: | 196 | case 8000: |
197 | pll_out = 12288000; | 197 | pll_out = 24576000; |
198 | mclk_div = WM8510_MCLKDIV_6; | 198 | mclk_div = WM8510_MCLKDIV_12; |
199 | bclk = WM8510_BCLKDIV_8; | 199 | bclk = WM8510_BCLKDIV_8; |
200 | break; | 200 | break; |
201 | 201 | ||
diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c index 6ea04be911d0..173a239a541c 100644 --- a/sound/soc/atmel/sam9g20_wm8731.c +++ b/sound/soc/atmel/sam9g20_wm8731.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/timer.h> | 36 | #include <linux/timer.h> |
37 | #include <linux/interrupt.h> | 37 | #include <linux/interrupt.h> |
38 | #include <linux/platform_device.h> | 38 | #include <linux/platform_device.h> |
39 | #include <linux/i2c.h> | ||
39 | 40 | ||
40 | #include <linux/atmel-ssc.h> | 41 | #include <linux/atmel-ssc.h> |
41 | 42 | ||
@@ -45,6 +46,7 @@ | |||
45 | #include <sound/soc.h> | 46 | #include <sound/soc.h> |
46 | #include <sound/soc-dapm.h> | 47 | #include <sound/soc-dapm.h> |
47 | 48 | ||
49 | #include <asm/mach-types.h> | ||
48 | #include <mach/hardware.h> | 50 | #include <mach/hardware.h> |
49 | #include <mach/gpio.h> | 51 | #include <mach/gpio.h> |
50 | 52 | ||
@@ -52,6 +54,9 @@ | |||
52 | #include "atmel-pcm.h" | 54 | #include "atmel-pcm.h" |
53 | #include "atmel_ssc_dai.h" | 55 | #include "atmel_ssc_dai.h" |
54 | 56 | ||
57 | #define MCLK_RATE 12000000 | ||
58 | |||
59 | static struct clk *mclk; | ||
55 | 60 | ||
56 | static int at91sam9g20ek_startup(struct snd_pcm_substream *substream) | 61 | static int at91sam9g20ek_startup(struct snd_pcm_substream *substream) |
57 | { | 62 | { |
@@ -59,11 +64,12 @@ static int at91sam9g20ek_startup(struct snd_pcm_substream *substream) | |||
59 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 64 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; |
60 | int ret; | 65 | int ret; |
61 | 66 | ||
62 | /* codec system clock is supplied by PCK0, set to 12MHz */ | ||
63 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK, | 67 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK, |
64 | 12000000, SND_SOC_CLOCK_IN); | 68 | MCLK_RATE, SND_SOC_CLOCK_IN); |
65 | if (ret < 0) | 69 | if (ret < 0) { |
70 | clk_disable(mclk); | ||
66 | return ret; | 71 | return ret; |
72 | } | ||
67 | 73 | ||
68 | return 0; | 74 | return 0; |
69 | } | 75 | } |
@@ -189,6 +195,31 @@ static struct snd_soc_ops at91sam9g20ek_ops = { | |||
189 | .shutdown = at91sam9g20ek_shutdown, | 195 | .shutdown = at91sam9g20ek_shutdown, |
190 | }; | 196 | }; |
191 | 197 | ||
198 | static int at91sam9g20ek_set_bias_level(struct snd_soc_card *card, | ||
199 | enum snd_soc_bias_level level) | ||
200 | { | ||
201 | static int mclk_on; | ||
202 | int ret = 0; | ||
203 | |||
204 | switch (level) { | ||
205 | case SND_SOC_BIAS_ON: | ||
206 | case SND_SOC_BIAS_PREPARE: | ||
207 | if (!mclk_on) | ||
208 | ret = clk_enable(mclk); | ||
209 | if (ret == 0) | ||
210 | mclk_on = 1; | ||
211 | break; | ||
212 | |||
213 | case SND_SOC_BIAS_OFF: | ||
214 | case SND_SOC_BIAS_STANDBY: | ||
215 | if (mclk_on) | ||
216 | clk_disable(mclk); | ||
217 | mclk_on = 0; | ||
218 | break; | ||
219 | } | ||
220 | |||
221 | return ret; | ||
222 | } | ||
192 | 223 | ||
193 | static const struct snd_soc_dapm_widget at91sam9g20ek_dapm_widgets[] = { | 224 | static const struct snd_soc_dapm_widget at91sam9g20ek_dapm_widgets[] = { |
194 | SND_SOC_DAPM_MIC("Int Mic", NULL), | 225 | SND_SOC_DAPM_MIC("Int Mic", NULL), |
@@ -243,21 +274,48 @@ static struct snd_soc_dai_link at91sam9g20ek_dai = { | |||
243 | }; | 274 | }; |
244 | 275 | ||
245 | static struct snd_soc_card snd_soc_at91sam9g20ek = { | 276 | static struct snd_soc_card snd_soc_at91sam9g20ek = { |
246 | .name = "WM8731", | 277 | .name = "AT91SAMG20-EK", |
247 | .platform = &atmel_soc_platform, | 278 | .platform = &atmel_soc_platform, |
248 | .dai_link = &at91sam9g20ek_dai, | 279 | .dai_link = &at91sam9g20ek_dai, |
249 | .num_links = 1, | 280 | .num_links = 1, |
281 | .set_bias_level = at91sam9g20ek_set_bias_level, | ||
250 | }; | 282 | }; |
251 | 283 | ||
252 | static struct wm8731_setup_data at91sam9g20ek_wm8731_setup = { | 284 | /* |
253 | .i2c_bus = 0, | 285 | * FIXME: This is a temporary bodge to avoid cross-tree merge issues. |
254 | .i2c_address = 0x1b, | 286 | * New drivers should register the wm8731 I2C device in the machine |
255 | }; | 287 | * setup code (under arch/arm for ARM systems). |
288 | */ | ||
289 | static int wm8731_i2c_register(void) | ||
290 | { | ||
291 | struct i2c_board_info info; | ||
292 | struct i2c_adapter *adapter; | ||
293 | struct i2c_client *client; | ||
294 | |||
295 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
296 | info.addr = 0x1b; | ||
297 | strlcpy(info.type, "wm8731", I2C_NAME_SIZE); | ||
298 | |||
299 | adapter = i2c_get_adapter(0); | ||
300 | if (!adapter) { | ||
301 | printk(KERN_ERR "can't get i2c adapter 0\n"); | ||
302 | return -ENODEV; | ||
303 | } | ||
304 | |||
305 | client = i2c_new_device(adapter, &info); | ||
306 | i2c_put_adapter(adapter); | ||
307 | if (!client) { | ||
308 | printk(KERN_ERR "can't add i2c device at 0x%x\n", | ||
309 | (unsigned int)info.addr); | ||
310 | return -ENODEV; | ||
311 | } | ||
312 | |||
313 | return 0; | ||
314 | } | ||
256 | 315 | ||
257 | static struct snd_soc_device at91sam9g20ek_snd_devdata = { | 316 | static struct snd_soc_device at91sam9g20ek_snd_devdata = { |
258 | .card = &snd_soc_at91sam9g20ek, | 317 | .card = &snd_soc_at91sam9g20ek, |
259 | .codec_dev = &soc_codec_dev_wm8731, | 318 | .codec_dev = &soc_codec_dev_wm8731, |
260 | .codec_data = &at91sam9g20ek_wm8731_setup, | ||
261 | }; | 319 | }; |
262 | 320 | ||
263 | static struct platform_device *at91sam9g20ek_snd_device; | 321 | static struct platform_device *at91sam9g20ek_snd_device; |
@@ -266,23 +324,56 @@ static int __init at91sam9g20ek_init(void) | |||
266 | { | 324 | { |
267 | struct atmel_ssc_info *ssc_p = at91sam9g20ek_dai.cpu_dai->private_data; | 325 | struct atmel_ssc_info *ssc_p = at91sam9g20ek_dai.cpu_dai->private_data; |
268 | struct ssc_device *ssc = NULL; | 326 | struct ssc_device *ssc = NULL; |
327 | struct clk *pllb; | ||
269 | int ret; | 328 | int ret; |
270 | 329 | ||
330 | if (!machine_is_at91sam9g20ek()) | ||
331 | return -ENODEV; | ||
332 | |||
333 | /* | ||
334 | * Codec MCLK is supplied by PCK0 - set it up. | ||
335 | */ | ||
336 | mclk = clk_get(NULL, "pck0"); | ||
337 | if (IS_ERR(mclk)) { | ||
338 | printk(KERN_ERR "ASoC: Failed to get MCLK\n"); | ||
339 | ret = PTR_ERR(mclk); | ||
340 | goto err; | ||
341 | } | ||
342 | |||
343 | pllb = clk_get(NULL, "pllb"); | ||
344 | if (IS_ERR(mclk)) { | ||
345 | printk(KERN_ERR "ASoC: Failed to get PLLB\n"); | ||
346 | ret = PTR_ERR(mclk); | ||
347 | goto err_mclk; | ||
348 | } | ||
349 | ret = clk_set_parent(mclk, pllb); | ||
350 | clk_put(pllb); | ||
351 | if (ret != 0) { | ||
352 | printk(KERN_ERR "ASoC: Failed to set MCLK parent\n"); | ||
353 | goto err_mclk; | ||
354 | } | ||
355 | |||
356 | clk_set_rate(mclk, MCLK_RATE); | ||
357 | |||
271 | /* | 358 | /* |
272 | * Request SSC device | 359 | * Request SSC device |
273 | */ | 360 | */ |
274 | ssc = ssc_request(0); | 361 | ssc = ssc_request(0); |
275 | if (IS_ERR(ssc)) { | 362 | if (IS_ERR(ssc)) { |
363 | printk(KERN_ERR "ASoC: Failed to request SSC 0\n"); | ||
276 | ret = PTR_ERR(ssc); | 364 | ret = PTR_ERR(ssc); |
277 | ssc = NULL; | 365 | ssc = NULL; |
278 | goto err_ssc; | 366 | goto err_ssc; |
279 | } | 367 | } |
280 | ssc_p->ssc = ssc; | 368 | ssc_p->ssc = ssc; |
281 | 369 | ||
370 | ret = wm8731_i2c_register(); | ||
371 | if (ret != 0) | ||
372 | goto err_ssc; | ||
373 | |||
282 | at91sam9g20ek_snd_device = platform_device_alloc("soc-audio", -1); | 374 | at91sam9g20ek_snd_device = platform_device_alloc("soc-audio", -1); |
283 | if (!at91sam9g20ek_snd_device) { | 375 | if (!at91sam9g20ek_snd_device) { |
284 | printk(KERN_DEBUG | 376 | printk(KERN_ERR "ASoC: Platform device allocation failed\n"); |
285 | "platform device allocation failed\n"); | ||
286 | ret = -ENOMEM; | 377 | ret = -ENOMEM; |
287 | } | 378 | } |
288 | 379 | ||
@@ -292,14 +383,19 @@ static int __init at91sam9g20ek_init(void) | |||
292 | 383 | ||
293 | ret = platform_device_add(at91sam9g20ek_snd_device); | 384 | ret = platform_device_add(at91sam9g20ek_snd_device); |
294 | if (ret) { | 385 | if (ret) { |
295 | printk(KERN_DEBUG | 386 | printk(KERN_ERR "ASoC: Platform device allocation failed\n"); |
296 | "platform device allocation failed\n"); | ||
297 | platform_device_put(at91sam9g20ek_snd_device); | 387 | platform_device_put(at91sam9g20ek_snd_device); |
298 | } | 388 | } |
299 | 389 | ||
300 | return ret; | 390 | return ret; |
301 | 391 | ||
302 | err_ssc: | 392 | err_ssc: |
393 | ssc_free(ssc); | ||
394 | ssc_p->ssc = NULL; | ||
395 | err_mclk: | ||
396 | clk_put(mclk); | ||
397 | mclk = NULL; | ||
398 | err: | ||
303 | return ret; | 399 | return ret; |
304 | } | 400 | } |
305 | 401 | ||
@@ -317,6 +413,8 @@ static void __exit at91sam9g20ek_exit(void) | |||
317 | 413 | ||
318 | platform_device_unregister(at91sam9g20ek_snd_device); | 414 | platform_device_unregister(at91sam9g20ek_snd_device); |
319 | at91sam9g20ek_snd_device = NULL; | 415 | at91sam9g20ek_snd_device = NULL; |
416 | clk_put(mclk); | ||
417 | mclk = NULL; | ||
320 | } | 418 | } |
321 | 419 | ||
322 | module_init(at91sam9g20ek_init); | 420 | module_init(at91sam9g20ek_init); |
diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c index bc8d654576c0..30490a259148 100644 --- a/sound/soc/au1x/dbdma2.c +++ b/sound/soc/au1x/dbdma2.c | |||
@@ -305,7 +305,7 @@ static int au1xpsc_pcm_close(struct snd_pcm_substream *substream) | |||
305 | return 0; | 305 | return 0; |
306 | } | 306 | } |
307 | 307 | ||
308 | struct snd_pcm_ops au1xpsc_pcm_ops = { | 308 | static struct snd_pcm_ops au1xpsc_pcm_ops = { |
309 | .open = au1xpsc_pcm_open, | 309 | .open = au1xpsc_pcm_open, |
310 | .close = au1xpsc_pcm_close, | 310 | .close = au1xpsc_pcm_close, |
311 | .ioctl = snd_pcm_lib_ioctl, | 311 | .ioctl = snd_pcm_lib_ioctl, |
diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c index f0e30aec7f23..479d7bdf1865 100644 --- a/sound/soc/au1x/psc-ac97.c +++ b/sound/soc/au1x/psc-ac97.c | |||
@@ -342,6 +342,11 @@ static int au1xpsc_ac97_resume(struct snd_soc_dai *dai) | |||
342 | return 0; | 342 | return 0; |
343 | } | 343 | } |
344 | 344 | ||
345 | static struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = { | ||
346 | .trigger = au1xpsc_ac97_trigger, | ||
347 | .hw_params = au1xpsc_ac97_hw_params, | ||
348 | }; | ||
349 | |||
345 | struct snd_soc_dai au1xpsc_ac97_dai = { | 350 | struct snd_soc_dai au1xpsc_ac97_dai = { |
346 | .name = "au1xpsc_ac97", | 351 | .name = "au1xpsc_ac97", |
347 | .ac97_control = 1, | 352 | .ac97_control = 1, |
@@ -361,10 +366,7 @@ struct snd_soc_dai au1xpsc_ac97_dai = { | |||
361 | .channels_min = 2, | 366 | .channels_min = 2, |
362 | .channels_max = 2, | 367 | .channels_max = 2, |
363 | }, | 368 | }, |
364 | .ops = { | 369 | .ops = &au1xpsc_ac97_dai_ops, |
365 | .trigger = au1xpsc_ac97_trigger, | ||
366 | .hw_params = au1xpsc_ac97_hw_params, | ||
367 | }, | ||
368 | }; | 370 | }; |
369 | EXPORT_SYMBOL_GPL(au1xpsc_ac97_dai); | 371 | EXPORT_SYMBOL_GPL(au1xpsc_ac97_dai); |
370 | 372 | ||
diff --git a/sound/soc/au1x/psc-i2s.c b/sound/soc/au1x/psc-i2s.c index f916de4400ed..bb589327ee32 100644 --- a/sound/soc/au1x/psc-i2s.c +++ b/sound/soc/au1x/psc-i2s.c | |||
@@ -367,6 +367,12 @@ static int au1xpsc_i2s_resume(struct snd_soc_dai *cpu_dai) | |||
367 | return 0; | 367 | return 0; |
368 | } | 368 | } |
369 | 369 | ||
370 | static struct snd_soc_dai_ops au1xpsc_i2s_dai_ops = { | ||
371 | .trigger = au1xpsc_i2s_trigger, | ||
372 | .hw_params = au1xpsc_i2s_hw_params, | ||
373 | .set_fmt = au1xpsc_i2s_set_fmt, | ||
374 | }; | ||
375 | |||
370 | struct snd_soc_dai au1xpsc_i2s_dai = { | 376 | struct snd_soc_dai au1xpsc_i2s_dai = { |
371 | .name = "au1xpsc_i2s", | 377 | .name = "au1xpsc_i2s", |
372 | .probe = au1xpsc_i2s_probe, | 378 | .probe = au1xpsc_i2s_probe, |
@@ -385,11 +391,7 @@ struct snd_soc_dai au1xpsc_i2s_dai = { | |||
385 | .channels_min = 2, | 391 | .channels_min = 2, |
386 | .channels_max = 8, /* 2 without external help */ | 392 | .channels_max = 8, /* 2 without external help */ |
387 | }, | 393 | }, |
388 | .ops = { | 394 | .ops = &au1xpsc_i2s_dai_ops, |
389 | .trigger = au1xpsc_i2s_trigger, | ||
390 | .hw_params = au1xpsc_i2s_hw_params, | ||
391 | .set_fmt = au1xpsc_i2s_set_fmt, | ||
392 | }, | ||
393 | }; | 395 | }; |
394 | EXPORT_SYMBOL(au1xpsc_i2s_dai); | 396 | EXPORT_SYMBOL(au1xpsc_i2s_dai); |
395 | 397 | ||
diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c index 8067cfafa3a7..8cfed1a5dcbe 100644 --- a/sound/soc/blackfin/bf5xx-ac97-pcm.c +++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c | |||
@@ -297,7 +297,7 @@ static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel, | |||
297 | } | 297 | } |
298 | #endif | 298 | #endif |
299 | 299 | ||
300 | struct snd_pcm_ops bf5xx_pcm_ac97_ops = { | 300 | static struct snd_pcm_ops bf5xx_pcm_ac97_ops = { |
301 | .open = bf5xx_pcm_open, | 301 | .open = bf5xx_pcm_open, |
302 | .ioctl = snd_pcm_lib_ioctl, | 302 | .ioctl = snd_pcm_lib_ioctl, |
303 | .hw_params = bf5xx_pcm_hw_params, | 303 | .hw_params = bf5xx_pcm_hw_params, |
diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c index 3be2be60576d..8a935f2d1767 100644 --- a/sound/soc/blackfin/bf5xx-ac97.c +++ b/sound/soc/blackfin/bf5xx-ac97.c | |||
@@ -31,72 +31,46 @@ | |||
31 | #include "bf5xx-sport.h" | 31 | #include "bf5xx-sport.h" |
32 | #include "bf5xx-ac97.h" | 32 | #include "bf5xx-ac97.h" |
33 | 33 | ||
34 | #if defined(CONFIG_BF54x) | ||
35 | #define PIN_REQ_SPORT_0 {P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, \ | ||
36 | P_SPORT0_RFS, P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0} | ||
37 | |||
38 | #define PIN_REQ_SPORT_1 {P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, \ | ||
39 | P_SPORT1_RFS, P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0} | ||
40 | |||
41 | #define PIN_REQ_SPORT_2 {P_SPORT2_TFS, P_SPORT2_DTPRI, P_SPORT2_TSCLK, \ | ||
42 | P_SPORT2_RFS, P_SPORT2_DRPRI, P_SPORT2_RSCLK, 0} | ||
43 | |||
44 | #define PIN_REQ_SPORT_3 {P_SPORT3_TFS, P_SPORT3_DTPRI, P_SPORT3_TSCLK, \ | ||
45 | P_SPORT3_RFS, P_SPORT3_DRPRI, P_SPORT3_RSCLK, 0} | ||
46 | #else | ||
47 | #define PIN_REQ_SPORT_0 {P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS, \ | ||
48 | P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0} | ||
49 | |||
50 | #define PIN_REQ_SPORT_1 {P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS, \ | ||
51 | P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0} | ||
52 | #endif | ||
53 | |||
54 | static int *cmd_count; | 34 | static int *cmd_count; |
55 | static int sport_num = CONFIG_SND_BF5XX_SPORT_NUM; | 35 | static int sport_num = CONFIG_SND_BF5XX_SPORT_NUM; |
56 | 36 | ||
37 | #define SPORT_REQ(x) \ | ||
38 | [x] = {P_SPORT##x##_TFS, P_SPORT##x##_DTPRI, P_SPORT##x##_TSCLK, \ | ||
39 | P_SPORT##x##_RFS, P_SPORT##x##_DRPRI, P_SPORT##x##_RSCLK, 0} | ||
57 | static u16 sport_req[][7] = { | 40 | static u16 sport_req[][7] = { |
58 | PIN_REQ_SPORT_0, | 41 | #ifdef SPORT0_TCR1 |
59 | #ifdef PIN_REQ_SPORT_1 | 42 | SPORT_REQ(0), |
60 | PIN_REQ_SPORT_1, | 43 | #endif |
44 | #ifdef SPORT1_TCR1 | ||
45 | SPORT_REQ(1), | ||
61 | #endif | 46 | #endif |
62 | #ifdef PIN_REQ_SPORT_2 | 47 | #ifdef SPORT2_TCR1 |
63 | PIN_REQ_SPORT_2, | 48 | SPORT_REQ(2), |
64 | #endif | 49 | #endif |
65 | #ifdef PIN_REQ_SPORT_3 | 50 | #ifdef SPORT3_TCR1 |
66 | PIN_REQ_SPORT_3, | 51 | SPORT_REQ(3), |
67 | #endif | 52 | #endif |
68 | }; | 53 | }; |
69 | 54 | ||
55 | #define SPORT_PARAMS(x) \ | ||
56 | [x] = { \ | ||
57 | .dma_rx_chan = CH_SPORT##x##_RX, \ | ||
58 | .dma_tx_chan = CH_SPORT##x##_TX, \ | ||
59 | .err_irq = IRQ_SPORT##x##_ERROR, \ | ||
60 | .regs = (struct sport_register *)SPORT##x##_TCR1, \ | ||
61 | } | ||
70 | static struct sport_param sport_params[4] = { | 62 | static struct sport_param sport_params[4] = { |
71 | { | 63 | #ifdef SPORT0_TCR1 |
72 | .dma_rx_chan = CH_SPORT0_RX, | 64 | SPORT_PARAMS(0), |
73 | .dma_tx_chan = CH_SPORT0_TX, | ||
74 | .err_irq = IRQ_SPORT0_ERROR, | ||
75 | .regs = (struct sport_register *)SPORT0_TCR1, | ||
76 | }, | ||
77 | #ifdef PIN_REQ_SPORT_1 | ||
78 | { | ||
79 | .dma_rx_chan = CH_SPORT1_RX, | ||
80 | .dma_tx_chan = CH_SPORT1_TX, | ||
81 | .err_irq = IRQ_SPORT1_ERROR, | ||
82 | .regs = (struct sport_register *)SPORT1_TCR1, | ||
83 | }, | ||
84 | #endif | 65 | #endif |
85 | #ifdef PIN_REQ_SPORT_2 | 66 | #ifdef SPORT1_TCR1 |
86 | { | 67 | SPORT_PARAMS(1), |
87 | .dma_rx_chan = CH_SPORT2_RX, | ||
88 | .dma_tx_chan = CH_SPORT2_TX, | ||
89 | .err_irq = IRQ_SPORT2_ERROR, | ||
90 | .regs = (struct sport_register *)SPORT2_TCR1, | ||
91 | }, | ||
92 | #endif | 68 | #endif |
93 | #ifdef PIN_REQ_SPORT_3 | 69 | #ifdef SPORT2_TCR1 |
94 | { | 70 | SPORT_PARAMS(2), |
95 | .dma_rx_chan = CH_SPORT3_RX, | 71 | #endif |
96 | .dma_tx_chan = CH_SPORT3_TX, | 72 | #ifdef SPORT3_TCR1 |
97 | .err_irq = IRQ_SPORT3_ERROR, | 73 | SPORT_PARAMS(3), |
98 | .regs = (struct sport_register *)SPORT3_TCR1, | ||
99 | } | ||
100 | #endif | 74 | #endif |
101 | }; | 75 | }; |
102 | 76 | ||
@@ -332,11 +306,11 @@ static int bf5xx_ac97_probe(struct platform_device *pdev, | |||
332 | if (cmd_count == NULL) | 306 | if (cmd_count == NULL) |
333 | return -ENOMEM; | 307 | return -ENOMEM; |
334 | 308 | ||
335 | if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) { | 309 | if (peripheral_request_list(sport_req[sport_num], "soc-audio")) { |
336 | pr_err("Requesting Peripherals failed\n"); | 310 | pr_err("Requesting Peripherals failed\n"); |
337 | ret = -EFAULT; | 311 | ret = -EFAULT; |
338 | goto peripheral_err; | 312 | goto peripheral_err; |
339 | } | 313 | } |
340 | 314 | ||
341 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET | 315 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET |
342 | /* Request PB3 as reset pin */ | 316 | /* Request PB3 as reset pin */ |
@@ -383,9 +357,9 @@ sport_config_err: | |||
383 | sport_err: | 357 | sport_err: |
384 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET | 358 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET |
385 | gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); | 359 | gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); |
386 | #endif | ||
387 | gpio_err: | 360 | gpio_err: |
388 | peripheral_free_list(&sport_req[sport_num][0]); | 361 | #endif |
362 | peripheral_free_list(sport_req[sport_num]); | ||
389 | peripheral_err: | 363 | peripheral_err: |
390 | free_page((unsigned long)cmd_count); | 364 | free_page((unsigned long)cmd_count); |
391 | cmd_count = NULL; | 365 | cmd_count = NULL; |
@@ -398,7 +372,7 @@ static void bf5xx_ac97_remove(struct platform_device *pdev, | |||
398 | { | 372 | { |
399 | free_page((unsigned long)cmd_count); | 373 | free_page((unsigned long)cmd_count); |
400 | cmd_count = NULL; | 374 | cmd_count = NULL; |
401 | peripheral_free_list(&sport_req[sport_num][0]); | 375 | peripheral_free_list(sport_req[sport_num]); |
402 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET | 376 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET |
403 | gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); | 377 | gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); |
404 | #endif | 378 | #endif |
diff --git a/sound/soc/blackfin/bf5xx-ad73311.c b/sound/soc/blackfin/bf5xx-ad73311.c index 7f2a5e199075..edfbdc024e66 100644 --- a/sound/soc/blackfin/bf5xx-ad73311.c +++ b/sound/soc/blackfin/bf5xx-ad73311.c | |||
@@ -114,7 +114,7 @@ static int snd_ad73311_configure(void) | |||
114 | SSYNC(); | 114 | SSYNC(); |
115 | 115 | ||
116 | /* When TUVF is set, the data is already send out */ | 116 | /* When TUVF is set, the data is already send out */ |
117 | while (!(status & TUVF) && count++ < 10000) { | 117 | while (!(status & TUVF) && ++count < 10000) { |
118 | udelay(1); | 118 | udelay(1); |
119 | status = bfin_read_SPORT_STAT(); | 119 | status = bfin_read_SPORT_STAT(); |
120 | SSYNC(); | 120 | SSYNC(); |
@@ -123,7 +123,7 @@ static int snd_ad73311_configure(void) | |||
123 | SSYNC(); | 123 | SSYNC(); |
124 | local_irq_enable(); | 124 | local_irq_enable(); |
125 | 125 | ||
126 | if (count == 10000) { | 126 | if (count >= 10000) { |
127 | printk(KERN_ERR "ad73311: failed to configure codec\n"); | 127 | printk(KERN_ERR "ad73311: failed to configure codec\n"); |
128 | return -1; | 128 | return -1; |
129 | } | 129 | } |
diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c index 53d290b3ea47..1318c4f627b7 100644 --- a/sound/soc/blackfin/bf5xx-i2s-pcm.c +++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c | |||
@@ -184,7 +184,7 @@ static int bf5xx_pcm_mmap(struct snd_pcm_substream *substream, | |||
184 | return 0 ; | 184 | return 0 ; |
185 | } | 185 | } |
186 | 186 | ||
187 | struct snd_pcm_ops bf5xx_pcm_i2s_ops = { | 187 | static struct snd_pcm_ops bf5xx_pcm_i2s_ops = { |
188 | .open = bf5xx_pcm_open, | 188 | .open = bf5xx_pcm_open, |
189 | .ioctl = snd_pcm_lib_ioctl, | 189 | .ioctl = snd_pcm_lib_ioctl, |
190 | .hw_params = bf5xx_pcm_hw_params, | 190 | .hw_params = bf5xx_pcm_hw_params, |
diff --git a/sound/soc/blackfin/bf5xx-i2s.c b/sound/soc/blackfin/bf5xx-i2s.c index d1d95d2393fe..964824419678 100644 --- a/sound/soc/blackfin/bf5xx-i2s.c +++ b/sound/soc/blackfin/bf5xx-i2s.c | |||
@@ -287,6 +287,13 @@ static int bf5xx_i2s_resume(struct platform_device *pdev, | |||
287 | #define BF5XX_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |\ | 287 | #define BF5XX_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |\ |
288 | SNDRV_PCM_FMTBIT_S32_LE) | 288 | SNDRV_PCM_FMTBIT_S32_LE) |
289 | 289 | ||
290 | static struct snd_soc_dai_ops bf5xx_i2s_dai_ops = { | ||
291 | .startup = bf5xx_i2s_startup, | ||
292 | .shutdown = bf5xx_i2s_shutdown, | ||
293 | .hw_params = bf5xx_i2s_hw_params, | ||
294 | .set_fmt = bf5xx_i2s_set_dai_fmt, | ||
295 | }; | ||
296 | |||
290 | struct snd_soc_dai bf5xx_i2s_dai = { | 297 | struct snd_soc_dai bf5xx_i2s_dai = { |
291 | .name = "bf5xx-i2s", | 298 | .name = "bf5xx-i2s", |
292 | .id = 0, | 299 | .id = 0, |
@@ -304,12 +311,7 @@ struct snd_soc_dai bf5xx_i2s_dai = { | |||
304 | .channels_max = 2, | 311 | .channels_max = 2, |
305 | .rates = BF5XX_I2S_RATES, | 312 | .rates = BF5XX_I2S_RATES, |
306 | .formats = BF5XX_I2S_FORMATS,}, | 313 | .formats = BF5XX_I2S_FORMATS,}, |
307 | .ops = { | 314 | .ops = &bf5xx_i2s_dai_ops, |
308 | .startup = bf5xx_i2s_startup, | ||
309 | .shutdown = bf5xx_i2s_shutdown, | ||
310 | .hw_params = bf5xx_i2s_hw_params, | ||
311 | .set_fmt = bf5xx_i2s_set_dai_fmt, | ||
312 | }, | ||
313 | }; | 315 | }; |
314 | EXPORT_SYMBOL_GPL(bf5xx_i2s_dai); | 316 | EXPORT_SYMBOL_GPL(bf5xx_i2s_dai); |
315 | 317 | ||
diff --git a/sound/soc/blackfin/bf5xx-sport.c b/sound/soc/blackfin/bf5xx-sport.c index 3b99e484d555..b7953c8cf838 100644 --- a/sound/soc/blackfin/bf5xx-sport.c +++ b/sound/soc/blackfin/bf5xx-sport.c | |||
@@ -133,7 +133,7 @@ static void setup_desc(struct dmasg *desc, void *buf, int fragcount, | |||
133 | int i; | 133 | int i; |
134 | 134 | ||
135 | for (i = 0; i < fragcount; ++i) { | 135 | for (i = 0; i < fragcount; ++i) { |
136 | desc[i].next_desc_addr = (unsigned long)&(desc[i + 1]); | 136 | desc[i].next_desc_addr = &(desc[i + 1]); |
137 | desc[i].start_addr = (unsigned long)buf + i*fragsize; | 137 | desc[i].start_addr = (unsigned long)buf + i*fragsize; |
138 | desc[i].cfg = cfg; | 138 | desc[i].cfg = cfg; |
139 | desc[i].x_count = x_count; | 139 | desc[i].x_count = x_count; |
@@ -143,12 +143,12 @@ static void setup_desc(struct dmasg *desc, void *buf, int fragcount, | |||
143 | } | 143 | } |
144 | 144 | ||
145 | /* make circular */ | 145 | /* make circular */ |
146 | desc[fragcount-1].next_desc_addr = (unsigned long)desc; | 146 | desc[fragcount-1].next_desc_addr = desc; |
147 | 147 | ||
148 | pr_debug("setup desc: desc0=%p, next0=%lx, desc1=%p," | 148 | pr_debug("setup desc: desc0=%p, next0=%p, desc1=%p," |
149 | "next1=%lx\nx_count=%x,y_count=%x,addr=0x%lx,cfs=0x%x\n", | 149 | "next1=%p\nx_count=%x,y_count=%x,addr=0x%lx,cfs=0x%x\n", |
150 | &(desc[0]), desc[0].next_desc_addr, | 150 | desc, desc[0].next_desc_addr, |
151 | &(desc[1]), desc[1].next_desc_addr, | 151 | desc+1, desc[1].next_desc_addr, |
152 | desc[0].x_count, desc[0].y_count, | 152 | desc[0].x_count, desc[0].y_count, |
153 | desc[0].start_addr, desc[0].cfg); | 153 | desc[0].start_addr, desc[0].cfg); |
154 | } | 154 | } |
@@ -184,22 +184,20 @@ static inline int sport_hook_rx_dummy(struct sport_device *sport) | |||
184 | BUG_ON(sport->curr_rx_desc == sport->dummy_rx_desc); | 184 | BUG_ON(sport->curr_rx_desc == sport->dummy_rx_desc); |
185 | 185 | ||
186 | /* Maybe the dummy buffer descriptor ring is damaged */ | 186 | /* Maybe the dummy buffer descriptor ring is damaged */ |
187 | sport->dummy_rx_desc->next_desc_addr = \ | 187 | sport->dummy_rx_desc->next_desc_addr = sport->dummy_rx_desc + 1; |
188 | (unsigned long)(sport->dummy_rx_desc+1); | ||
189 | 188 | ||
190 | local_irq_save(flags); | 189 | local_irq_save(flags); |
191 | desc = (struct dmasg *)get_dma_next_desc_ptr(sport->dma_rx_chan); | 190 | desc = get_dma_next_desc_ptr(sport->dma_rx_chan); |
192 | /* Copy the descriptor which will be damaged to backup */ | 191 | /* Copy the descriptor which will be damaged to backup */ |
193 | temp_desc = *desc; | 192 | temp_desc = *desc; |
194 | desc->x_count = 0xa; | 193 | desc->x_count = 0xa; |
195 | desc->y_count = 0; | 194 | desc->y_count = 0; |
196 | desc->next_desc_addr = (unsigned long)(sport->dummy_rx_desc); | 195 | desc->next_desc_addr = sport->dummy_rx_desc; |
197 | local_irq_restore(flags); | 196 | local_irq_restore(flags); |
198 | /* Waiting for dummy buffer descriptor is already hooked*/ | 197 | /* Waiting for dummy buffer descriptor is already hooked*/ |
199 | while ((get_dma_curr_desc_ptr(sport->dma_rx_chan) - | 198 | while ((get_dma_curr_desc_ptr(sport->dma_rx_chan) - |
200 | sizeof(struct dmasg)) != | 199 | sizeof(struct dmasg)) != sport->dummy_rx_desc) |
201 | (unsigned long)sport->dummy_rx_desc) | 200 | continue; |
202 | ; | ||
203 | sport->curr_rx_desc = sport->dummy_rx_desc; | 201 | sport->curr_rx_desc = sport->dummy_rx_desc; |
204 | /* Restore the damaged descriptor */ | 202 | /* Restore the damaged descriptor */ |
205 | *desc = temp_desc; | 203 | *desc = temp_desc; |
@@ -210,14 +208,12 @@ static inline int sport_hook_rx_dummy(struct sport_device *sport) | |||
210 | static inline int sport_rx_dma_start(struct sport_device *sport, int dummy) | 208 | static inline int sport_rx_dma_start(struct sport_device *sport, int dummy) |
211 | { | 209 | { |
212 | if (dummy) { | 210 | if (dummy) { |
213 | sport->dummy_rx_desc->next_desc_addr = \ | 211 | sport->dummy_rx_desc->next_desc_addr = sport->dummy_rx_desc; |
214 | (unsigned long) sport->dummy_rx_desc; | ||
215 | sport->curr_rx_desc = sport->dummy_rx_desc; | 212 | sport->curr_rx_desc = sport->dummy_rx_desc; |
216 | } else | 213 | } else |
217 | sport->curr_rx_desc = sport->dma_rx_desc; | 214 | sport->curr_rx_desc = sport->dma_rx_desc; |
218 | 215 | ||
219 | set_dma_next_desc_addr(sport->dma_rx_chan, \ | 216 | set_dma_next_desc_addr(sport->dma_rx_chan, sport->curr_rx_desc); |
220 | (unsigned long)(sport->curr_rx_desc)); | ||
221 | set_dma_x_count(sport->dma_rx_chan, 0); | 217 | set_dma_x_count(sport->dma_rx_chan, 0); |
222 | set_dma_x_modify(sport->dma_rx_chan, 0); | 218 | set_dma_x_modify(sport->dma_rx_chan, 0); |
223 | set_dma_config(sport->dma_rx_chan, (DMAFLOW_LARGE | NDSIZE_9 | \ | 219 | set_dma_config(sport->dma_rx_chan, (DMAFLOW_LARGE | NDSIZE_9 | \ |
@@ -231,14 +227,12 @@ static inline int sport_rx_dma_start(struct sport_device *sport, int dummy) | |||
231 | static inline int sport_tx_dma_start(struct sport_device *sport, int dummy) | 227 | static inline int sport_tx_dma_start(struct sport_device *sport, int dummy) |
232 | { | 228 | { |
233 | if (dummy) { | 229 | if (dummy) { |
234 | sport->dummy_tx_desc->next_desc_addr = \ | 230 | sport->dummy_tx_desc->next_desc_addr = sport->dummy_tx_desc; |
235 | (unsigned long) sport->dummy_tx_desc; | ||
236 | sport->curr_tx_desc = sport->dummy_tx_desc; | 231 | sport->curr_tx_desc = sport->dummy_tx_desc; |
237 | } else | 232 | } else |
238 | sport->curr_tx_desc = sport->dma_tx_desc; | 233 | sport->curr_tx_desc = sport->dma_tx_desc; |
239 | 234 | ||
240 | set_dma_next_desc_addr(sport->dma_tx_chan, \ | 235 | set_dma_next_desc_addr(sport->dma_tx_chan, sport->curr_tx_desc); |
241 | (unsigned long)(sport->curr_tx_desc)); | ||
242 | set_dma_x_count(sport->dma_tx_chan, 0); | 236 | set_dma_x_count(sport->dma_tx_chan, 0); |
243 | set_dma_x_modify(sport->dma_tx_chan, 0); | 237 | set_dma_x_modify(sport->dma_tx_chan, 0); |
244 | set_dma_config(sport->dma_tx_chan, | 238 | set_dma_config(sport->dma_tx_chan, |
@@ -261,11 +255,9 @@ int sport_rx_start(struct sport_device *sport) | |||
261 | BUG_ON(sport->curr_rx_desc != sport->dummy_rx_desc); | 255 | BUG_ON(sport->curr_rx_desc != sport->dummy_rx_desc); |
262 | local_irq_save(flags); | 256 | local_irq_save(flags); |
263 | while ((get_dma_curr_desc_ptr(sport->dma_rx_chan) - | 257 | while ((get_dma_curr_desc_ptr(sport->dma_rx_chan) - |
264 | sizeof(struct dmasg)) != | 258 | sizeof(struct dmasg)) != sport->dummy_rx_desc) |
265 | (unsigned long)sport->dummy_rx_desc) | 259 | continue; |
266 | ; | 260 | sport->dummy_rx_desc->next_desc_addr = sport->dma_rx_desc; |
267 | sport->dummy_rx_desc->next_desc_addr = | ||
268 | (unsigned long)(sport->dma_rx_desc); | ||
269 | local_irq_restore(flags); | 261 | local_irq_restore(flags); |
270 | sport->curr_rx_desc = sport->dma_rx_desc; | 262 | sport->curr_rx_desc = sport->dma_rx_desc; |
271 | } else { | 263 | } else { |
@@ -310,23 +302,21 @@ static inline int sport_hook_tx_dummy(struct sport_device *sport) | |||
310 | BUG_ON(sport->dummy_tx_desc == NULL); | 302 | BUG_ON(sport->dummy_tx_desc == NULL); |
311 | BUG_ON(sport->curr_tx_desc == sport->dummy_tx_desc); | 303 | BUG_ON(sport->curr_tx_desc == sport->dummy_tx_desc); |
312 | 304 | ||
313 | sport->dummy_tx_desc->next_desc_addr = \ | 305 | sport->dummy_tx_desc->next_desc_addr = sport->dummy_tx_desc + 1; |
314 | (unsigned long)(sport->dummy_tx_desc+1); | ||
315 | 306 | ||
316 | /* Shorten the time on last normal descriptor */ | 307 | /* Shorten the time on last normal descriptor */ |
317 | local_irq_save(flags); | 308 | local_irq_save(flags); |
318 | desc = (struct dmasg *)get_dma_next_desc_ptr(sport->dma_tx_chan); | 309 | desc = get_dma_next_desc_ptr(sport->dma_tx_chan); |
319 | /* Store the descriptor which will be damaged */ | 310 | /* Store the descriptor which will be damaged */ |
320 | temp_desc = *desc; | 311 | temp_desc = *desc; |
321 | desc->x_count = 0xa; | 312 | desc->x_count = 0xa; |
322 | desc->y_count = 0; | 313 | desc->y_count = 0; |
323 | desc->next_desc_addr = (unsigned long)(sport->dummy_tx_desc); | 314 | desc->next_desc_addr = sport->dummy_tx_desc; |
324 | local_irq_restore(flags); | 315 | local_irq_restore(flags); |
325 | /* Waiting for dummy buffer descriptor is already hooked*/ | 316 | /* Waiting for dummy buffer descriptor is already hooked*/ |
326 | while ((get_dma_curr_desc_ptr(sport->dma_tx_chan) - \ | 317 | while ((get_dma_curr_desc_ptr(sport->dma_tx_chan) - \ |
327 | sizeof(struct dmasg)) != \ | 318 | sizeof(struct dmasg)) != sport->dummy_tx_desc) |
328 | (unsigned long)sport->dummy_tx_desc) | 319 | continue; |
329 | ; | ||
330 | sport->curr_tx_desc = sport->dummy_tx_desc; | 320 | sport->curr_tx_desc = sport->dummy_tx_desc; |
331 | /* Restore the damaged descriptor */ | 321 | /* Restore the damaged descriptor */ |
332 | *desc = temp_desc; | 322 | *desc = temp_desc; |
@@ -347,11 +337,9 @@ int sport_tx_start(struct sport_device *sport) | |||
347 | /* Hook the normal buffer descriptor */ | 337 | /* Hook the normal buffer descriptor */ |
348 | local_irq_save(flags); | 338 | local_irq_save(flags); |
349 | while ((get_dma_curr_desc_ptr(sport->dma_tx_chan) - | 339 | while ((get_dma_curr_desc_ptr(sport->dma_tx_chan) - |
350 | sizeof(struct dmasg)) != | 340 | sizeof(struct dmasg)) != sport->dummy_tx_desc) |
351 | (unsigned long)sport->dummy_tx_desc) | 341 | continue; |
352 | ; | 342 | sport->dummy_tx_desc->next_desc_addr = sport->dma_tx_desc; |
353 | sport->dummy_tx_desc->next_desc_addr = | ||
354 | (unsigned long)(sport->dma_tx_desc); | ||
355 | local_irq_restore(flags); | 343 | local_irq_restore(flags); |
356 | sport->curr_tx_desc = sport->dma_tx_desc; | 344 | sport->curr_tx_desc = sport->dma_tx_desc; |
357 | } else { | 345 | } else { |
@@ -536,19 +524,17 @@ static int sport_config_rx_dummy(struct sport_device *sport) | |||
536 | unsigned config; | 524 | unsigned config; |
537 | 525 | ||
538 | pr_debug("%s entered\n", __func__); | 526 | pr_debug("%s entered\n", __func__); |
539 | #if L1_DATA_A_LENGTH != 0 | 527 | if (L1_DATA_A_LENGTH) |
540 | desc = (struct dmasg *) l1_data_sram_alloc(2 * sizeof(*desc)); | 528 | desc = l1_data_sram_zalloc(2 * sizeof(*desc)); |
541 | #else | 529 | else { |
542 | { | ||
543 | dma_addr_t addr; | 530 | dma_addr_t addr; |
544 | desc = dma_alloc_coherent(NULL, 2 * sizeof(*desc), &addr, 0); | 531 | desc = dma_alloc_coherent(NULL, 2 * sizeof(*desc), &addr, 0); |
532 | memset(desc, 0, 2 * sizeof(*desc)); | ||
545 | } | 533 | } |
546 | #endif | ||
547 | if (desc == NULL) { | 534 | if (desc == NULL) { |
548 | pr_err("Failed to allocate memory for dummy rx desc\n"); | 535 | pr_err("Failed to allocate memory for dummy rx desc\n"); |
549 | return -ENOMEM; | 536 | return -ENOMEM; |
550 | } | 537 | } |
551 | memset(desc, 0, 2 * sizeof(*desc)); | ||
552 | sport->dummy_rx_desc = desc; | 538 | sport->dummy_rx_desc = desc; |
553 | desc->start_addr = (unsigned long)sport->dummy_buf; | 539 | desc->start_addr = (unsigned long)sport->dummy_buf; |
554 | config = DMAFLOW_LARGE | NDSIZE_9 | compute_wdsize(sport->wdsize) | 540 | config = DMAFLOW_LARGE | NDSIZE_9 | compute_wdsize(sport->wdsize) |
@@ -559,8 +545,8 @@ static int sport_config_rx_dummy(struct sport_device *sport) | |||
559 | desc->y_count = 0; | 545 | desc->y_count = 0; |
560 | desc->y_modify = 0; | 546 | desc->y_modify = 0; |
561 | memcpy(desc+1, desc, sizeof(*desc)); | 547 | memcpy(desc+1, desc, sizeof(*desc)); |
562 | desc->next_desc_addr = (unsigned long)(desc+1); | 548 | desc->next_desc_addr = desc + 1; |
563 | desc[1].next_desc_addr = (unsigned long)desc; | 549 | desc[1].next_desc_addr = desc; |
564 | return 0; | 550 | return 0; |
565 | } | 551 | } |
566 | 552 | ||
@@ -571,19 +557,17 @@ static int sport_config_tx_dummy(struct sport_device *sport) | |||
571 | 557 | ||
572 | pr_debug("%s entered\n", __func__); | 558 | pr_debug("%s entered\n", __func__); |
573 | 559 | ||
574 | #if L1_DATA_A_LENGTH != 0 | 560 | if (L1_DATA_A_LENGTH) |
575 | desc = (struct dmasg *) l1_data_sram_alloc(2 * sizeof(*desc)); | 561 | desc = l1_data_sram_zalloc(2 * sizeof(*desc)); |
576 | #else | 562 | else { |
577 | { | ||
578 | dma_addr_t addr; | 563 | dma_addr_t addr; |
579 | desc = dma_alloc_coherent(NULL, 2 * sizeof(*desc), &addr, 0); | 564 | desc = dma_alloc_coherent(NULL, 2 * sizeof(*desc), &addr, 0); |
565 | memset(desc, 0, 2 * sizeof(*desc)); | ||
580 | } | 566 | } |
581 | #endif | ||
582 | if (!desc) { | 567 | if (!desc) { |
583 | pr_err("Failed to allocate memory for dummy tx desc\n"); | 568 | pr_err("Failed to allocate memory for dummy tx desc\n"); |
584 | return -ENOMEM; | 569 | return -ENOMEM; |
585 | } | 570 | } |
586 | memset(desc, 0, 2 * sizeof(*desc)); | ||
587 | sport->dummy_tx_desc = desc; | 571 | sport->dummy_tx_desc = desc; |
588 | desc->start_addr = (unsigned long)sport->dummy_buf + \ | 572 | desc->start_addr = (unsigned long)sport->dummy_buf + \ |
589 | sport->dummy_count; | 573 | sport->dummy_count; |
@@ -595,8 +579,8 @@ static int sport_config_tx_dummy(struct sport_device *sport) | |||
595 | desc->y_count = 0; | 579 | desc->y_count = 0; |
596 | desc->y_modify = 0; | 580 | desc->y_modify = 0; |
597 | memcpy(desc+1, desc, sizeof(*desc)); | 581 | memcpy(desc+1, desc, sizeof(*desc)); |
598 | desc->next_desc_addr = (unsigned long)(desc+1); | 582 | desc->next_desc_addr = desc + 1; |
599 | desc[1].next_desc_addr = (unsigned long)desc; | 583 | desc[1].next_desc_addr = desc; |
600 | return 0; | 584 | return 0; |
601 | } | 585 | } |
602 | 586 | ||
@@ -872,17 +856,15 @@ struct sport_device *sport_init(struct sport_param *param, unsigned wdsize, | |||
872 | sport->wdsize = wdsize; | 856 | sport->wdsize = wdsize; |
873 | sport->dummy_count = dummy_count; | 857 | sport->dummy_count = dummy_count; |
874 | 858 | ||
875 | #if L1_DATA_A_LENGTH != 0 | 859 | if (L1_DATA_A_LENGTH) |
876 | sport->dummy_buf = l1_data_sram_alloc(dummy_count * 2); | 860 | sport->dummy_buf = l1_data_sram_zalloc(dummy_count * 2); |
877 | #else | 861 | else |
878 | sport->dummy_buf = kmalloc(dummy_count * 2, GFP_KERNEL); | 862 | sport->dummy_buf = kzalloc(dummy_count * 2, GFP_KERNEL); |
879 | #endif | ||
880 | if (sport->dummy_buf == NULL) { | 863 | if (sport->dummy_buf == NULL) { |
881 | pr_err("Failed to allocate dummy buffer\n"); | 864 | pr_err("Failed to allocate dummy buffer\n"); |
882 | goto __error; | 865 | goto __error; |
883 | } | 866 | } |
884 | 867 | ||
885 | memset(sport->dummy_buf, 0, dummy_count * 2); | ||
886 | ret = sport_config_rx_dummy(sport); | 868 | ret = sport_config_rx_dummy(sport); |
887 | if (ret) { | 869 | if (ret) { |
888 | pr_err("Failed to config rx dummy ring\n"); | 870 | pr_err("Failed to config rx dummy ring\n"); |
@@ -939,6 +921,7 @@ void sport_done(struct sport_device *sport) | |||
939 | sport = NULL; | 921 | sport = NULL; |
940 | } | 922 | } |
941 | EXPORT_SYMBOL(sport_done); | 923 | EXPORT_SYMBOL(sport_done); |
924 | |||
942 | /* | 925 | /* |
943 | * It is only used to send several bytes when dma is not enabled | 926 | * It is only used to send several bytes when dma is not enabled |
944 | * sport controller is configured but not enabled. | 927 | * sport controller is configured but not enabled. |
@@ -1029,4 +1012,3 @@ EXPORT_SYMBOL(sport_send_and_recv); | |||
1029 | MODULE_AUTHOR("Roy Huang"); | 1012 | MODULE_AUTHOR("Roy Huang"); |
1030 | MODULE_DESCRIPTION("SPORT driver for ADI Blackfin"); | 1013 | MODULE_DESCRIPTION("SPORT driver for ADI Blackfin"); |
1031 | MODULE_LICENSE("GPL"); | 1014 | MODULE_LICENSE("GPL"); |
1032 | |||
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index d0e0d691ae51..b6c7f7a01cb0 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -10,9 +10,11 @@ config SND_SOC_I2C_AND_SPI | |||
10 | 10 | ||
11 | config SND_SOC_ALL_CODECS | 11 | config SND_SOC_ALL_CODECS |
12 | tristate "Build all ASoC CODEC drivers" | 12 | tristate "Build all ASoC CODEC drivers" |
13 | select SND_SOC_L3 | ||
13 | select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS | 14 | select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS |
14 | select SND_SOC_AD1980 if SND_SOC_AC97_BUS | 15 | select SND_SOC_AD1980 if SND_SOC_AC97_BUS |
15 | select SND_SOC_AD73311 if I2C | 16 | select SND_SOC_AD73311 if I2C |
17 | select SND_SOC_AK4104 if SPI_MASTER | ||
16 | select SND_SOC_AK4535 if I2C | 18 | select SND_SOC_AK4535 if I2C |
17 | select SND_SOC_CS4270 if I2C | 19 | select SND_SOC_CS4270 if I2C |
18 | select SND_SOC_PCM3008 | 20 | select SND_SOC_PCM3008 |
@@ -24,6 +26,7 @@ config SND_SOC_ALL_CODECS | |||
24 | select SND_SOC_UDA134X | 26 | select SND_SOC_UDA134X |
25 | select SND_SOC_UDA1380 if I2C | 27 | select SND_SOC_UDA1380 if I2C |
26 | select SND_SOC_WM8350 if MFD_WM8350 | 28 | select SND_SOC_WM8350 if MFD_WM8350 |
29 | select SND_SOC_WM8400 if MFD_WM8400 | ||
27 | select SND_SOC_WM8510 if SND_SOC_I2C_AND_SPI | 30 | select SND_SOC_WM8510 if SND_SOC_I2C_AND_SPI |
28 | select SND_SOC_WM8580 if I2C | 31 | select SND_SOC_WM8580 if I2C |
29 | select SND_SOC_WM8728 if SND_SOC_I2C_AND_SPI | 32 | select SND_SOC_WM8728 if SND_SOC_I2C_AND_SPI |
@@ -34,6 +37,7 @@ config SND_SOC_ALL_CODECS | |||
34 | select SND_SOC_WM8903 if I2C | 37 | select SND_SOC_WM8903 if I2C |
35 | select SND_SOC_WM8971 if I2C | 38 | select SND_SOC_WM8971 if I2C |
36 | select SND_SOC_WM8990 if I2C | 39 | select SND_SOC_WM8990 if I2C |
40 | select SND_SOC_WM9705 if SND_SOC_AC97_BUS | ||
37 | select SND_SOC_WM9712 if SND_SOC_AC97_BUS | 41 | select SND_SOC_WM9712 if SND_SOC_AC97_BUS |
38 | select SND_SOC_WM9713 if SND_SOC_AC97_BUS | 42 | select SND_SOC_WM9713 if SND_SOC_AC97_BUS |
39 | help | 43 | help |
@@ -58,6 +62,9 @@ config SND_SOC_AD1980 | |||
58 | config SND_SOC_AD73311 | 62 | config SND_SOC_AD73311 |
59 | tristate | 63 | tristate |
60 | 64 | ||
65 | config SND_SOC_AK4104 | ||
66 | tristate | ||
67 | |||
61 | config SND_SOC_AK4535 | 68 | config SND_SOC_AK4535 |
62 | tristate | 69 | tristate |
63 | 70 | ||
@@ -65,12 +72,6 @@ config SND_SOC_AK4535 | |||
65 | config SND_SOC_CS4270 | 72 | config SND_SOC_CS4270 |
66 | tristate | 73 | tristate |
67 | 74 | ||
68 | # Cirrus Logic CS4270 Codec Hardware Mute Support | ||
69 | # Select if you have external muting circuitry attached to your CS4270. | ||
70 | config SND_SOC_CS4270_HWMUTE | ||
71 | bool | ||
72 | depends on SND_SOC_CS4270 | ||
73 | |||
74 | # Cirrus Logic CS4270 Codec VD = 3.3V Errata | 75 | # Cirrus Logic CS4270 Codec VD = 3.3V Errata |
75 | # Select if you are affected by the errata where the part will not function | 76 | # Select if you are affected by the errata where the part will not function |
76 | # if MCLK divide-by-1.5 is selected and VD is set to 3.3V. The driver will | 77 | # if MCLK divide-by-1.5 is selected and VD is set to 3.3V. The driver will |
@@ -90,7 +91,6 @@ config SND_SOC_SSM2602 | |||
90 | 91 | ||
91 | config SND_SOC_TLV320AIC23 | 92 | config SND_SOC_TLV320AIC23 |
92 | tristate | 93 | tristate |
93 | depends on I2C | ||
94 | 94 | ||
95 | config SND_SOC_TLV320AIC26 | 95 | config SND_SOC_TLV320AIC26 |
96 | tristate "TI TLV320AIC26 Codec support" if SND_SOC_OF_SIMPLE | 96 | tristate "TI TLV320AIC26 Codec support" if SND_SOC_OF_SIMPLE |
@@ -98,15 +98,12 @@ config SND_SOC_TLV320AIC26 | |||
98 | 98 | ||
99 | config SND_SOC_TLV320AIC3X | 99 | config SND_SOC_TLV320AIC3X |
100 | tristate | 100 | tristate |
101 | depends on I2C | ||
102 | 101 | ||
103 | config SND_SOC_TWL4030 | 102 | config SND_SOC_TWL4030 |
104 | tristate | 103 | tristate |
105 | depends on TWL4030_CORE | ||
106 | 104 | ||
107 | config SND_SOC_UDA134X | 105 | config SND_SOC_UDA134X |
108 | tristate | 106 | tristate |
109 | select SND_SOC_L3 | ||
110 | 107 | ||
111 | config SND_SOC_UDA1380 | 108 | config SND_SOC_UDA1380 |
112 | tristate | 109 | tristate |
@@ -114,6 +111,9 @@ config SND_SOC_UDA1380 | |||
114 | config SND_SOC_WM8350 | 111 | config SND_SOC_WM8350 |
115 | tristate | 112 | tristate |
116 | 113 | ||
114 | config SND_SOC_WM8400 | ||
115 | tristate | ||
116 | |||
117 | config SND_SOC_WM8510 | 117 | config SND_SOC_WM8510 |
118 | tristate | 118 | tristate |
119 | 119 | ||
@@ -144,6 +144,9 @@ config SND_SOC_WM8971 | |||
144 | config SND_SOC_WM8990 | 144 | config SND_SOC_WM8990 |
145 | tristate | 145 | tristate |
146 | 146 | ||
147 | config SND_SOC_WM9705 | ||
148 | tristate | ||
149 | |||
147 | config SND_SOC_WM9712 | 150 | config SND_SOC_WM9712 |
148 | tristate | 151 | tristate |
149 | 152 | ||
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index c4ddc9aa2bbd..030d2454725f 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
@@ -1,6 +1,7 @@ | |||
1 | snd-soc-ac97-objs := ac97.o | 1 | snd-soc-ac97-objs := ac97.o |
2 | snd-soc-ad1980-objs := ad1980.o | 2 | snd-soc-ad1980-objs := ad1980.o |
3 | snd-soc-ad73311-objs := ad73311.o | 3 | snd-soc-ad73311-objs := ad73311.o |
4 | snd-soc-ak4104-objs := ak4104.o | ||
4 | snd-soc-ak4535-objs := ak4535.o | 5 | snd-soc-ak4535-objs := ak4535.o |
5 | snd-soc-cs4270-objs := cs4270.o | 6 | snd-soc-cs4270-objs := cs4270.o |
6 | snd-soc-l3-objs := l3.o | 7 | snd-soc-l3-objs := l3.o |
@@ -13,6 +14,7 @@ snd-soc-twl4030-objs := twl4030.o | |||
13 | snd-soc-uda134x-objs := uda134x.o | 14 | snd-soc-uda134x-objs := uda134x.o |
14 | snd-soc-uda1380-objs := uda1380.o | 15 | snd-soc-uda1380-objs := uda1380.o |
15 | snd-soc-wm8350-objs := wm8350.o | 16 | snd-soc-wm8350-objs := wm8350.o |
17 | snd-soc-wm8400-objs := wm8400.o | ||
16 | snd-soc-wm8510-objs := wm8510.o | 18 | snd-soc-wm8510-objs := wm8510.o |
17 | snd-soc-wm8580-objs := wm8580.o | 19 | snd-soc-wm8580-objs := wm8580.o |
18 | snd-soc-wm8728-objs := wm8728.o | 20 | snd-soc-wm8728-objs := wm8728.o |
@@ -23,12 +25,14 @@ snd-soc-wm8900-objs := wm8900.o | |||
23 | snd-soc-wm8903-objs := wm8903.o | 25 | snd-soc-wm8903-objs := wm8903.o |
24 | snd-soc-wm8971-objs := wm8971.o | 26 | snd-soc-wm8971-objs := wm8971.o |
25 | snd-soc-wm8990-objs := wm8990.o | 27 | snd-soc-wm8990-objs := wm8990.o |
28 | snd-soc-wm9705-objs := wm9705.o | ||
26 | snd-soc-wm9712-objs := wm9712.o | 29 | snd-soc-wm9712-objs := wm9712.o |
27 | snd-soc-wm9713-objs := wm9713.o | 30 | snd-soc-wm9713-objs := wm9713.o |
28 | 31 | ||
29 | obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o | 32 | obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o |
30 | obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o | 33 | obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o |
31 | obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o | 34 | obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o |
35 | obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o | ||
32 | obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o | 36 | obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o |
33 | obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o | 37 | obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o |
34 | obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o | 38 | obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o |
@@ -41,6 +45,7 @@ obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o | |||
41 | obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o | 45 | obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o |
42 | obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o | 46 | obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o |
43 | obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o | 47 | obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o |
48 | obj-$(CONFIG_SND_SOC_WM8400) += snd-soc-wm8400.o | ||
44 | obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o | 49 | obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o |
45 | obj-$(CONFIG_SND_SOC_WM8580) += snd-soc-wm8580.o | 50 | obj-$(CONFIG_SND_SOC_WM8580) += snd-soc-wm8580.o |
46 | obj-$(CONFIG_SND_SOC_WM8728) += snd-soc-wm8728.o | 51 | obj-$(CONFIG_SND_SOC_WM8728) += snd-soc-wm8728.o |
@@ -51,5 +56,7 @@ obj-$(CONFIG_SND_SOC_WM8900) += snd-soc-wm8900.o | |||
51 | obj-$(CONFIG_SND_SOC_WM8903) += snd-soc-wm8903.o | 56 | obj-$(CONFIG_SND_SOC_WM8903) += snd-soc-wm8903.o |
52 | obj-$(CONFIG_SND_SOC_WM8971) += snd-soc-wm8971.o | 57 | obj-$(CONFIG_SND_SOC_WM8971) += snd-soc-wm8971.o |
53 | obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o | 58 | obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o |
59 | obj-$(CONFIG_SND_SOC_WM8991) += snd-soc-wm8991.o | ||
60 | obj-$(CONFIG_SND_SOC_WM9705) += snd-soc-wm9705.o | ||
54 | obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o | 61 | obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o |
55 | obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o | 62 | obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o |
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c index fb53e6511af2..b0d4af145b87 100644 --- a/sound/soc/codecs/ac97.c +++ b/sound/soc/codecs/ac97.c | |||
@@ -30,7 +30,7 @@ static int ac97_prepare(struct snd_pcm_substream *substream, | |||
30 | struct snd_pcm_runtime *runtime = substream->runtime; | 30 | struct snd_pcm_runtime *runtime = substream->runtime; |
31 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 31 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
32 | struct snd_soc_device *socdev = rtd->socdev; | 32 | struct snd_soc_device *socdev = rtd->socdev; |
33 | struct snd_soc_codec *codec = socdev->codec; | 33 | struct snd_soc_codec *codec = socdev->card->codec; |
34 | 34 | ||
35 | int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? | 35 | int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? |
36 | AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE; | 36 | AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE; |
@@ -41,6 +41,10 @@ static int ac97_prepare(struct snd_pcm_substream *substream, | |||
41 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 |\ | 41 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 |\ |
42 | SNDRV_PCM_RATE_48000) | 42 | SNDRV_PCM_RATE_48000) |
43 | 43 | ||
44 | static struct snd_soc_dai_ops ac97_dai_ops = { | ||
45 | .prepare = ac97_prepare, | ||
46 | }; | ||
47 | |||
44 | struct snd_soc_dai ac97_dai = { | 48 | struct snd_soc_dai ac97_dai = { |
45 | .name = "AC97 HiFi", | 49 | .name = "AC97 HiFi", |
46 | .ac97_control = 1, | 50 | .ac97_control = 1, |
@@ -56,8 +60,7 @@ struct snd_soc_dai ac97_dai = { | |||
56 | .channels_max = 2, | 60 | .channels_max = 2, |
57 | .rates = STD_AC97_RATES, | 61 | .rates = STD_AC97_RATES, |
58 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | 62 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, |
59 | .ops = { | 63 | .ops = &ac97_dai_ops, |
60 | .prepare = ac97_prepare,}, | ||
61 | }; | 64 | }; |
62 | EXPORT_SYMBOL_GPL(ac97_dai); | 65 | EXPORT_SYMBOL_GPL(ac97_dai); |
63 | 66 | ||
@@ -84,10 +87,10 @@ static int ac97_soc_probe(struct platform_device *pdev) | |||
84 | 87 | ||
85 | printk(KERN_INFO "AC97 SoC Audio Codec %s\n", AC97_VERSION); | 88 | printk(KERN_INFO "AC97 SoC Audio Codec %s\n", AC97_VERSION); |
86 | 89 | ||
87 | socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | 90 | socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); |
88 | if (!socdev->codec) | 91 | if (!socdev->card->codec) |
89 | return -ENOMEM; | 92 | return -ENOMEM; |
90 | codec = socdev->codec; | 93 | codec = socdev->card->codec; |
91 | mutex_init(&codec->mutex); | 94 | mutex_init(&codec->mutex); |
92 | 95 | ||
93 | codec->name = "AC97"; | 96 | codec->name = "AC97"; |
@@ -123,23 +126,21 @@ bus_err: | |||
123 | snd_soc_free_pcms(socdev); | 126 | snd_soc_free_pcms(socdev); |
124 | 127 | ||
125 | err: | 128 | err: |
126 | kfree(socdev->codec->reg_cache); | 129 | kfree(socdev->card->codec); |
127 | kfree(socdev->codec); | 130 | socdev->card->codec = NULL; |
128 | socdev->codec = NULL; | ||
129 | return ret; | 131 | return ret; |
130 | } | 132 | } |
131 | 133 | ||
132 | static int ac97_soc_remove(struct platform_device *pdev) | 134 | static int ac97_soc_remove(struct platform_device *pdev) |
133 | { | 135 | { |
134 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 136 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
135 | struct snd_soc_codec *codec = socdev->codec; | 137 | struct snd_soc_codec *codec = socdev->card->codec; |
136 | 138 | ||
137 | if (!codec) | 139 | if (!codec) |
138 | return 0; | 140 | return 0; |
139 | 141 | ||
140 | snd_soc_free_pcms(socdev); | 142 | snd_soc_free_pcms(socdev); |
141 | kfree(socdev->codec->reg_cache); | 143 | kfree(socdev->card->codec); |
142 | kfree(socdev->codec); | ||
143 | 144 | ||
144 | return 0; | 145 | return 0; |
145 | } | 146 | } |
@@ -149,7 +150,7 @@ static int ac97_soc_suspend(struct platform_device *pdev, pm_message_t msg) | |||
149 | { | 150 | { |
150 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 151 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
151 | 152 | ||
152 | snd_ac97_suspend(socdev->codec->ac97); | 153 | snd_ac97_suspend(socdev->card->codec->ac97); |
153 | 154 | ||
154 | return 0; | 155 | return 0; |
155 | } | 156 | } |
@@ -158,7 +159,7 @@ static int ac97_soc_resume(struct platform_device *pdev) | |||
158 | { | 159 | { |
159 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 160 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
160 | 161 | ||
161 | snd_ac97_resume(socdev->codec->ac97); | 162 | snd_ac97_resume(socdev->card->codec->ac97); |
162 | 163 | ||
163 | return 0; | 164 | return 0; |
164 | } | 165 | } |
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index 73fdbb4d4a3d..ddb3b08ac23c 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c | |||
@@ -93,20 +93,6 @@ SOC_ENUM("Capture Source", ad1980_cap_src), | |||
93 | SOC_SINGLE("Mic Boost Switch", AC97_MIC, 6, 1, 0), | 93 | SOC_SINGLE("Mic Boost Switch", AC97_MIC, 6, 1, 0), |
94 | }; | 94 | }; |
95 | 95 | ||
96 | /* add non dapm controls */ | ||
97 | static int ad1980_add_controls(struct snd_soc_codec *codec) | ||
98 | { | ||
99 | int err, i; | ||
100 | |||
101 | for (i = 0; i < ARRAY_SIZE(ad1980_snd_ac97_controls); i++) { | ||
102 | err = snd_ctl_add(codec->card, snd_soc_cnew( | ||
103 | &ad1980_snd_ac97_controls[i], codec, NULL)); | ||
104 | if (err < 0) | ||
105 | return err; | ||
106 | } | ||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | static unsigned int ac97_read(struct snd_soc_codec *codec, | 96 | static unsigned int ac97_read(struct snd_soc_codec *codec, |
111 | unsigned int reg) | 97 | unsigned int reg) |
112 | { | 98 | { |
@@ -123,7 +109,7 @@ static unsigned int ac97_read(struct snd_soc_codec *codec, | |||
123 | default: | 109 | default: |
124 | reg = reg >> 1; | 110 | reg = reg >> 1; |
125 | 111 | ||
126 | if (reg >= (ARRAY_SIZE(ad1980_reg))) | 112 | if (reg >= ARRAY_SIZE(ad1980_reg)) |
127 | return -EINVAL; | 113 | return -EINVAL; |
128 | 114 | ||
129 | return cache[reg]; | 115 | return cache[reg]; |
@@ -137,7 +123,7 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, | |||
137 | 123 | ||
138 | soc_ac97_ops.write(codec->ac97, reg, val); | 124 | soc_ac97_ops.write(codec->ac97, reg, val); |
139 | reg = reg >> 1; | 125 | reg = reg >> 1; |
140 | if (reg < (ARRAY_SIZE(ad1980_reg))) | 126 | if (reg < ARRAY_SIZE(ad1980_reg)) |
141 | cache[reg] = val; | 127 | cache[reg] = val; |
142 | 128 | ||
143 | return 0; | 129 | return 0; |
@@ -200,10 +186,10 @@ static int ad1980_soc_probe(struct platform_device *pdev) | |||
200 | 186 | ||
201 | printk(KERN_INFO "AD1980 SoC Audio Codec\n"); | 187 | printk(KERN_INFO "AD1980 SoC Audio Codec\n"); |
202 | 188 | ||
203 | socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | 189 | socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); |
204 | if (socdev->codec == NULL) | 190 | if (socdev->card->codec == NULL) |
205 | return -ENOMEM; | 191 | return -ENOMEM; |
206 | codec = socdev->codec; | 192 | codec = socdev->card->codec; |
207 | mutex_init(&codec->mutex); | 193 | mutex_init(&codec->mutex); |
208 | 194 | ||
209 | codec->reg_cache = | 195 | codec->reg_cache = |
@@ -269,7 +255,8 @@ static int ad1980_soc_probe(struct platform_device *pdev) | |||
269 | ext_status = ac97_read(codec, AC97_EXTENDED_STATUS); | 255 | ext_status = ac97_read(codec, AC97_EXTENDED_STATUS); |
270 | ac97_write(codec, AC97_EXTENDED_STATUS, ext_status&~0x3800); | 256 | ac97_write(codec, AC97_EXTENDED_STATUS, ext_status&~0x3800); |
271 | 257 | ||
272 | ad1980_add_controls(codec); | 258 | snd_soc_add_controls(codec, ad1980_snd_ac97_controls, |
259 | ARRAY_SIZE(ad1980_snd_ac97_controls)); | ||
273 | ret = snd_soc_init_card(socdev); | 260 | ret = snd_soc_init_card(socdev); |
274 | if (ret < 0) { | 261 | if (ret < 0) { |
275 | printk(KERN_ERR "ad1980: failed to register card\n"); | 262 | printk(KERN_ERR "ad1980: failed to register card\n"); |
@@ -288,15 +275,15 @@ codec_err: | |||
288 | kfree(codec->reg_cache); | 275 | kfree(codec->reg_cache); |
289 | 276 | ||
290 | cache_err: | 277 | cache_err: |
291 | kfree(socdev->codec); | 278 | kfree(socdev->card->codec); |
292 | socdev->codec = NULL; | 279 | socdev->card->codec = NULL; |
293 | return ret; | 280 | return ret; |
294 | } | 281 | } |
295 | 282 | ||
296 | static int ad1980_soc_remove(struct platform_device *pdev) | 283 | static int ad1980_soc_remove(struct platform_device *pdev) |
297 | { | 284 | { |
298 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 285 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
299 | struct snd_soc_codec *codec = socdev->codec; | 286 | struct snd_soc_codec *codec = socdev->card->codec; |
300 | 287 | ||
301 | if (codec == NULL) | 288 | if (codec == NULL) |
302 | return 0; | 289 | return 0; |
diff --git a/sound/soc/codecs/ad73311.c b/sound/soc/codecs/ad73311.c index b09289a1e55a..e61dac5e7b8f 100644 --- a/sound/soc/codecs/ad73311.c +++ b/sound/soc/codecs/ad73311.c | |||
@@ -53,7 +53,7 @@ static int ad73311_soc_probe(struct platform_device *pdev) | |||
53 | codec->owner = THIS_MODULE; | 53 | codec->owner = THIS_MODULE; |
54 | codec->dai = &ad73311_dai; | 54 | codec->dai = &ad73311_dai; |
55 | codec->num_dai = 1; | 55 | codec->num_dai = 1; |
56 | socdev->codec = codec; | 56 | socdev->card->codec = codec; |
57 | INIT_LIST_HEAD(&codec->dapm_widgets); | 57 | INIT_LIST_HEAD(&codec->dapm_widgets); |
58 | INIT_LIST_HEAD(&codec->dapm_paths); | 58 | INIT_LIST_HEAD(&codec->dapm_paths); |
59 | 59 | ||
@@ -75,15 +75,15 @@ static int ad73311_soc_probe(struct platform_device *pdev) | |||
75 | register_err: | 75 | register_err: |
76 | snd_soc_free_pcms(socdev); | 76 | snd_soc_free_pcms(socdev); |
77 | pcm_err: | 77 | pcm_err: |
78 | kfree(socdev->codec); | 78 | kfree(socdev->card->codec); |
79 | socdev->codec = NULL; | 79 | socdev->card->codec = NULL; |
80 | return ret; | 80 | return ret; |
81 | } | 81 | } |
82 | 82 | ||
83 | static int ad73311_soc_remove(struct platform_device *pdev) | 83 | static int ad73311_soc_remove(struct platform_device *pdev) |
84 | { | 84 | { |
85 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 85 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
86 | struct snd_soc_codec *codec = socdev->codec; | 86 | struct snd_soc_codec *codec = socdev->card->codec; |
87 | 87 | ||
88 | if (codec == NULL) | 88 | if (codec == NULL) |
89 | return 0; | 89 | return 0; |
diff --git a/sound/soc/codecs/ad73311.h b/sound/soc/codecs/ad73311.h index 507ce0c30edf..569573d2d4d7 100644 --- a/sound/soc/codecs/ad73311.h +++ b/sound/soc/codecs/ad73311.h | |||
@@ -70,7 +70,7 @@ | |||
70 | #define REGD_IGS(x) (x & 0x7) | 70 | #define REGD_IGS(x) (x & 0x7) |
71 | #define REGD_RMOD (1 << 3) | 71 | #define REGD_RMOD (1 << 3) |
72 | #define REGD_OGS(x) ((x & 0x7) << 4) | 72 | #define REGD_OGS(x) ((x & 0x7) << 4) |
73 | #define REGD_MUTE (x << 7) | 73 | #define REGD_MUTE (1 << 7) |
74 | 74 | ||
75 | /* Control register E */ | 75 | /* Control register E */ |
76 | #define CTRL_REG_E (4 << 8) | 76 | #define CTRL_REG_E (4 << 8) |
diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c new file mode 100644 index 000000000000..4d47bc4f7428 --- /dev/null +++ b/sound/soc/codecs/ak4104.c | |||
@@ -0,0 +1,365 @@ | |||
1 | /* | ||
2 | * AK4104 ALSA SoC (ASoC) driver | ||
3 | * | ||
4 | * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <sound/core.h> | ||
14 | #include <sound/soc.h> | ||
15 | #include <sound/initval.h> | ||
16 | #include <linux/spi/spi.h> | ||
17 | #include <sound/asoundef.h> | ||
18 | |||
19 | #include "ak4104.h" | ||
20 | |||
21 | /* AK4104 registers addresses */ | ||
22 | #define AK4104_REG_CONTROL1 0x00 | ||
23 | #define AK4104_REG_RESERVED 0x01 | ||
24 | #define AK4104_REG_CONTROL2 0x02 | ||
25 | #define AK4104_REG_TX 0x03 | ||
26 | #define AK4104_REG_CHN_STATUS(x) ((x) + 0x04) | ||
27 | #define AK4104_NUM_REGS 10 | ||
28 | |||
29 | #define AK4104_REG_MASK 0x1f | ||
30 | #define AK4104_READ 0xc0 | ||
31 | #define AK4104_WRITE 0xe0 | ||
32 | #define AK4104_RESERVED_VAL 0x5b | ||
33 | |||
34 | /* Bit masks for AK4104 registers */ | ||
35 | #define AK4104_CONTROL1_RSTN (1 << 0) | ||
36 | #define AK4104_CONTROL1_PW (1 << 1) | ||
37 | #define AK4104_CONTROL1_DIF0 (1 << 2) | ||
38 | #define AK4104_CONTROL1_DIF1 (1 << 3) | ||
39 | |||
40 | #define AK4104_CONTROL2_SEL0 (1 << 0) | ||
41 | #define AK4104_CONTROL2_SEL1 (1 << 1) | ||
42 | #define AK4104_CONTROL2_MODE (1 << 2) | ||
43 | |||
44 | #define AK4104_TX_TXE (1 << 0) | ||
45 | #define AK4104_TX_V (1 << 1) | ||
46 | |||
47 | #define DRV_NAME "ak4104" | ||
48 | |||
49 | struct ak4104_private { | ||
50 | struct snd_soc_codec codec; | ||
51 | u8 reg_cache[AK4104_NUM_REGS]; | ||
52 | }; | ||
53 | |||
54 | static int ak4104_fill_cache(struct snd_soc_codec *codec) | ||
55 | { | ||
56 | int i; | ||
57 | u8 *reg_cache = codec->reg_cache; | ||
58 | struct spi_device *spi = codec->control_data; | ||
59 | |||
60 | for (i = 0; i < codec->reg_cache_size; i++) { | ||
61 | int ret = spi_w8r8(spi, i | AK4104_READ); | ||
62 | if (ret < 0) { | ||
63 | dev_err(&spi->dev, "SPI write failure\n"); | ||
64 | return ret; | ||
65 | } | ||
66 | |||
67 | reg_cache[i] = ret; | ||
68 | } | ||
69 | |||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | static unsigned int ak4104_read_reg_cache(struct snd_soc_codec *codec, | ||
74 | unsigned int reg) | ||
75 | { | ||
76 | u8 *reg_cache = codec->reg_cache; | ||
77 | |||
78 | if (reg >= codec->reg_cache_size) | ||
79 | return -EINVAL; | ||
80 | |||
81 | return reg_cache[reg]; | ||
82 | } | ||
83 | |||
84 | static int ak4104_spi_write(struct snd_soc_codec *codec, unsigned int reg, | ||
85 | unsigned int value) | ||
86 | { | ||
87 | u8 *cache = codec->reg_cache; | ||
88 | struct spi_device *spi = codec->control_data; | ||
89 | |||
90 | if (reg >= codec->reg_cache_size) | ||
91 | return -EINVAL; | ||
92 | |||
93 | reg &= AK4104_REG_MASK; | ||
94 | reg |= AK4104_WRITE; | ||
95 | |||
96 | /* only write to the hardware if value has changed */ | ||
97 | if (cache[reg] != value) { | ||
98 | u8 tmp[2] = { reg, value }; | ||
99 | if (spi_write(spi, tmp, sizeof(tmp))) { | ||
100 | dev_err(&spi->dev, "SPI write failed\n"); | ||
101 | return -EIO; | ||
102 | } | ||
103 | |||
104 | cache[reg] = value; | ||
105 | } | ||
106 | |||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | static int ak4104_set_dai_fmt(struct snd_soc_dai *codec_dai, | ||
111 | unsigned int format) | ||
112 | { | ||
113 | struct snd_soc_codec *codec = codec_dai->codec; | ||
114 | int val = 0; | ||
115 | |||
116 | val = ak4104_read_reg_cache(codec, AK4104_REG_CONTROL1); | ||
117 | if (val < 0) | ||
118 | return val; | ||
119 | |||
120 | val &= ~(AK4104_CONTROL1_DIF0 | AK4104_CONTROL1_DIF1); | ||
121 | |||
122 | /* set DAI format */ | ||
123 | switch (format & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
124 | case SND_SOC_DAIFMT_RIGHT_J: | ||
125 | break; | ||
126 | case SND_SOC_DAIFMT_LEFT_J: | ||
127 | val |= AK4104_CONTROL1_DIF0; | ||
128 | break; | ||
129 | case SND_SOC_DAIFMT_I2S: | ||
130 | val |= AK4104_CONTROL1_DIF0 | AK4104_CONTROL1_DIF1; | ||
131 | break; | ||
132 | default: | ||
133 | dev_err(codec->dev, "invalid dai format\n"); | ||
134 | return -EINVAL; | ||
135 | } | ||
136 | |||
137 | /* This device can only be slave */ | ||
138 | if ((format & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) | ||
139 | return -EINVAL; | ||
140 | |||
141 | return ak4104_spi_write(codec, AK4104_REG_CONTROL1, val); | ||
142 | } | ||
143 | |||
144 | static int ak4104_hw_params(struct snd_pcm_substream *substream, | ||
145 | struct snd_pcm_hw_params *params, | ||
146 | struct snd_soc_dai *dai) | ||
147 | { | ||
148 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
149 | struct snd_soc_device *socdev = rtd->socdev; | ||
150 | struct snd_soc_codec *codec = socdev->card->codec; | ||
151 | int val = 0; | ||
152 | |||
153 | /* set the IEC958 bits: consumer mode, no copyright bit */ | ||
154 | val |= IEC958_AES0_CON_NOT_COPYRIGHT; | ||
155 | ak4104_spi_write(codec, AK4104_REG_CHN_STATUS(0), val); | ||
156 | |||
157 | val = 0; | ||
158 | |||
159 | switch (params_rate(params)) { | ||
160 | case 44100: | ||
161 | val |= IEC958_AES3_CON_FS_44100; | ||
162 | break; | ||
163 | case 48000: | ||
164 | val |= IEC958_AES3_CON_FS_48000; | ||
165 | break; | ||
166 | case 32000: | ||
167 | val |= IEC958_AES3_CON_FS_32000; | ||
168 | break; | ||
169 | default: | ||
170 | dev_err(codec->dev, "unsupported sampling rate\n"); | ||
171 | return -EINVAL; | ||
172 | } | ||
173 | |||
174 | return ak4104_spi_write(codec, AK4104_REG_CHN_STATUS(3), val); | ||
175 | } | ||
176 | |||
177 | static struct snd_soc_dai_ops ak4101_dai_ops = { | ||
178 | .hw_params = ak4104_hw_params, | ||
179 | .set_fmt = ak4104_set_dai_fmt, | ||
180 | }; | ||
181 | |||
182 | struct snd_soc_dai ak4104_dai = { | ||
183 | .name = DRV_NAME, | ||
184 | .playback = { | ||
185 | .stream_name = "Playback", | ||
186 | .channels_min = 2, | ||
187 | .channels_max = 2, | ||
188 | .rates = SNDRV_PCM_RATE_44100 | | ||
189 | SNDRV_PCM_RATE_48000 | | ||
190 | SNDRV_PCM_RATE_32000, | ||
191 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | ||
192 | SNDRV_PCM_FMTBIT_S24_3LE | | ||
193 | SNDRV_PCM_FMTBIT_S24_LE | ||
194 | }, | ||
195 | .ops = &ak4101_dai_ops, | ||
196 | }; | ||
197 | |||
198 | static struct snd_soc_codec *ak4104_codec; | ||
199 | |||
200 | static int ak4104_spi_probe(struct spi_device *spi) | ||
201 | { | ||
202 | struct snd_soc_codec *codec; | ||
203 | struct ak4104_private *ak4104; | ||
204 | int ret, val; | ||
205 | |||
206 | spi->bits_per_word = 8; | ||
207 | spi->mode = SPI_MODE_0; | ||
208 | ret = spi_setup(spi); | ||
209 | if (ret < 0) | ||
210 | return ret; | ||
211 | |||
212 | ak4104 = kzalloc(sizeof(struct ak4104_private), GFP_KERNEL); | ||
213 | if (!ak4104) { | ||
214 | dev_err(&spi->dev, "could not allocate codec\n"); | ||
215 | return -ENOMEM; | ||
216 | } | ||
217 | |||
218 | codec = &ak4104->codec; | ||
219 | mutex_init(&codec->mutex); | ||
220 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
221 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
222 | |||
223 | codec->dev = &spi->dev; | ||
224 | codec->name = DRV_NAME; | ||
225 | codec->owner = THIS_MODULE; | ||
226 | codec->dai = &ak4104_dai; | ||
227 | codec->num_dai = 1; | ||
228 | codec->private_data = ak4104; | ||
229 | codec->control_data = spi; | ||
230 | codec->reg_cache = ak4104->reg_cache; | ||
231 | codec->reg_cache_size = AK4104_NUM_REGS; | ||
232 | |||
233 | /* read all regs and fill the cache */ | ||
234 | ret = ak4104_fill_cache(codec); | ||
235 | if (ret < 0) { | ||
236 | dev_err(&spi->dev, "failed to fill register cache\n"); | ||
237 | return ret; | ||
238 | } | ||
239 | |||
240 | /* read the 'reserved' register - according to the datasheet, it | ||
241 | * should contain 0x5b. Not a good way to verify the presence of | ||
242 | * the device, but there is no hardware ID register. */ | ||
243 | if (ak4104_read_reg_cache(codec, AK4104_REG_RESERVED) != | ||
244 | AK4104_RESERVED_VAL) { | ||
245 | ret = -ENODEV; | ||
246 | goto error_free_codec; | ||
247 | } | ||
248 | |||
249 | /* set power-up and non-reset bits */ | ||
250 | val = ak4104_read_reg_cache(codec, AK4104_REG_CONTROL1); | ||
251 | val |= AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN; | ||
252 | ret = ak4104_spi_write(codec, AK4104_REG_CONTROL1, val); | ||
253 | if (ret < 0) | ||
254 | goto error_free_codec; | ||
255 | |||
256 | /* enable transmitter */ | ||
257 | val = ak4104_read_reg_cache(codec, AK4104_REG_TX); | ||
258 | val |= AK4104_TX_TXE; | ||
259 | ret = ak4104_spi_write(codec, AK4104_REG_TX, val); | ||
260 | if (ret < 0) | ||
261 | goto error_free_codec; | ||
262 | |||
263 | ak4104_codec = codec; | ||
264 | ret = snd_soc_register_dai(&ak4104_dai); | ||
265 | if (ret < 0) { | ||
266 | dev_err(&spi->dev, "failed to register DAI\n"); | ||
267 | goto error_free_codec; | ||
268 | } | ||
269 | |||
270 | spi_set_drvdata(spi, ak4104); | ||
271 | dev_info(&spi->dev, "SPI device initialized\n"); | ||
272 | return 0; | ||
273 | |||
274 | error_free_codec: | ||
275 | kfree(ak4104); | ||
276 | ak4104_dai.dev = NULL; | ||
277 | return ret; | ||
278 | } | ||
279 | |||
280 | static int __devexit ak4104_spi_remove(struct spi_device *spi) | ||
281 | { | ||
282 | int ret, val; | ||
283 | struct ak4104_private *ak4104 = spi_get_drvdata(spi); | ||
284 | |||
285 | val = ak4104_read_reg_cache(&ak4104->codec, AK4104_REG_CONTROL1); | ||
286 | if (val < 0) | ||
287 | return val; | ||
288 | |||
289 | /* clear power-up and non-reset bits */ | ||
290 | val &= ~(AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN); | ||
291 | ret = ak4104_spi_write(&ak4104->codec, AK4104_REG_CONTROL1, val); | ||
292 | if (ret < 0) | ||
293 | return ret; | ||
294 | |||
295 | ak4104_codec = NULL; | ||
296 | kfree(ak4104); | ||
297 | return 0; | ||
298 | } | ||
299 | |||
300 | static int ak4104_probe(struct platform_device *pdev) | ||
301 | { | ||
302 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
303 | struct snd_soc_codec *codec = ak4104_codec; | ||
304 | int ret; | ||
305 | |||
306 | /* Connect the codec to the socdev. snd_soc_new_pcms() needs this. */ | ||
307 | socdev->card->codec = codec; | ||
308 | |||
309 | /* Register PCMs */ | ||
310 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
311 | if (ret < 0) { | ||
312 | dev_err(codec->dev, "failed to create pcms\n"); | ||
313 | return ret; | ||
314 | } | ||
315 | |||
316 | /* Register the socdev */ | ||
317 | ret = snd_soc_init_card(socdev); | ||
318 | if (ret < 0) { | ||
319 | dev_err(codec->dev, "failed to register card\n"); | ||
320 | snd_soc_free_pcms(socdev); | ||
321 | return ret; | ||
322 | } | ||
323 | |||
324 | return 0; | ||
325 | } | ||
326 | |||
327 | static int ak4104_remove(struct platform_device *pdev) | ||
328 | { | ||
329 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
330 | snd_soc_free_pcms(socdev); | ||
331 | return 0; | ||
332 | }; | ||
333 | |||
334 | struct snd_soc_codec_device soc_codec_device_ak4104 = { | ||
335 | .probe = ak4104_probe, | ||
336 | .remove = ak4104_remove | ||
337 | }; | ||
338 | EXPORT_SYMBOL_GPL(soc_codec_device_ak4104); | ||
339 | |||
340 | static struct spi_driver ak4104_spi_driver = { | ||
341 | .driver = { | ||
342 | .name = DRV_NAME, | ||
343 | .owner = THIS_MODULE, | ||
344 | }, | ||
345 | .probe = ak4104_spi_probe, | ||
346 | .remove = __devexit_p(ak4104_spi_remove), | ||
347 | }; | ||
348 | |||
349 | static int __init ak4104_init(void) | ||
350 | { | ||
351 | pr_info("Asahi Kasei AK4104 ALSA SoC Codec Driver\n"); | ||
352 | return spi_register_driver(&ak4104_spi_driver); | ||
353 | } | ||
354 | module_init(ak4104_init); | ||
355 | |||
356 | static void __exit ak4104_exit(void) | ||
357 | { | ||
358 | spi_unregister_driver(&ak4104_spi_driver); | ||
359 | } | ||
360 | module_exit(ak4104_exit); | ||
361 | |||
362 | MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); | ||
363 | MODULE_DESCRIPTION("Asahi Kasei AK4104 ALSA SoC driver"); | ||
364 | MODULE_LICENSE("GPL"); | ||
365 | |||
diff --git a/sound/soc/codecs/ak4104.h b/sound/soc/codecs/ak4104.h new file mode 100644 index 000000000000..eb88fe7e4def --- /dev/null +++ b/sound/soc/codecs/ak4104.h | |||
@@ -0,0 +1,7 @@ | |||
1 | #ifndef _AK4104_H | ||
2 | #define _AK4104_H | ||
3 | |||
4 | extern struct snd_soc_dai ak4104_dai; | ||
5 | extern struct snd_soc_codec_device soc_codec_device_ak4104; | ||
6 | |||
7 | #endif | ||
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c index 81300d8d42ca..1f63d387a2f4 100644 --- a/sound/soc/codecs/ak4535.c +++ b/sound/soc/codecs/ak4535.c | |||
@@ -155,21 +155,6 @@ static const struct snd_kcontrol_new ak4535_snd_controls[] = { | |||
155 | SOC_SINGLE("Mic Sidetone Volume", AK4535_VOL, 4, 7, 0), | 155 | SOC_SINGLE("Mic Sidetone Volume", AK4535_VOL, 4, 7, 0), |
156 | }; | 156 | }; |
157 | 157 | ||
158 | /* add non dapm controls */ | ||
159 | static int ak4535_add_controls(struct snd_soc_codec *codec) | ||
160 | { | ||
161 | int err, i; | ||
162 | |||
163 | for (i = 0; i < ARRAY_SIZE(ak4535_snd_controls); i++) { | ||
164 | err = snd_ctl_add(codec->card, | ||
165 | snd_soc_cnew(&ak4535_snd_controls[i], codec, NULL)); | ||
166 | if (err < 0) | ||
167 | return err; | ||
168 | } | ||
169 | |||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | /* Mono 1 Mixer */ | 158 | /* Mono 1 Mixer */ |
174 | static const struct snd_kcontrol_new ak4535_mono1_mixer_controls[] = { | 159 | static const struct snd_kcontrol_new ak4535_mono1_mixer_controls[] = { |
175 | SOC_DAPM_SINGLE("Mic Sidetone Switch", AK4535_SIG1, 4, 1, 0), | 160 | SOC_DAPM_SINGLE("Mic Sidetone Switch", AK4535_SIG1, 4, 1, 0), |
@@ -344,7 +329,7 @@ static int ak4535_hw_params(struct snd_pcm_substream *substream, | |||
344 | { | 329 | { |
345 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 330 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
346 | struct snd_soc_device *socdev = rtd->socdev; | 331 | struct snd_soc_device *socdev = rtd->socdev; |
347 | struct snd_soc_codec *codec = socdev->codec; | 332 | struct snd_soc_codec *codec = socdev->card->codec; |
348 | struct ak4535_priv *ak4535 = codec->private_data; | 333 | struct ak4535_priv *ak4535 = codec->private_data; |
349 | u8 mode2 = ak4535_read_reg_cache(codec, AK4535_MODE2) & ~(0x3 << 5); | 334 | u8 mode2 = ak4535_read_reg_cache(codec, AK4535_MODE2) & ~(0x3 << 5); |
350 | int rate = params_rate(params), fs = 256; | 335 | int rate = params_rate(params), fs = 256; |
@@ -436,6 +421,13 @@ static int ak4535_set_bias_level(struct snd_soc_codec *codec, | |||
436 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\ | 421 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\ |
437 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) | 422 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) |
438 | 423 | ||
424 | static struct snd_soc_dai_ops ak4535_dai_ops = { | ||
425 | .hw_params = ak4535_hw_params, | ||
426 | .set_fmt = ak4535_set_dai_fmt, | ||
427 | .digital_mute = ak4535_mute, | ||
428 | .set_sysclk = ak4535_set_dai_sysclk, | ||
429 | }; | ||
430 | |||
439 | struct snd_soc_dai ak4535_dai = { | 431 | struct snd_soc_dai ak4535_dai = { |
440 | .name = "AK4535", | 432 | .name = "AK4535", |
441 | .playback = { | 433 | .playback = { |
@@ -450,19 +442,14 @@ struct snd_soc_dai ak4535_dai = { | |||
450 | .channels_max = 2, | 442 | .channels_max = 2, |
451 | .rates = AK4535_RATES, | 443 | .rates = AK4535_RATES, |
452 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | 444 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, |
453 | .ops = { | 445 | .ops = &ak4535_dai_ops, |
454 | .hw_params = ak4535_hw_params, | ||
455 | .set_fmt = ak4535_set_dai_fmt, | ||
456 | .digital_mute = ak4535_mute, | ||
457 | .set_sysclk = ak4535_set_dai_sysclk, | ||
458 | }, | ||
459 | }; | 446 | }; |
460 | EXPORT_SYMBOL_GPL(ak4535_dai); | 447 | EXPORT_SYMBOL_GPL(ak4535_dai); |
461 | 448 | ||
462 | static int ak4535_suspend(struct platform_device *pdev, pm_message_t state) | 449 | static int ak4535_suspend(struct platform_device *pdev, pm_message_t state) |
463 | { | 450 | { |
464 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 451 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
465 | struct snd_soc_codec *codec = socdev->codec; | 452 | struct snd_soc_codec *codec = socdev->card->codec; |
466 | 453 | ||
467 | ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF); | 454 | ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF); |
468 | return 0; | 455 | return 0; |
@@ -471,7 +458,7 @@ static int ak4535_suspend(struct platform_device *pdev, pm_message_t state) | |||
471 | static int ak4535_resume(struct platform_device *pdev) | 458 | static int ak4535_resume(struct platform_device *pdev) |
472 | { | 459 | { |
473 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 460 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
474 | struct snd_soc_codec *codec = socdev->codec; | 461 | struct snd_soc_codec *codec = socdev->card->codec; |
475 | ak4535_sync(codec); | 462 | ak4535_sync(codec); |
476 | ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 463 | ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
477 | ak4535_set_bias_level(codec, codec->suspend_bias_level); | 464 | ak4535_set_bias_level(codec, codec->suspend_bias_level); |
@@ -484,7 +471,7 @@ static int ak4535_resume(struct platform_device *pdev) | |||
484 | */ | 471 | */ |
485 | static int ak4535_init(struct snd_soc_device *socdev) | 472 | static int ak4535_init(struct snd_soc_device *socdev) |
486 | { | 473 | { |
487 | struct snd_soc_codec *codec = socdev->codec; | 474 | struct snd_soc_codec *codec = socdev->card->codec; |
488 | int ret = 0; | 475 | int ret = 0; |
489 | 476 | ||
490 | codec->name = "AK4535"; | 477 | codec->name = "AK4535"; |
@@ -510,7 +497,8 @@ static int ak4535_init(struct snd_soc_device *socdev) | |||
510 | /* power on device */ | 497 | /* power on device */ |
511 | ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 498 | ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
512 | 499 | ||
513 | ak4535_add_controls(codec); | 500 | snd_soc_add_controls(codec, ak4535_snd_controls, |
501 | ARRAY_SIZE(ak4535_snd_controls)); | ||
514 | ak4535_add_widgets(codec); | 502 | ak4535_add_widgets(codec); |
515 | ret = snd_soc_init_card(socdev); | 503 | ret = snd_soc_init_card(socdev); |
516 | if (ret < 0) { | 504 | if (ret < 0) { |
@@ -537,7 +525,7 @@ static int ak4535_i2c_probe(struct i2c_client *i2c, | |||
537 | const struct i2c_device_id *id) | 525 | const struct i2c_device_id *id) |
538 | { | 526 | { |
539 | struct snd_soc_device *socdev = ak4535_socdev; | 527 | struct snd_soc_device *socdev = ak4535_socdev; |
540 | struct snd_soc_codec *codec = socdev->codec; | 528 | struct snd_soc_codec *codec = socdev->card->codec; |
541 | int ret; | 529 | int ret; |
542 | 530 | ||
543 | i2c_set_clientdata(i2c, codec); | 531 | i2c_set_clientdata(i2c, codec); |
@@ -636,7 +624,7 @@ static int ak4535_probe(struct platform_device *pdev) | |||
636 | } | 624 | } |
637 | 625 | ||
638 | codec->private_data = ak4535; | 626 | codec->private_data = ak4535; |
639 | socdev->codec = codec; | 627 | socdev->card->codec = codec; |
640 | mutex_init(&codec->mutex); | 628 | mutex_init(&codec->mutex); |
641 | INIT_LIST_HEAD(&codec->dapm_widgets); | 629 | INIT_LIST_HEAD(&codec->dapm_widgets); |
642 | INIT_LIST_HEAD(&codec->dapm_paths); | 630 | INIT_LIST_HEAD(&codec->dapm_paths); |
@@ -663,7 +651,7 @@ static int ak4535_probe(struct platform_device *pdev) | |||
663 | static int ak4535_remove(struct platform_device *pdev) | 651 | static int ak4535_remove(struct platform_device *pdev) |
664 | { | 652 | { |
665 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 653 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
666 | struct snd_soc_codec *codec = socdev->codec; | 654 | struct snd_soc_codec *codec = socdev->card->codec; |
667 | 655 | ||
668 | if (codec->control_data) | 656 | if (codec->control_data) |
669 | ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF); | 657 | ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF); |
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index f1aa0c34421c..7fa09a387622 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c | |||
@@ -3,27 +3,22 @@ | |||
3 | * | 3 | * |
4 | * Author: Timur Tabi <timur@freescale.com> | 4 | * Author: Timur Tabi <timur@freescale.com> |
5 | * | 5 | * |
6 | * Copyright 2007 Freescale Semiconductor, Inc. This file is licensed under | 6 | * Copyright 2007-2009 Freescale Semiconductor, Inc. This file is licensed |
7 | * the terms of the GNU General Public License version 2. This program | 7 | * under the terms of the GNU General Public License version 2. This |
8 | * is licensed "as is" without any warranty of any kind, whether express | 8 | * program is licensed "as is" without any warranty of any kind, whether |
9 | * or implied. | 9 | * express or implied. |
10 | * | 10 | * |
11 | * This is an ASoC device driver for the Cirrus Logic CS4270 codec. | 11 | * This is an ASoC device driver for the Cirrus Logic CS4270 codec. |
12 | * | 12 | * |
13 | * Current features/limitations: | 13 | * Current features/limitations: |
14 | * | 14 | * |
15 | * 1) Software mode is supported. Stand-alone mode is automatically | 15 | * - Software mode is supported. Stand-alone mode is not supported. |
16 | * selected if I2C is disabled or if a CS4270 is not found on the I2C | 16 | * - Only I2C is supported, not SPI |
17 | * bus. However, stand-alone mode is only partially implemented because | 17 | * - Support for master and slave mode |
18 | * there is no mechanism yet for this driver and the machine driver to | 18 | * - The machine driver's 'startup' function must call |
19 | * communicate the values of the M0, M1, MCLK1, and MCLK2 pins. | 19 | * cs4270_set_dai_sysclk() with the value of MCLK. |
20 | * 2) Only I2C is supported, not SPI | 20 | * - Only I2S and left-justified modes are supported |
21 | * 3) Only Master mode is supported, not Slave. | 21 | * - Power management is not supported |
22 | * 4) The machine driver's 'startup' function must call | ||
23 | * cs4270_set_dai_sysclk() with the value of MCLK. | ||
24 | * 5) Only I2S and left-justified modes are supported | ||
25 | * 6) Power management is not supported | ||
26 | * 7) The only supported control is volume and hardware mute (if enabled) | ||
27 | */ | 22 | */ |
28 | 23 | ||
29 | #include <linux/module.h> | 24 | #include <linux/module.h> |
@@ -35,18 +30,6 @@ | |||
35 | 30 | ||
36 | #include "cs4270.h" | 31 | #include "cs4270.h" |
37 | 32 | ||
38 | /* If I2C is defined, then we support software mode. However, if we're | ||
39 | not compiled as module but I2C is, then we can't use I2C calls. */ | ||
40 | #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) | ||
41 | #define USE_I2C | ||
42 | #endif | ||
43 | |||
44 | /* Private data for the CS4270 */ | ||
45 | struct cs4270_private { | ||
46 | unsigned int mclk; /* Input frequency of the MCLK pin */ | ||
47 | unsigned int mode; /* The mode (I2S or left-justified) */ | ||
48 | }; | ||
49 | |||
50 | /* | 33 | /* |
51 | * The codec isn't really big-endian or little-endian, since the I2S | 34 | * The codec isn't really big-endian or little-endian, since the I2S |
52 | * interface requires data to be sent serially with the MSbit first. | 35 | * interface requires data to be sent serially with the MSbit first. |
@@ -60,8 +43,6 @@ struct cs4270_private { | |||
60 | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE | \ | 43 | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE | \ |
61 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE) | 44 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE) |
62 | 45 | ||
63 | #ifdef USE_I2C | ||
64 | |||
65 | /* CS4270 registers addresses */ | 46 | /* CS4270 registers addresses */ |
66 | #define CS4270_CHIPID 0x01 /* Chip ID */ | 47 | #define CS4270_CHIPID 0x01 /* Chip ID */ |
67 | #define CS4270_PWRCTL 0x02 /* Power Control */ | 48 | #define CS4270_PWRCTL 0x02 /* Power Control */ |
@@ -121,8 +102,22 @@ struct cs4270_private { | |||
121 | #define CS4270_MUTE_DAC_A 0x01 | 102 | #define CS4270_MUTE_DAC_A 0x01 |
122 | #define CS4270_MUTE_DAC_B 0x02 | 103 | #define CS4270_MUTE_DAC_B 0x02 |
123 | 104 | ||
124 | /* | 105 | /* Private data for the CS4270 */ |
125 | * Clock Ratio Selection for Master Mode with I2C enabled | 106 | struct cs4270_private { |
107 | struct snd_soc_codec codec; | ||
108 | u8 reg_cache[CS4270_NUMREGS]; | ||
109 | unsigned int mclk; /* Input frequency of the MCLK pin */ | ||
110 | unsigned int mode; /* The mode (I2S or left-justified) */ | ||
111 | unsigned int slave_mode; | ||
112 | }; | ||
113 | |||
114 | /** | ||
115 | * struct cs4270_mode_ratios - clock ratio tables | ||
116 | * @ratio: the ratio of MCLK to the sample rate | ||
117 | * @speed_mode: the Speed Mode bits to set in the Mode Control register for | ||
118 | * this ratio | ||
119 | * @mclk: the Ratio Select bits to set in the Mode Control register for this | ||
120 | * ratio | ||
126 | * | 121 | * |
127 | * The data for this chart is taken from Table 5 of the CS4270 reference | 122 | * The data for this chart is taken from Table 5 of the CS4270 reference |
128 | * manual. | 123 | * manual. |
@@ -131,31 +126,30 @@ struct cs4270_private { | |||
131 | * It is also used by cs4270_set_dai_sysclk() to tell ALSA which sampling | 126 | * It is also used by cs4270_set_dai_sysclk() to tell ALSA which sampling |
132 | * rates the CS4270 currently supports. | 127 | * rates the CS4270 currently supports. |
133 | * | 128 | * |
134 | * Each element in this array corresponds to the ratios in mclk_ratios[]. | 129 | * @speed_mode is the corresponding bit pattern to be written to the |
135 | * These two arrays need to be in sync. | ||
136 | * | ||
137 | * 'speed_mode' is the corresponding bit pattern to be written to the | ||
138 | * MODE bits of the Mode Control Register | 130 | * MODE bits of the Mode Control Register |
139 | * | 131 | * |
140 | * 'mclk' is the corresponding bit pattern to be wirten to the MCLK bits of | 132 | * @mclk is the corresponding bit pattern to be wirten to the MCLK bits of |
141 | * the Mode Control Register. | 133 | * the Mode Control Register. |
142 | * | 134 | * |
143 | * In situations where a single ratio is represented by multiple speed | 135 | * In situations where a single ratio is represented by multiple speed |
144 | * modes, we favor the slowest speed. E.g, for a ratio of 128, we pick | 136 | * modes, we favor the slowest speed. E.g, for a ratio of 128, we pick |
145 | * double-speed instead of quad-speed. However, the CS4270 errata states | 137 | * double-speed instead of quad-speed. However, the CS4270 errata states |
146 | * that Divide-By-1.5 can cause failures, so we avoid that mode where | 138 | * that divide-By-1.5 can cause failures, so we avoid that mode where |
147 | * possible. | 139 | * possible. |
148 | * | 140 | * |
149 | * ERRATA: There is an errata for the CS4270 where divide-by-1.5 does not | 141 | * Errata: There is an errata for the CS4270 where divide-by-1.5 does not |
150 | * work if VD = 3.3V. If this effects you, select the | 142 | * work if Vd is 3.3V. If this effects you, select the |
151 | * CONFIG_SND_SOC_CS4270_VD33_ERRATA Kconfig option, and the driver will | 143 | * CONFIG_SND_SOC_CS4270_VD33_ERRATA Kconfig option, and the driver will |
152 | * never select any sample rates that require divide-by-1.5. | 144 | * never select any sample rates that require divide-by-1.5. |
153 | */ | 145 | */ |
154 | static struct { | 146 | struct cs4270_mode_ratios { |
155 | unsigned int ratio; | 147 | unsigned int ratio; |
156 | u8 speed_mode; | 148 | u8 speed_mode; |
157 | u8 mclk; | 149 | u8 mclk; |
158 | } cs4270_mode_ratios[] = { | 150 | }; |
151 | |||
152 | static struct cs4270_mode_ratios cs4270_mode_ratios[] = { | ||
159 | {64, CS4270_MODE_4X, CS4270_MODE_DIV1}, | 153 | {64, CS4270_MODE_4X, CS4270_MODE_DIV1}, |
160 | #ifndef CONFIG_SND_SOC_CS4270_VD33_ERRATA | 154 | #ifndef CONFIG_SND_SOC_CS4270_VD33_ERRATA |
161 | {96, CS4270_MODE_4X, CS4270_MODE_DIV15}, | 155 | {96, CS4270_MODE_4X, CS4270_MODE_DIV15}, |
@@ -172,34 +166,27 @@ static struct { | |||
172 | /* The number of MCLK/LRCK ratios supported by the CS4270 */ | 166 | /* The number of MCLK/LRCK ratios supported by the CS4270 */ |
173 | #define NUM_MCLK_RATIOS ARRAY_SIZE(cs4270_mode_ratios) | 167 | #define NUM_MCLK_RATIOS ARRAY_SIZE(cs4270_mode_ratios) |
174 | 168 | ||
175 | /* | 169 | /** |
176 | * Determine the CS4270 samples rates. | 170 | * cs4270_set_dai_sysclk - determine the CS4270 samples rates. |
171 | * @codec_dai: the codec DAI | ||
172 | * @clk_id: the clock ID (ignored) | ||
173 | * @freq: the MCLK input frequency | ||
174 | * @dir: the clock direction (ignored) | ||
177 | * | 175 | * |
178 | * 'freq' is the input frequency to MCLK. The other parameters are ignored. | 176 | * This function is used to tell the codec driver what the input MCLK |
177 | * frequency is. | ||
179 | * | 178 | * |
180 | * The value of MCLK is used to determine which sample rates are supported | 179 | * The value of MCLK is used to determine which sample rates are supported |
181 | * by the CS4270. The ratio of MCLK / Fs must be equal to one of nine | 180 | * by the CS4270. The ratio of MCLK / Fs must be equal to one of nine |
182 | * support values: 64, 96, 128, 192, 256, 384, 512, 768, and 1024. | 181 | * supported values - 64, 96, 128, 192, 256, 384, 512, 768, and 1024. |
183 | * | 182 | * |
184 | * This function calculates the nine ratios and determines which ones match | 183 | * This function calculates the nine ratios and determines which ones match |
185 | * a standard sample rate. If there's a match, then it is added to the list | 184 | * a standard sample rate. If there's a match, then it is added to the list |
186 | * of support sample rates. | 185 | * of supported sample rates. |
187 | * | 186 | * |
188 | * This function must be called by the machine driver's 'startup' function, | 187 | * This function must be called by the machine driver's 'startup' function, |
189 | * otherwise the list of supported sample rates will not be available in | 188 | * otherwise the list of supported sample rates will not be available in |
190 | * time for ALSA. | 189 | * time for ALSA. |
191 | * | ||
192 | * Note that in stand-alone mode, the sample rate is determined by input | ||
193 | * pins M0, M1, MDIV1, and MDIV2. Also in stand-alone mode, divide-by-3 | ||
194 | * is not a programmable option. However, divide-by-3 is not an available | ||
195 | * option in stand-alone mode. This cases two problems: a ratio of 768 is | ||
196 | * not available (it requires divide-by-3) and B) ratios 192 and 384 can | ||
197 | * only be selected with divide-by-1.5, but there is an errate that make | ||
198 | * this selection difficult. | ||
199 | * | ||
200 | * In addition, there is no mechanism for communicating with the machine | ||
201 | * driver what the input settings can be. This would need to be implemented | ||
202 | * for stand-alone mode to work. | ||
203 | */ | 190 | */ |
204 | static int cs4270_set_dai_sysclk(struct snd_soc_dai *codec_dai, | 191 | static int cs4270_set_dai_sysclk(struct snd_soc_dai *codec_dai, |
205 | int clk_id, unsigned int freq, int dir) | 192 | int clk_id, unsigned int freq, int dir) |
@@ -225,7 +212,7 @@ static int cs4270_set_dai_sysclk(struct snd_soc_dai *codec_dai, | |||
225 | rates &= ~SNDRV_PCM_RATE_KNOT; | 212 | rates &= ~SNDRV_PCM_RATE_KNOT; |
226 | 213 | ||
227 | if (!rates) { | 214 | if (!rates) { |
228 | printk(KERN_ERR "cs4270: could not find a valid sample rate\n"); | 215 | dev_err(codec->dev, "could not find a valid sample rate\n"); |
229 | return -EINVAL; | 216 | return -EINVAL; |
230 | } | 217 | } |
231 | 218 | ||
@@ -240,8 +227,10 @@ static int cs4270_set_dai_sysclk(struct snd_soc_dai *codec_dai, | |||
240 | return 0; | 227 | return 0; |
241 | } | 228 | } |
242 | 229 | ||
243 | /* | 230 | /** |
244 | * Configure the codec for the selected audio format | 231 | * cs4270_set_dai_fmt - configure the codec for the selected audio format |
232 | * @codec_dai: the codec DAI | ||
233 | * @format: a SND_SOC_DAIFMT_x value indicating the data format | ||
245 | * | 234 | * |
246 | * This function takes a bitmask of SND_SOC_DAIFMT_x bits and programs the | 235 | * This function takes a bitmask of SND_SOC_DAIFMT_x bits and programs the |
247 | * codec accordingly. | 236 | * codec accordingly. |
@@ -258,32 +247,43 @@ static int cs4270_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
258 | struct cs4270_private *cs4270 = codec->private_data; | 247 | struct cs4270_private *cs4270 = codec->private_data; |
259 | int ret = 0; | 248 | int ret = 0; |
260 | 249 | ||
250 | /* set DAI format */ | ||
261 | switch (format & SND_SOC_DAIFMT_FORMAT_MASK) { | 251 | switch (format & SND_SOC_DAIFMT_FORMAT_MASK) { |
262 | case SND_SOC_DAIFMT_I2S: | 252 | case SND_SOC_DAIFMT_I2S: |
263 | case SND_SOC_DAIFMT_LEFT_J: | 253 | case SND_SOC_DAIFMT_LEFT_J: |
264 | cs4270->mode = format & SND_SOC_DAIFMT_FORMAT_MASK; | 254 | cs4270->mode = format & SND_SOC_DAIFMT_FORMAT_MASK; |
265 | break; | 255 | break; |
266 | default: | 256 | default: |
267 | printk(KERN_ERR "cs4270: invalid DAI format\n"); | 257 | dev_err(codec->dev, "invalid dai format\n"); |
258 | ret = -EINVAL; | ||
259 | } | ||
260 | |||
261 | /* set master/slave audio interface */ | ||
262 | switch (format & SND_SOC_DAIFMT_MASTER_MASK) { | ||
263 | case SND_SOC_DAIFMT_CBS_CFS: | ||
264 | cs4270->slave_mode = 1; | ||
265 | break; | ||
266 | case SND_SOC_DAIFMT_CBM_CFM: | ||
267 | cs4270->slave_mode = 0; | ||
268 | break; | ||
269 | default: | ||
270 | /* all other modes are unsupported by the hardware */ | ||
268 | ret = -EINVAL; | 271 | ret = -EINVAL; |
269 | } | 272 | } |
270 | 273 | ||
271 | return ret; | 274 | return ret; |
272 | } | 275 | } |
273 | 276 | ||
274 | /* | 277 | /** |
275 | * A list of addresses on which this CS4270 could use. I2C addresses are | 278 | * cs4270_fill_cache - pre-fill the CS4270 register cache. |
276 | * 7 bits. For the CS4270, the upper four bits are always 1001, and the | 279 | * @codec: the codec for this CS4270 |
277 | * lower three bits are determined via the AD2, AD1, and AD0 pins | 280 | * |
278 | * (respectively). | 281 | * This function fills in the CS4270 register cache by reading the register |
279 | */ | 282 | * values from the hardware. |
280 | static const unsigned short normal_i2c[] = { | 283 | * |
281 | 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, I2C_CLIENT_END | 284 | * This CS4270 registers are cached to avoid excessive I2C I/O operations. |
282 | }; | 285 | * After the initial read to pre-fill the cache, the CS4270 never updates |
283 | I2C_CLIENT_INSMOD; | 286 | * the register values, so we won't have a cache coherency problem. |
284 | |||
285 | /* | ||
286 | * Pre-fill the CS4270 register cache. | ||
287 | * | 287 | * |
288 | * We use the auto-increment feature of the CS4270 to read all registers in | 288 | * We use the auto-increment feature of the CS4270 to read all registers in |
289 | * one shot. | 289 | * one shot. |
@@ -298,7 +298,7 @@ static int cs4270_fill_cache(struct snd_soc_codec *codec) | |||
298 | CS4270_FIRSTREG | 0x80, CS4270_NUMREGS, cache); | 298 | CS4270_FIRSTREG | 0x80, CS4270_NUMREGS, cache); |
299 | 299 | ||
300 | if (length != CS4270_NUMREGS) { | 300 | if (length != CS4270_NUMREGS) { |
301 | printk(KERN_ERR "cs4270: I2C read failure, addr=0x%x\n", | 301 | dev_err(codec->dev, "i2c read failure, addr=0x%x\n", |
302 | i2c_client->addr); | 302 | i2c_client->addr); |
303 | return -EIO; | 303 | return -EIO; |
304 | } | 304 | } |
@@ -306,12 +306,17 @@ static int cs4270_fill_cache(struct snd_soc_codec *codec) | |||
306 | return 0; | 306 | return 0; |
307 | } | 307 | } |
308 | 308 | ||
309 | /* | 309 | /** |
310 | * Read from the CS4270 register cache. | 310 | * cs4270_read_reg_cache - read from the CS4270 register cache. |
311 | * @codec: the codec for this CS4270 | ||
312 | * @reg: the register to read | ||
313 | * | ||
314 | * This function returns the value for a given register. It reads only from | ||
315 | * the register cache, not the hardware itself. | ||
311 | * | 316 | * |
312 | * This CS4270 registers are cached to avoid excessive I2C I/O operations. | 317 | * This CS4270 registers are cached to avoid excessive I2C I/O operations. |
313 | * After the initial read to pre-fill the cache, the CS4270 never updates | 318 | * After the initial read to pre-fill the cache, the CS4270 never updates |
314 | * the register values, so we won't have a cache coherncy problem. | 319 | * the register values, so we won't have a cache coherency problem. |
315 | */ | 320 | */ |
316 | static unsigned int cs4270_read_reg_cache(struct snd_soc_codec *codec, | 321 | static unsigned int cs4270_read_reg_cache(struct snd_soc_codec *codec, |
317 | unsigned int reg) | 322 | unsigned int reg) |
@@ -324,8 +329,11 @@ static unsigned int cs4270_read_reg_cache(struct snd_soc_codec *codec, | |||
324 | return cache[reg - CS4270_FIRSTREG]; | 329 | return cache[reg - CS4270_FIRSTREG]; |
325 | } | 330 | } |
326 | 331 | ||
327 | /* | 332 | /** |
328 | * Write to a CS4270 register via the I2C bus. | 333 | * cs4270_i2c_write - write to a CS4270 register via the I2C bus. |
334 | * @codec: the codec for this CS4270 | ||
335 | * @reg: the register to write | ||
336 | * @value: the value to write to the register | ||
329 | * | 337 | * |
330 | * This function writes the given value to the given CS4270 register, and | 338 | * This function writes the given value to the given CS4270 register, and |
331 | * also updates the register cache. | 339 | * also updates the register cache. |
@@ -346,7 +354,7 @@ static int cs4270_i2c_write(struct snd_soc_codec *codec, unsigned int reg, | |||
346 | if (cache[reg - CS4270_FIRSTREG] != value) { | 354 | if (cache[reg - CS4270_FIRSTREG] != value) { |
347 | struct i2c_client *client = codec->control_data; | 355 | struct i2c_client *client = codec->control_data; |
348 | if (i2c_smbus_write_byte_data(client, reg, value)) { | 356 | if (i2c_smbus_write_byte_data(client, reg, value)) { |
349 | printk(KERN_ERR "cs4270: I2C write failed\n"); | 357 | dev_err(codec->dev, "i2c write failed\n"); |
350 | return -EIO; | 358 | return -EIO; |
351 | } | 359 | } |
352 | 360 | ||
@@ -357,11 +365,17 @@ static int cs4270_i2c_write(struct snd_soc_codec *codec, unsigned int reg, | |||
357 | return 0; | 365 | return 0; |
358 | } | 366 | } |
359 | 367 | ||
360 | /* | 368 | /** |
361 | * Program the CS4270 with the given hardware parameters. | 369 | * cs4270_hw_params - program the CS4270 with the given hardware parameters. |
370 | * @substream: the audio stream | ||
371 | * @params: the hardware parameters to set | ||
372 | * @dai: the SOC DAI (ignored) | ||
373 | * | ||
374 | * This function programs the hardware with the values provided. | ||
375 | * Specifically, the sample rate and the data format. | ||
362 | * | 376 | * |
363 | * The .ops functions are used to provide board-specific data, like | 377 | * The .ops functions are used to provide board-specific data, like input |
364 | * input frequencies, to this driver. This function takes that information, | 378 | * frequencies, to this driver. This function takes that information, |
365 | * combines it with the hardware parameters provided, and programs the | 379 | * combines it with the hardware parameters provided, and programs the |
366 | * hardware accordingly. | 380 | * hardware accordingly. |
367 | */ | 381 | */ |
@@ -371,7 +385,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream, | |||
371 | { | 385 | { |
372 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 386 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
373 | struct snd_soc_device *socdev = rtd->socdev; | 387 | struct snd_soc_device *socdev = rtd->socdev; |
374 | struct snd_soc_codec *codec = socdev->codec; | 388 | struct snd_soc_codec *codec = socdev->card->codec; |
375 | struct cs4270_private *cs4270 = codec->private_data; | 389 | struct cs4270_private *cs4270 = codec->private_data; |
376 | int ret; | 390 | int ret; |
377 | unsigned int i; | 391 | unsigned int i; |
@@ -391,33 +405,28 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream, | |||
391 | 405 | ||
392 | if (i == NUM_MCLK_RATIOS) { | 406 | if (i == NUM_MCLK_RATIOS) { |
393 | /* We did not find a matching ratio */ | 407 | /* We did not find a matching ratio */ |
394 | printk(KERN_ERR "cs4270: could not find matching ratio\n"); | 408 | dev_err(codec->dev, "could not find matching ratio\n"); |
395 | return -EINVAL; | 409 | return -EINVAL; |
396 | } | 410 | } |
397 | 411 | ||
398 | /* Freeze and power-down the codec */ | 412 | /* Set the sample rate */ |
399 | |||
400 | ret = snd_soc_write(codec, CS4270_PWRCTL, CS4270_PWRCTL_FREEZE | | ||
401 | CS4270_PWRCTL_PDN_ADC | CS4270_PWRCTL_PDN_DAC | | ||
402 | CS4270_PWRCTL_PDN); | ||
403 | if (ret < 0) { | ||
404 | printk(KERN_ERR "cs4270: I2C write failed\n"); | ||
405 | return ret; | ||
406 | } | ||
407 | |||
408 | /* Program the mode control register */ | ||
409 | 413 | ||
410 | reg = snd_soc_read(codec, CS4270_MODE); | 414 | reg = snd_soc_read(codec, CS4270_MODE); |
411 | reg &= ~(CS4270_MODE_SPEED_MASK | CS4270_MODE_DIV_MASK); | 415 | reg &= ~(CS4270_MODE_SPEED_MASK | CS4270_MODE_DIV_MASK); |
412 | reg |= cs4270_mode_ratios[i].speed_mode | cs4270_mode_ratios[i].mclk; | 416 | reg |= cs4270_mode_ratios[i].mclk; |
417 | |||
418 | if (cs4270->slave_mode) | ||
419 | reg |= CS4270_MODE_SLAVE; | ||
420 | else | ||
421 | reg |= cs4270_mode_ratios[i].speed_mode; | ||
413 | 422 | ||
414 | ret = snd_soc_write(codec, CS4270_MODE, reg); | 423 | ret = snd_soc_write(codec, CS4270_MODE, reg); |
415 | if (ret < 0) { | 424 | if (ret < 0) { |
416 | printk(KERN_ERR "cs4270: I2C write failed\n"); | 425 | dev_err(codec->dev, "i2c write failed\n"); |
417 | return ret; | 426 | return ret; |
418 | } | 427 | } |
419 | 428 | ||
420 | /* Program the format register */ | 429 | /* Set the DAI format */ |
421 | 430 | ||
422 | reg = snd_soc_read(codec, CS4270_FORMAT); | 431 | reg = snd_soc_read(codec, CS4270_FORMAT); |
423 | reg &= ~(CS4270_FORMAT_DAC_MASK | CS4270_FORMAT_ADC_MASK); | 432 | reg &= ~(CS4270_FORMAT_DAC_MASK | CS4270_FORMAT_ADC_MASK); |
@@ -430,55 +439,23 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream, | |||
430 | reg |= CS4270_FORMAT_DAC_LJ | CS4270_FORMAT_ADC_LJ; | 439 | reg |= CS4270_FORMAT_DAC_LJ | CS4270_FORMAT_ADC_LJ; |
431 | break; | 440 | break; |
432 | default: | 441 | default: |
433 | printk(KERN_ERR "cs4270: unknown format\n"); | 442 | dev_err(codec->dev, "unknown dai format\n"); |
434 | return -EINVAL; | 443 | return -EINVAL; |
435 | } | 444 | } |
436 | 445 | ||
437 | ret = snd_soc_write(codec, CS4270_FORMAT, reg); | 446 | ret = snd_soc_write(codec, CS4270_FORMAT, reg); |
438 | if (ret < 0) { | 447 | if (ret < 0) { |
439 | printk(KERN_ERR "cs4270: I2C write failed\n"); | 448 | dev_err(codec->dev, "i2c write failed\n"); |
440 | return ret; | ||
441 | } | ||
442 | |||
443 | /* Disable auto-mute. This feature appears to be buggy, because in | ||
444 | some situations, auto-mute will not deactivate when it should. */ | ||
445 | |||
446 | reg = snd_soc_read(codec, CS4270_MUTE); | ||
447 | reg &= ~CS4270_MUTE_AUTO; | ||
448 | ret = snd_soc_write(codec, CS4270_MUTE, reg); | ||
449 | if (ret < 0) { | ||
450 | printk(KERN_ERR "cs4270: I2C write failed\n"); | ||
451 | return ret; | ||
452 | } | ||
453 | |||
454 | /* Disable automatic volume control. It's enabled by default, and | ||
455 | * it causes volume change commands to be delayed, sometimes until | ||
456 | * after playback has started. | ||
457 | */ | ||
458 | |||
459 | reg = cs4270_read_reg_cache(codec, CS4270_TRANS); | ||
460 | reg &= ~(CS4270_TRANS_SOFT | CS4270_TRANS_ZERO); | ||
461 | ret = cs4270_i2c_write(codec, CS4270_TRANS, reg); | ||
462 | if (ret < 0) { | ||
463 | printk(KERN_ERR "I2C write failed\n"); | ||
464 | return ret; | ||
465 | } | ||
466 | |||
467 | /* Thaw and power-up the codec */ | ||
468 | |||
469 | ret = snd_soc_write(codec, CS4270_PWRCTL, 0); | ||
470 | if (ret < 0) { | ||
471 | printk(KERN_ERR "cs4270: I2C write failed\n"); | ||
472 | return ret; | 449 | return ret; |
473 | } | 450 | } |
474 | 451 | ||
475 | return ret; | 452 | return ret; |
476 | } | 453 | } |
477 | 454 | ||
478 | #ifdef CONFIG_SND_SOC_CS4270_HWMUTE | 455 | /** |
479 | 456 | * cs4270_mute - enable/disable the CS4270 external mute | |
480 | /* | 457 | * @dai: the SOC DAI |
481 | * Set the CS4270 external mute | 458 | * @mute: 0 = disable mute, 1 = enable mute |
482 | * | 459 | * |
483 | * This function toggles the mute bits in the MUTE register. The CS4270's | 460 | * This function toggles the mute bits in the MUTE register. The CS4270's |
484 | * mute capability is intended for external muting circuitry, so if the | 461 | * mute capability is intended for external muting circuitry, so if the |
@@ -493,276 +470,306 @@ static int cs4270_mute(struct snd_soc_dai *dai, int mute) | |||
493 | reg6 = snd_soc_read(codec, CS4270_MUTE); | 470 | reg6 = snd_soc_read(codec, CS4270_MUTE); |
494 | 471 | ||
495 | if (mute) | 472 | if (mute) |
496 | reg6 |= CS4270_MUTE_ADC_A | CS4270_MUTE_ADC_B | | 473 | reg6 |= CS4270_MUTE_DAC_A | CS4270_MUTE_DAC_B; |
497 | CS4270_MUTE_DAC_A | CS4270_MUTE_DAC_B; | ||
498 | else | 474 | else |
499 | reg6 &= ~(CS4270_MUTE_ADC_A | CS4270_MUTE_ADC_B | | 475 | reg6 &= ~(CS4270_MUTE_DAC_A | CS4270_MUTE_DAC_B); |
500 | CS4270_MUTE_DAC_A | CS4270_MUTE_DAC_B); | ||
501 | 476 | ||
502 | return snd_soc_write(codec, CS4270_MUTE, reg6); | 477 | return snd_soc_write(codec, CS4270_MUTE, reg6); |
503 | } | 478 | } |
504 | 479 | ||
505 | #endif | ||
506 | |||
507 | static int cs4270_i2c_probe(struct i2c_client *, const struct i2c_device_id *); | ||
508 | |||
509 | /* A list of non-DAPM controls that the CS4270 supports */ | 480 | /* A list of non-DAPM controls that the CS4270 supports */ |
510 | static const struct snd_kcontrol_new cs4270_snd_controls[] = { | 481 | static const struct snd_kcontrol_new cs4270_snd_controls[] = { |
511 | SOC_DOUBLE_R("Master Playback Volume", | 482 | SOC_DOUBLE_R("Master Playback Volume", |
512 | CS4270_VOLA, CS4270_VOLB, 0, 0xFF, 1) | 483 | CS4270_VOLA, CS4270_VOLB, 0, 0xFF, 1), |
513 | }; | 484 | SOC_SINGLE("Digital Sidetone Switch", CS4270_FORMAT, 5, 1, 0), |
514 | 485 | SOC_SINGLE("Soft Ramp Switch", CS4270_TRANS, 6, 1, 0), | |
515 | static const struct i2c_device_id cs4270_id[] = { | 486 | SOC_SINGLE("Zero Cross Switch", CS4270_TRANS, 5, 1, 0), |
516 | {"cs4270", 0}, | 487 | SOC_SINGLE("Popguard Switch", CS4270_MODE, 0, 1, 1), |
517 | {} | 488 | SOC_SINGLE("Auto-Mute Switch", CS4270_MUTE, 5, 1, 0), |
518 | }; | 489 | SOC_DOUBLE("Master Capture Switch", CS4270_MUTE, 3, 4, 1, 0) |
519 | MODULE_DEVICE_TABLE(i2c, cs4270_id); | ||
520 | |||
521 | static struct i2c_driver cs4270_i2c_driver = { | ||
522 | .driver = { | ||
523 | .name = "CS4270 I2C", | ||
524 | .owner = THIS_MODULE, | ||
525 | }, | ||
526 | .id_table = cs4270_id, | ||
527 | .probe = cs4270_i2c_probe, | ||
528 | }; | 490 | }; |
529 | 491 | ||
530 | /* | 492 | /* |
531 | * Global variable to store socdev for i2c probe function. | 493 | * cs4270_codec - global variable to store codec for the ASoC probe function |
532 | * | 494 | * |
533 | * If struct i2c_driver had a private_data field, we wouldn't need to use | 495 | * If struct i2c_driver had a private_data field, we wouldn't need to use |
534 | * cs4270_socdec. This is the only way to pass the socdev structure to | 496 | * cs4270_codec. This is the only way to pass the codec structure from |
535 | * cs4270_i2c_probe(). | 497 | * cs4270_i2c_probe() to cs4270_probe(). Unfortunately, there is no good |
536 | * | 498 | * way to synchronize these two functions. cs4270_i2c_probe() can be called |
537 | * The real solution to cs4270_socdev is to create a mechanism | 499 | * multiple times before cs4270_probe() is called even once. So for now, we |
538 | * that maps I2C addresses to snd_soc_device structures. Perhaps the | 500 | * also only allow cs4270_i2c_probe() to be run once. That means that we do |
539 | * creation of the snd_soc_device object should be moved out of | 501 | * not support more than one cs4270 device in the system, at least for now. |
540 | * cs4270_probe() and into cs4270_i2c_probe(), but that would make this | ||
541 | * driver dependent on I2C. The CS4270 supports "stand-alone" mode, whereby | ||
542 | * the chip is *not* connected to the I2C bus, but is instead configured via | ||
543 | * input pins. | ||
544 | */ | 502 | */ |
545 | static struct snd_soc_device *cs4270_socdev; | 503 | static struct snd_soc_codec *cs4270_codec; |
546 | 504 | ||
547 | /* | 505 | static struct snd_soc_dai_ops cs4270_dai_ops = { |
548 | * Initialize the I2C interface of the CS4270 | 506 | .hw_params = cs4270_hw_params, |
549 | * | 507 | .set_sysclk = cs4270_set_dai_sysclk, |
550 | * This function is called for whenever the I2C subsystem finds a device | 508 | .set_fmt = cs4270_set_dai_fmt, |
551 | * at a particular address. | 509 | .digital_mute = cs4270_mute, |
510 | }; | ||
511 | |||
512 | struct snd_soc_dai cs4270_dai = { | ||
513 | .name = "cs4270", | ||
514 | .playback = { | ||
515 | .stream_name = "Playback", | ||
516 | .channels_min = 1, | ||
517 | .channels_max = 2, | ||
518 | .rates = 0, | ||
519 | .formats = CS4270_FORMATS, | ||
520 | }, | ||
521 | .capture = { | ||
522 | .stream_name = "Capture", | ||
523 | .channels_min = 1, | ||
524 | .channels_max = 2, | ||
525 | .rates = 0, | ||
526 | .formats = CS4270_FORMATS, | ||
527 | }, | ||
528 | .ops = &cs4270_dai_ops, | ||
529 | }; | ||
530 | EXPORT_SYMBOL_GPL(cs4270_dai); | ||
531 | |||
532 | /** | ||
533 | * cs4270_probe - ASoC probe function | ||
534 | * @pdev: platform device | ||
552 | * | 535 | * |
553 | * Note: snd_soc_new_pcms() must be called before this function can be called, | 536 | * This function is called when ASoC has all the pieces it needs to |
554 | * because of snd_ctl_add(). | 537 | * instantiate a sound driver. |
555 | */ | 538 | */ |
556 | static int cs4270_i2c_probe(struct i2c_client *i2c_client, | 539 | static int cs4270_probe(struct platform_device *pdev) |
557 | const struct i2c_device_id *id) | ||
558 | { | 540 | { |
559 | struct snd_soc_device *socdev = cs4270_socdev; | 541 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
560 | struct snd_soc_codec *codec = socdev->codec; | 542 | struct snd_soc_codec *codec = cs4270_codec; |
561 | int i; | 543 | int ret; |
562 | int ret = 0; | ||
563 | |||
564 | /* Probing all possible addresses has one drawback: if there are | ||
565 | multiple CS4270s on the bus, then you cannot specify which | ||
566 | socdev is matched with which CS4270. For now, we just reject | ||
567 | this I2C device if the socdev already has one attached. */ | ||
568 | if (codec->control_data) | ||
569 | return -ENODEV; | ||
570 | |||
571 | /* Note: codec_dai->codec is NULL here */ | ||
572 | |||
573 | codec->reg_cache = kzalloc(CS4270_NUMREGS, GFP_KERNEL); | ||
574 | if (!codec->reg_cache) { | ||
575 | printk(KERN_ERR "cs4270: could not allocate register cache\n"); | ||
576 | ret = -ENOMEM; | ||
577 | goto error; | ||
578 | } | ||
579 | 544 | ||
580 | /* Verify that we have a CS4270 */ | 545 | /* Connect the codec to the socdev. snd_soc_new_pcms() needs this. */ |
546 | socdev->card->codec = codec; | ||
581 | 547 | ||
582 | ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID); | 548 | /* Register PCMs */ |
549 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
583 | if (ret < 0) { | 550 | if (ret < 0) { |
584 | printk(KERN_ERR "cs4270: failed to read I2C\n"); | 551 | dev_err(codec->dev, "failed to create pcms\n"); |
585 | goto error; | 552 | return ret; |
586 | } | ||
587 | /* The top four bits of the chip ID should be 1100. */ | ||
588 | if ((ret & 0xF0) != 0xC0) { | ||
589 | /* The device at this address is not a CS4270 codec */ | ||
590 | ret = -ENODEV; | ||
591 | goto error; | ||
592 | } | 553 | } |
593 | 554 | ||
594 | printk(KERN_INFO "cs4270: found device at I2C address %X\n", | 555 | /* Add the non-DAPM controls */ |
595 | i2c_client->addr); | 556 | ret = snd_soc_add_controls(codec, cs4270_snd_controls, |
596 | printk(KERN_INFO "cs4270: hardware revision %X\n", ret & 0xF); | 557 | ARRAY_SIZE(cs4270_snd_controls)); |
597 | |||
598 | codec->control_data = i2c_client; | ||
599 | codec->read = cs4270_read_reg_cache; | ||
600 | codec->write = cs4270_i2c_write; | ||
601 | codec->reg_cache_size = CS4270_NUMREGS; | ||
602 | |||
603 | /* The I2C interface is set up, so pre-fill our register cache */ | ||
604 | |||
605 | ret = cs4270_fill_cache(codec); | ||
606 | if (ret < 0) { | 558 | if (ret < 0) { |
607 | printk(KERN_ERR "cs4270: failed to fill register cache\n"); | 559 | dev_err(codec->dev, "failed to add controls\n"); |
608 | goto error; | 560 | goto error_free_pcms; |
609 | } | 561 | } |
610 | 562 | ||
611 | /* Add the non-DAPM controls */ | 563 | /* And finally, register the socdev */ |
612 | 564 | ret = snd_soc_init_card(socdev); | |
613 | for (i = 0; i < ARRAY_SIZE(cs4270_snd_controls); i++) { | 565 | if (ret < 0) { |
614 | struct snd_kcontrol *kctrl = | 566 | dev_err(codec->dev, "failed to register card\n"); |
615 | snd_soc_cnew(&cs4270_snd_controls[i], codec, NULL); | 567 | goto error_free_pcms; |
616 | |||
617 | ret = snd_ctl_add(codec->card, kctrl); | ||
618 | if (ret < 0) | ||
619 | goto error; | ||
620 | } | 568 | } |
621 | 569 | ||
622 | i2c_set_clientdata(i2c_client, codec); | ||
623 | |||
624 | return 0; | 570 | return 0; |
625 | 571 | ||
626 | error: | 572 | error_free_pcms: |
627 | codec->control_data = NULL; | 573 | snd_soc_free_pcms(socdev); |
628 | |||
629 | kfree(codec->reg_cache); | ||
630 | codec->reg_cache = NULL; | ||
631 | codec->reg_cache_size = 0; | ||
632 | 574 | ||
633 | return ret; | 575 | return ret; |
634 | } | 576 | } |
635 | 577 | ||
636 | #endif /* USE_I2C*/ | 578 | /** |
579 | * cs4270_remove - ASoC remove function | ||
580 | * @pdev: platform device | ||
581 | * | ||
582 | * This function is the counterpart to cs4270_probe(). | ||
583 | */ | ||
584 | static int cs4270_remove(struct platform_device *pdev) | ||
585 | { | ||
586 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
637 | 587 | ||
638 | struct snd_soc_dai cs4270_dai = { | 588 | snd_soc_free_pcms(socdev); |
639 | .name = "CS4270", | 589 | |
640 | .playback = { | 590 | return 0; |
641 | .stream_name = "Playback", | ||
642 | .channels_min = 1, | ||
643 | .channels_max = 2, | ||
644 | .rates = 0, | ||
645 | .formats = CS4270_FORMATS, | ||
646 | }, | ||
647 | .capture = { | ||
648 | .stream_name = "Capture", | ||
649 | .channels_min = 1, | ||
650 | .channels_max = 2, | ||
651 | .rates = 0, | ||
652 | .formats = CS4270_FORMATS, | ||
653 | }, | ||
654 | }; | 591 | }; |
655 | EXPORT_SYMBOL_GPL(cs4270_dai); | ||
656 | 592 | ||
657 | /* | 593 | /** |
658 | * ASoC probe function | 594 | * cs4270_i2c_probe - initialize the I2C interface of the CS4270 |
595 | * @i2c_client: the I2C client object | ||
596 | * @id: the I2C device ID (ignored) | ||
659 | * | 597 | * |
660 | * This function is called when the machine driver calls | 598 | * This function is called whenever the I2C subsystem finds a device that |
661 | * platform_device_add(). | 599 | * matches the device ID given via a prior call to i2c_add_driver(). |
662 | */ | 600 | */ |
663 | static int cs4270_probe(struct platform_device *pdev) | 601 | static int cs4270_i2c_probe(struct i2c_client *i2c_client, |
602 | const struct i2c_device_id *id) | ||
664 | { | 603 | { |
665 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
666 | struct snd_soc_codec *codec; | 604 | struct snd_soc_codec *codec; |
667 | int ret = 0; | 605 | struct cs4270_private *cs4270; |
606 | unsigned int reg; | ||
607 | int ret; | ||
668 | 608 | ||
669 | printk(KERN_INFO "CS4270 ALSA SoC Codec\n"); | 609 | /* For now, we only support one cs4270 device in the system. See the |
610 | * comment for cs4270_codec. | ||
611 | */ | ||
612 | if (cs4270_codec) { | ||
613 | dev_err(&i2c_client->dev, "ignoring CS4270 at addr %X\n", | ||
614 | i2c_client->addr); | ||
615 | dev_err(&i2c_client->dev, "only one per board allowed\n"); | ||
616 | /* Should we return something other than ENODEV here? */ | ||
617 | return -ENODEV; | ||
618 | } | ||
619 | |||
620 | /* Verify that we have a CS4270 */ | ||
621 | |||
622 | ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID); | ||
623 | if (ret < 0) { | ||
624 | dev_err(&i2c_client->dev, "failed to read i2c at addr %X\n", | ||
625 | i2c_client->addr); | ||
626 | return ret; | ||
627 | } | ||
628 | /* The top four bits of the chip ID should be 1100. */ | ||
629 | if ((ret & 0xF0) != 0xC0) { | ||
630 | dev_err(&i2c_client->dev, "device at addr %X is not a CS4270\n", | ||
631 | i2c_client->addr); | ||
632 | return -ENODEV; | ||
633 | } | ||
634 | |||
635 | dev_info(&i2c_client->dev, "found device at i2c address %X\n", | ||
636 | i2c_client->addr); | ||
637 | dev_info(&i2c_client->dev, "hardware revision %X\n", ret & 0xF); | ||
670 | 638 | ||
671 | /* Allocate enough space for the snd_soc_codec structure | 639 | /* Allocate enough space for the snd_soc_codec structure |
672 | and our private data together. */ | 640 | and our private data together. */ |
673 | codec = kzalloc(ALIGN(sizeof(struct snd_soc_codec), 4) + | 641 | cs4270 = kzalloc(sizeof(struct cs4270_private), GFP_KERNEL); |
674 | sizeof(struct cs4270_private), GFP_KERNEL); | 642 | if (!cs4270) { |
675 | if (!codec) { | 643 | dev_err(&i2c_client->dev, "could not allocate codec\n"); |
676 | printk(KERN_ERR "cs4270: Could not allocate codec structure\n"); | ||
677 | return -ENOMEM; | 644 | return -ENOMEM; |
678 | } | 645 | } |
646 | codec = &cs4270->codec; | ||
679 | 647 | ||
680 | mutex_init(&codec->mutex); | 648 | mutex_init(&codec->mutex); |
681 | INIT_LIST_HEAD(&codec->dapm_widgets); | 649 | INIT_LIST_HEAD(&codec->dapm_widgets); |
682 | INIT_LIST_HEAD(&codec->dapm_paths); | 650 | INIT_LIST_HEAD(&codec->dapm_paths); |
683 | 651 | ||
652 | codec->dev = &i2c_client->dev; | ||
684 | codec->name = "CS4270"; | 653 | codec->name = "CS4270"; |
685 | codec->owner = THIS_MODULE; | 654 | codec->owner = THIS_MODULE; |
686 | codec->dai = &cs4270_dai; | 655 | codec->dai = &cs4270_dai; |
687 | codec->num_dai = 1; | 656 | codec->num_dai = 1; |
688 | codec->private_data = (void *) codec + | 657 | codec->private_data = cs4270; |
689 | ALIGN(sizeof(struct snd_soc_codec), 4); | 658 | codec->control_data = i2c_client; |
690 | 659 | codec->read = cs4270_read_reg_cache; | |
691 | socdev->codec = codec; | 660 | codec->write = cs4270_i2c_write; |
661 | codec->reg_cache = cs4270->reg_cache; | ||
662 | codec->reg_cache_size = CS4270_NUMREGS; | ||
692 | 663 | ||
693 | /* Register PCMs */ | 664 | /* The I2C interface is set up, so pre-fill our register cache */ |
694 | 665 | ||
695 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | 666 | ret = cs4270_fill_cache(codec); |
696 | if (ret < 0) { | 667 | if (ret < 0) { |
697 | printk(KERN_ERR "cs4270: failed to create PCMs\n"); | 668 | dev_err(&i2c_client->dev, "failed to fill register cache\n"); |
698 | goto error_free_codec; | 669 | goto error_free_codec; |
699 | } | 670 | } |
700 | 671 | ||
701 | #ifdef USE_I2C | 672 | /* Disable auto-mute. This feature appears to be buggy. In some |
702 | cs4270_socdev = socdev; | 673 | * situations, auto-mute will not deactivate when it should, so we want |
674 | * this feature disabled by default. An application (e.g. alsactl) can | ||
675 | * re-enabled it by using the controls. | ||
676 | */ | ||
703 | 677 | ||
704 | ret = i2c_add_driver(&cs4270_i2c_driver); | 678 | reg = cs4270_read_reg_cache(codec, CS4270_MUTE); |
705 | if (ret) { | 679 | reg &= ~CS4270_MUTE_AUTO; |
706 | printk(KERN_ERR "cs4270: failed to attach driver"); | 680 | ret = cs4270_i2c_write(codec, CS4270_MUTE, reg); |
707 | goto error_free_pcms; | 681 | if (ret < 0) { |
682 | dev_err(&i2c_client->dev, "i2c write failed\n"); | ||
683 | return ret; | ||
708 | } | 684 | } |
709 | 685 | ||
710 | /* Did we find a CS4270 on the I2C bus? */ | 686 | /* Disable automatic volume control. The hardware enables, and it |
711 | if (codec->control_data) { | 687 | * causes volume change commands to be delayed, sometimes until after |
712 | /* Initialize codec ops */ | 688 | * playback has started. An application (e.g. alsactl) can |
713 | cs4270_dai.ops.hw_params = cs4270_hw_params; | 689 | * re-enabled it by using the controls. |
714 | cs4270_dai.ops.set_sysclk = cs4270_set_dai_sysclk; | 690 | */ |
715 | cs4270_dai.ops.set_fmt = cs4270_set_dai_fmt; | ||
716 | #ifdef CONFIG_SND_SOC_CS4270_HWMUTE | ||
717 | cs4270_dai.ops.digital_mute = cs4270_mute; | ||
718 | #endif | ||
719 | } else | ||
720 | printk(KERN_INFO "cs4270: no I2C device found, " | ||
721 | "using stand-alone mode\n"); | ||
722 | #else | ||
723 | printk(KERN_INFO "cs4270: I2C disabled, using stand-alone mode\n"); | ||
724 | #endif | ||
725 | 691 | ||
726 | ret = snd_soc_init_card(socdev); | 692 | reg = cs4270_read_reg_cache(codec, CS4270_TRANS); |
693 | reg &= ~(CS4270_TRANS_SOFT | CS4270_TRANS_ZERO); | ||
694 | ret = cs4270_i2c_write(codec, CS4270_TRANS, reg); | ||
727 | if (ret < 0) { | 695 | if (ret < 0) { |
728 | printk(KERN_ERR "cs4270: failed to register card\n"); | 696 | dev_err(&i2c_client->dev, "i2c write failed\n"); |
729 | goto error_del_driver; | 697 | return ret; |
730 | } | 698 | } |
731 | 699 | ||
732 | return 0; | 700 | /* Initialize the DAI. Normally, we'd prefer to have a kmalloc'd DAI |
701 | * structure for each CS4270 device, but the machine driver needs to | ||
702 | * have a pointer to the DAI structure, so for now it must be a global | ||
703 | * variable. | ||
704 | */ | ||
705 | cs4270_dai.dev = &i2c_client->dev; | ||
733 | 706 | ||
734 | error_del_driver: | 707 | /* Register the DAI. If all the other ASoC driver have already |
735 | #ifdef USE_I2C | 708 | * registered, then this will call our probe function, so |
736 | i2c_del_driver(&cs4270_i2c_driver); | 709 | * cs4270_codec needs to be ready. |
710 | */ | ||
711 | cs4270_codec = codec; | ||
712 | ret = snd_soc_register_dai(&cs4270_dai); | ||
713 | if (ret < 0) { | ||
714 | dev_err(&i2c_client->dev, "failed to register DAIe\n"); | ||
715 | goto error_free_codec; | ||
716 | } | ||
737 | 717 | ||
738 | error_free_pcms: | 718 | i2c_set_clientdata(i2c_client, cs4270); |
739 | #endif | 719 | |
740 | snd_soc_free_pcms(socdev); | 720 | return 0; |
741 | 721 | ||
742 | error_free_codec: | 722 | error_free_codec: |
743 | kfree(socdev->codec); | 723 | kfree(cs4270); |
744 | socdev->codec = NULL; | 724 | cs4270_codec = NULL; |
725 | cs4270_dai.dev = NULL; | ||
745 | 726 | ||
746 | return ret; | 727 | return ret; |
747 | } | 728 | } |
748 | 729 | ||
749 | static int cs4270_remove(struct platform_device *pdev) | 730 | /** |
731 | * cs4270_i2c_remove - remove an I2C device | ||
732 | * @i2c_client: the I2C client object | ||
733 | * | ||
734 | * This function is the counterpart to cs4270_i2c_probe(). | ||
735 | */ | ||
736 | static int cs4270_i2c_remove(struct i2c_client *i2c_client) | ||
750 | { | 737 | { |
751 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 738 | struct cs4270_private *cs4270 = i2c_get_clientdata(i2c_client); |
752 | |||
753 | snd_soc_free_pcms(socdev); | ||
754 | |||
755 | #ifdef USE_I2C | ||
756 | i2c_del_driver(&cs4270_i2c_driver); | ||
757 | #endif | ||
758 | 739 | ||
759 | kfree(socdev->codec); | 740 | kfree(cs4270); |
760 | socdev->codec = NULL; | 741 | cs4270_codec = NULL; |
742 | cs4270_dai.dev = NULL; | ||
761 | 743 | ||
762 | return 0; | 744 | return 0; |
763 | } | 745 | } |
764 | 746 | ||
765 | /* | 747 | /* |
748 | * cs4270_id - I2C device IDs supported by this driver | ||
749 | */ | ||
750 | static struct i2c_device_id cs4270_id[] = { | ||
751 | {"cs4270", 0}, | ||
752 | {} | ||
753 | }; | ||
754 | MODULE_DEVICE_TABLE(i2c, cs4270_id); | ||
755 | |||
756 | /* | ||
757 | * cs4270_i2c_driver - I2C device identification | ||
758 | * | ||
759 | * This structure tells the I2C subsystem how to identify and support a | ||
760 | * given I2C device type. | ||
761 | */ | ||
762 | static struct i2c_driver cs4270_i2c_driver = { | ||
763 | .driver = { | ||
764 | .name = "cs4270", | ||
765 | .owner = THIS_MODULE, | ||
766 | }, | ||
767 | .id_table = cs4270_id, | ||
768 | .probe = cs4270_i2c_probe, | ||
769 | .remove = cs4270_i2c_remove, | ||
770 | }; | ||
771 | |||
772 | /* | ||
766 | * ASoC codec device structure | 773 | * ASoC codec device structure |
767 | * | 774 | * |
768 | * Assign this variable to the codec_dev field of the machine driver's | 775 | * Assign this variable to the codec_dev field of the machine driver's |
@@ -776,13 +783,15 @@ EXPORT_SYMBOL_GPL(soc_codec_device_cs4270); | |||
776 | 783 | ||
777 | static int __init cs4270_init(void) | 784 | static int __init cs4270_init(void) |
778 | { | 785 | { |
779 | return snd_soc_register_dai(&cs4270_dai); | 786 | pr_info("Cirrus Logic CS4270 ALSA SoC Codec Driver\n"); |
787 | |||
788 | return i2c_add_driver(&cs4270_i2c_driver); | ||
780 | } | 789 | } |
781 | module_init(cs4270_init); | 790 | module_init(cs4270_init); |
782 | 791 | ||
783 | static void __exit cs4270_exit(void) | 792 | static void __exit cs4270_exit(void) |
784 | { | 793 | { |
785 | snd_soc_unregister_dai(&cs4270_dai); | 794 | i2c_del_driver(&cs4270_i2c_driver); |
786 | } | 795 | } |
787 | module_exit(cs4270_exit); | 796 | module_exit(cs4270_exit); |
788 | 797 | ||
diff --git a/sound/soc/codecs/pcm3008.c b/sound/soc/codecs/pcm3008.c index 9a3e67e5319c..5cda9e6b5a74 100644 --- a/sound/soc/codecs/pcm3008.c +++ b/sound/soc/codecs/pcm3008.c | |||
@@ -67,11 +67,11 @@ static int pcm3008_soc_probe(struct platform_device *pdev) | |||
67 | 67 | ||
68 | printk(KERN_INFO "PCM3008 SoC Audio Codec %s\n", PCM3008_VERSION); | 68 | printk(KERN_INFO "PCM3008 SoC Audio Codec %s\n", PCM3008_VERSION); |
69 | 69 | ||
70 | socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | 70 | socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); |
71 | if (!socdev->codec) | 71 | if (!socdev->card->codec) |
72 | return -ENOMEM; | 72 | return -ENOMEM; |
73 | 73 | ||
74 | codec = socdev->codec; | 74 | codec = socdev->card->codec; |
75 | mutex_init(&codec->mutex); | 75 | mutex_init(&codec->mutex); |
76 | 76 | ||
77 | codec->name = "PCM3008"; | 77 | codec->name = "PCM3008"; |
@@ -139,7 +139,7 @@ gpio_err: | |||
139 | card_err: | 139 | card_err: |
140 | snd_soc_free_pcms(socdev); | 140 | snd_soc_free_pcms(socdev); |
141 | pcm_err: | 141 | pcm_err: |
142 | kfree(socdev->codec); | 142 | kfree(socdev->card->codec); |
143 | 143 | ||
144 | return ret; | 144 | return ret; |
145 | } | 145 | } |
@@ -147,7 +147,7 @@ pcm_err: | |||
147 | static int pcm3008_soc_remove(struct platform_device *pdev) | 147 | static int pcm3008_soc_remove(struct platform_device *pdev) |
148 | { | 148 | { |
149 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 149 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
150 | struct snd_soc_codec *codec = socdev->codec; | 150 | struct snd_soc_codec *codec = socdev->card->codec; |
151 | struct pcm3008_setup_data *setup = socdev->codec_data; | 151 | struct pcm3008_setup_data *setup = socdev->codec_data; |
152 | 152 | ||
153 | if (!codec) | 153 | if (!codec) |
@@ -155,7 +155,7 @@ static int pcm3008_soc_remove(struct platform_device *pdev) | |||
155 | 155 | ||
156 | pcm3008_gpio_free(setup); | 156 | pcm3008_gpio_free(setup); |
157 | snd_soc_free_pcms(socdev); | 157 | snd_soc_free_pcms(socdev); |
158 | kfree(socdev->codec); | 158 | kfree(socdev->card->codec); |
159 | 159 | ||
160 | return 0; | 160 | return 0; |
161 | } | 161 | } |
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index cac373616768..87f606c76822 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c | |||
@@ -151,21 +151,6 @@ SOC_ENUM("Capture Source", ssm2602_enum[0]), | |||
151 | SOC_ENUM("Playback De-emphasis", ssm2602_enum[1]), | 151 | SOC_ENUM("Playback De-emphasis", ssm2602_enum[1]), |
152 | }; | 152 | }; |
153 | 153 | ||
154 | /* add non dapm controls */ | ||
155 | static int ssm2602_add_controls(struct snd_soc_codec *codec) | ||
156 | { | ||
157 | int err, i; | ||
158 | |||
159 | for (i = 0; i < ARRAY_SIZE(ssm2602_snd_controls); i++) { | ||
160 | err = snd_ctl_add(codec->card, | ||
161 | snd_soc_cnew(&ssm2602_snd_controls[i], codec, NULL)); | ||
162 | if (err < 0) | ||
163 | return err; | ||
164 | } | ||
165 | |||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | /* Output Mixer */ | 154 | /* Output Mixer */ |
170 | static const struct snd_kcontrol_new ssm2602_output_mixer_controls[] = { | 155 | static const struct snd_kcontrol_new ssm2602_output_mixer_controls[] = { |
171 | SOC_DAPM_SINGLE("Line Bypass Switch", SSM2602_APANA, 3, 1, 0), | 156 | SOC_DAPM_SINGLE("Line Bypass Switch", SSM2602_APANA, 3, 1, 0), |
@@ -291,7 +276,7 @@ static int ssm2602_hw_params(struct snd_pcm_substream *substream, | |||
291 | u16 srate; | 276 | u16 srate; |
292 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 277 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
293 | struct snd_soc_device *socdev = rtd->socdev; | 278 | struct snd_soc_device *socdev = rtd->socdev; |
294 | struct snd_soc_codec *codec = socdev->codec; | 279 | struct snd_soc_codec *codec = socdev->card->codec; |
295 | struct ssm2602_priv *ssm2602 = codec->private_data; | 280 | struct ssm2602_priv *ssm2602 = codec->private_data; |
296 | struct i2c_client *i2c = codec->control_data; | 281 | struct i2c_client *i2c = codec->control_data; |
297 | u16 iface = ssm2602_read_reg_cache(codec, SSM2602_IFACE) & 0xfff3; | 282 | u16 iface = ssm2602_read_reg_cache(codec, SSM2602_IFACE) & 0xfff3; |
@@ -336,7 +321,7 @@ static int ssm2602_startup(struct snd_pcm_substream *substream, | |||
336 | { | 321 | { |
337 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 322 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
338 | struct snd_soc_device *socdev = rtd->socdev; | 323 | struct snd_soc_device *socdev = rtd->socdev; |
339 | struct snd_soc_codec *codec = socdev->codec; | 324 | struct snd_soc_codec *codec = socdev->card->codec; |
340 | struct ssm2602_priv *ssm2602 = codec->private_data; | 325 | struct ssm2602_priv *ssm2602 = codec->private_data; |
341 | struct i2c_client *i2c = codec->control_data; | 326 | struct i2c_client *i2c = codec->control_data; |
342 | struct snd_pcm_runtime *master_runtime; | 327 | struct snd_pcm_runtime *master_runtime; |
@@ -373,7 +358,7 @@ static int ssm2602_pcm_prepare(struct snd_pcm_substream *substream, | |||
373 | { | 358 | { |
374 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 359 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
375 | struct snd_soc_device *socdev = rtd->socdev; | 360 | struct snd_soc_device *socdev = rtd->socdev; |
376 | struct snd_soc_codec *codec = socdev->codec; | 361 | struct snd_soc_codec *codec = socdev->card->codec; |
377 | /* set active */ | 362 | /* set active */ |
378 | ssm2602_write(codec, SSM2602_ACTIVE, ACTIVE_ACTIVATE_CODEC); | 363 | ssm2602_write(codec, SSM2602_ACTIVE, ACTIVE_ACTIVATE_CODEC); |
379 | 364 | ||
@@ -385,7 +370,7 @@ static void ssm2602_shutdown(struct snd_pcm_substream *substream, | |||
385 | { | 370 | { |
386 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 371 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
387 | struct snd_soc_device *socdev = rtd->socdev; | 372 | struct snd_soc_device *socdev = rtd->socdev; |
388 | struct snd_soc_codec *codec = socdev->codec; | 373 | struct snd_soc_codec *codec = socdev->card->codec; |
389 | struct ssm2602_priv *ssm2602 = codec->private_data; | 374 | struct ssm2602_priv *ssm2602 = codec->private_data; |
390 | /* deactivate */ | 375 | /* deactivate */ |
391 | if (!codec->active) | 376 | if (!codec->active) |
@@ -521,6 +506,16 @@ static int ssm2602_set_bias_level(struct snd_soc_codec *codec, | |||
521 | #define SSM2602_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | 506 | #define SSM2602_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ |
522 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) | 507 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) |
523 | 508 | ||
509 | static struct snd_soc_dai_ops ssm2602_dai_ops = { | ||
510 | .startup = ssm2602_startup, | ||
511 | .prepare = ssm2602_pcm_prepare, | ||
512 | .hw_params = ssm2602_hw_params, | ||
513 | .shutdown = ssm2602_shutdown, | ||
514 | .digital_mute = ssm2602_mute, | ||
515 | .set_sysclk = ssm2602_set_dai_sysclk, | ||
516 | .set_fmt = ssm2602_set_dai_fmt, | ||
517 | }; | ||
518 | |||
524 | struct snd_soc_dai ssm2602_dai = { | 519 | struct snd_soc_dai ssm2602_dai = { |
525 | .name = "SSM2602", | 520 | .name = "SSM2602", |
526 | .playback = { | 521 | .playback = { |
@@ -535,22 +530,14 @@ struct snd_soc_dai ssm2602_dai = { | |||
535 | .channels_max = 2, | 530 | .channels_max = 2, |
536 | .rates = SSM2602_RATES, | 531 | .rates = SSM2602_RATES, |
537 | .formats = SSM2602_FORMATS,}, | 532 | .formats = SSM2602_FORMATS,}, |
538 | .ops = { | 533 | .ops = &ssm2602_dai_ops, |
539 | .startup = ssm2602_startup, | ||
540 | .prepare = ssm2602_pcm_prepare, | ||
541 | .hw_params = ssm2602_hw_params, | ||
542 | .shutdown = ssm2602_shutdown, | ||
543 | .digital_mute = ssm2602_mute, | ||
544 | .set_sysclk = ssm2602_set_dai_sysclk, | ||
545 | .set_fmt = ssm2602_set_dai_fmt, | ||
546 | } | ||
547 | }; | 534 | }; |
548 | EXPORT_SYMBOL_GPL(ssm2602_dai); | 535 | EXPORT_SYMBOL_GPL(ssm2602_dai); |
549 | 536 | ||
550 | static int ssm2602_suspend(struct platform_device *pdev, pm_message_t state) | 537 | static int ssm2602_suspend(struct platform_device *pdev, pm_message_t state) |
551 | { | 538 | { |
552 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 539 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
553 | struct snd_soc_codec *codec = socdev->codec; | 540 | struct snd_soc_codec *codec = socdev->card->codec; |
554 | 541 | ||
555 | ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF); | 542 | ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF); |
556 | return 0; | 543 | return 0; |
@@ -559,7 +546,7 @@ static int ssm2602_suspend(struct platform_device *pdev, pm_message_t state) | |||
559 | static int ssm2602_resume(struct platform_device *pdev) | 546 | static int ssm2602_resume(struct platform_device *pdev) |
560 | { | 547 | { |
561 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 548 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
562 | struct snd_soc_codec *codec = socdev->codec; | 549 | struct snd_soc_codec *codec = socdev->card->codec; |
563 | int i; | 550 | int i; |
564 | u8 data[2]; | 551 | u8 data[2]; |
565 | u16 *cache = codec->reg_cache; | 552 | u16 *cache = codec->reg_cache; |
@@ -581,7 +568,7 @@ static int ssm2602_resume(struct platform_device *pdev) | |||
581 | */ | 568 | */ |
582 | static int ssm2602_init(struct snd_soc_device *socdev) | 569 | static int ssm2602_init(struct snd_soc_device *socdev) |
583 | { | 570 | { |
584 | struct snd_soc_codec *codec = socdev->codec; | 571 | struct snd_soc_codec *codec = socdev->card->codec; |
585 | int reg, ret = 0; | 572 | int reg, ret = 0; |
586 | 573 | ||
587 | codec->name = "SSM2602"; | 574 | codec->name = "SSM2602"; |
@@ -622,7 +609,8 @@ static int ssm2602_init(struct snd_soc_device *socdev) | |||
622 | APANA_ENABLE_MIC_BOOST); | 609 | APANA_ENABLE_MIC_BOOST); |
623 | ssm2602_write(codec, SSM2602_PWR, 0); | 610 | ssm2602_write(codec, SSM2602_PWR, 0); |
624 | 611 | ||
625 | ssm2602_add_controls(codec); | 612 | snd_soc_add_controls(codec, ssm2602_snd_controls, |
613 | ARRAY_SIZE(ssm2602_snd_controls)); | ||
626 | ssm2602_add_widgets(codec); | 614 | ssm2602_add_widgets(codec); |
627 | ret = snd_soc_init_card(socdev); | 615 | ret = snd_soc_init_card(socdev); |
628 | if (ret < 0) { | 616 | if (ret < 0) { |
@@ -653,7 +641,7 @@ static int ssm2602_i2c_probe(struct i2c_client *i2c, | |||
653 | const struct i2c_device_id *id) | 641 | const struct i2c_device_id *id) |
654 | { | 642 | { |
655 | struct snd_soc_device *socdev = ssm2602_socdev; | 643 | struct snd_soc_device *socdev = ssm2602_socdev; |
656 | struct snd_soc_codec *codec = socdev->codec; | 644 | struct snd_soc_codec *codec = socdev->card->codec; |
657 | int ret; | 645 | int ret; |
658 | 646 | ||
659 | i2c_set_clientdata(i2c, codec); | 647 | i2c_set_clientdata(i2c, codec); |
@@ -747,7 +735,7 @@ static int ssm2602_probe(struct platform_device *pdev) | |||
747 | } | 735 | } |
748 | 736 | ||
749 | codec->private_data = ssm2602; | 737 | codec->private_data = ssm2602; |
750 | socdev->codec = codec; | 738 | socdev->card->codec = codec; |
751 | mutex_init(&codec->mutex); | 739 | mutex_init(&codec->mutex); |
752 | INIT_LIST_HEAD(&codec->dapm_widgets); | 740 | INIT_LIST_HEAD(&codec->dapm_widgets); |
753 | INIT_LIST_HEAD(&codec->dapm_paths); | 741 | INIT_LIST_HEAD(&codec->dapm_paths); |
@@ -768,7 +756,7 @@ static int ssm2602_probe(struct platform_device *pdev) | |||
768 | static int ssm2602_remove(struct platform_device *pdev) | 756 | static int ssm2602_remove(struct platform_device *pdev) |
769 | { | 757 | { |
770 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 758 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
771 | struct snd_soc_codec *codec = socdev->codec; | 759 | struct snd_soc_codec *codec = socdev->card->codec; |
772 | 760 | ||
773 | if (codec->control_data) | 761 | if (codec->control_data) |
774 | ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF); | 762 | ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF); |
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index cfdea007c4cb..c3f4afb5d017 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c | |||
@@ -183,24 +183,6 @@ static const struct snd_kcontrol_new tlv320aic23_snd_controls[] = { | |||
183 | SOC_ENUM("Playback De-emphasis", tlv320aic23_deemph), | 183 | SOC_ENUM("Playback De-emphasis", tlv320aic23_deemph), |
184 | }; | 184 | }; |
185 | 185 | ||
186 | /* add non dapm controls */ | ||
187 | static int tlv320aic23_add_controls(struct snd_soc_codec *codec) | ||
188 | { | ||
189 | |||
190 | int err, i; | ||
191 | |||
192 | for (i = 0; i < ARRAY_SIZE(tlv320aic23_snd_controls); i++) { | ||
193 | err = snd_ctl_add(codec->card, | ||
194 | snd_soc_cnew(&tlv320aic23_snd_controls[i], | ||
195 | codec, NULL)); | ||
196 | if (err < 0) | ||
197 | return err; | ||
198 | } | ||
199 | |||
200 | return 0; | ||
201 | |||
202 | } | ||
203 | |||
204 | /* PGA Mixer controls for Line and Mic switch */ | 186 | /* PGA Mixer controls for Line and Mic switch */ |
205 | static const struct snd_kcontrol_new tlv320aic23_output_mixer_controls[] = { | 187 | static const struct snd_kcontrol_new tlv320aic23_output_mixer_controls[] = { |
206 | SOC_DAPM_SINGLE("Line Bypass Switch", TLV320AIC23_ANLG, 3, 1, 0), | 188 | SOC_DAPM_SINGLE("Line Bypass Switch", TLV320AIC23_ANLG, 3, 1, 0), |
@@ -423,7 +405,7 @@ static int tlv320aic23_hw_params(struct snd_pcm_substream *substream, | |||
423 | { | 405 | { |
424 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 406 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
425 | struct snd_soc_device *socdev = rtd->socdev; | 407 | struct snd_soc_device *socdev = rtd->socdev; |
426 | struct snd_soc_codec *codec = socdev->codec; | 408 | struct snd_soc_codec *codec = socdev->card->codec; |
427 | u16 iface_reg; | 409 | u16 iface_reg; |
428 | int ret; | 410 | int ret; |
429 | struct aic23 *aic23 = container_of(codec, struct aic23, codec); | 411 | struct aic23 *aic23 = container_of(codec, struct aic23, codec); |
@@ -471,7 +453,7 @@ static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream, | |||
471 | { | 453 | { |
472 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 454 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
473 | struct snd_soc_device *socdev = rtd->socdev; | 455 | struct snd_soc_device *socdev = rtd->socdev; |
474 | struct snd_soc_codec *codec = socdev->codec; | 456 | struct snd_soc_codec *codec = socdev->card->codec; |
475 | 457 | ||
476 | /* set active */ | 458 | /* set active */ |
477 | tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0001); | 459 | tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0001); |
@@ -484,7 +466,7 @@ static void tlv320aic23_shutdown(struct snd_pcm_substream *substream, | |||
484 | { | 466 | { |
485 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 467 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
486 | struct snd_soc_device *socdev = rtd->socdev; | 468 | struct snd_soc_device *socdev = rtd->socdev; |
487 | struct snd_soc_codec *codec = socdev->codec; | 469 | struct snd_soc_codec *codec = socdev->card->codec; |
488 | struct aic23 *aic23 = container_of(codec, struct aic23, codec); | 470 | struct aic23 *aic23 = container_of(codec, struct aic23, codec); |
489 | 471 | ||
490 | /* deactivate */ | 472 | /* deactivate */ |
@@ -598,6 +580,15 @@ static int tlv320aic23_set_bias_level(struct snd_soc_codec *codec, | |||
598 | #define AIC23_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ | 580 | #define AIC23_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ |
599 | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) | 581 | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) |
600 | 582 | ||
583 | static struct snd_soc_dai_ops tlv320aic23_dai_ops = { | ||
584 | .prepare = tlv320aic23_pcm_prepare, | ||
585 | .hw_params = tlv320aic23_hw_params, | ||
586 | .shutdown = tlv320aic23_shutdown, | ||
587 | .digital_mute = tlv320aic23_mute, | ||
588 | .set_fmt = tlv320aic23_set_dai_fmt, | ||
589 | .set_sysclk = tlv320aic23_set_dai_sysclk, | ||
590 | }; | ||
591 | |||
601 | struct snd_soc_dai tlv320aic23_dai = { | 592 | struct snd_soc_dai tlv320aic23_dai = { |
602 | .name = "tlv320aic23", | 593 | .name = "tlv320aic23", |
603 | .playback = { | 594 | .playback = { |
@@ -612,14 +603,7 @@ struct snd_soc_dai tlv320aic23_dai = { | |||
612 | .channels_max = 2, | 603 | .channels_max = 2, |
613 | .rates = AIC23_RATES, | 604 | .rates = AIC23_RATES, |
614 | .formats = AIC23_FORMATS,}, | 605 | .formats = AIC23_FORMATS,}, |
615 | .ops = { | 606 | .ops = &tlv320aic23_dai_ops, |
616 | .prepare = tlv320aic23_pcm_prepare, | ||
617 | .hw_params = tlv320aic23_hw_params, | ||
618 | .shutdown = tlv320aic23_shutdown, | ||
619 | .digital_mute = tlv320aic23_mute, | ||
620 | .set_fmt = tlv320aic23_set_dai_fmt, | ||
621 | .set_sysclk = tlv320aic23_set_dai_sysclk, | ||
622 | } | ||
623 | }; | 607 | }; |
624 | EXPORT_SYMBOL_GPL(tlv320aic23_dai); | 608 | EXPORT_SYMBOL_GPL(tlv320aic23_dai); |
625 | 609 | ||
@@ -627,7 +611,7 @@ static int tlv320aic23_suspend(struct platform_device *pdev, | |||
627 | pm_message_t state) | 611 | pm_message_t state) |
628 | { | 612 | { |
629 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 613 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
630 | struct snd_soc_codec *codec = socdev->codec; | 614 | struct snd_soc_codec *codec = socdev->card->codec; |
631 | 615 | ||
632 | tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0); | 616 | tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0); |
633 | tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF); | 617 | tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF); |
@@ -638,7 +622,7 @@ static int tlv320aic23_suspend(struct platform_device *pdev, | |||
638 | static int tlv320aic23_resume(struct platform_device *pdev) | 622 | static int tlv320aic23_resume(struct platform_device *pdev) |
639 | { | 623 | { |
640 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 624 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
641 | struct snd_soc_codec *codec = socdev->codec; | 625 | struct snd_soc_codec *codec = socdev->card->codec; |
642 | int i; | 626 | int i; |
643 | u16 reg; | 627 | u16 reg; |
644 | 628 | ||
@@ -660,7 +644,7 @@ static int tlv320aic23_resume(struct platform_device *pdev) | |||
660 | */ | 644 | */ |
661 | static int tlv320aic23_init(struct snd_soc_device *socdev) | 645 | static int tlv320aic23_init(struct snd_soc_device *socdev) |
662 | { | 646 | { |
663 | struct snd_soc_codec *codec = socdev->codec; | 647 | struct snd_soc_codec *codec = socdev->card->codec; |
664 | int ret = 0; | 648 | int ret = 0; |
665 | u16 reg; | 649 | u16 reg; |
666 | 650 | ||
@@ -718,7 +702,8 @@ static int tlv320aic23_init(struct snd_soc_device *socdev) | |||
718 | 702 | ||
719 | tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x1); | 703 | tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x1); |
720 | 704 | ||
721 | tlv320aic23_add_controls(codec); | 705 | snd_soc_add_controls(codec, tlv320aic23_snd_controls, |
706 | ARRAY_SIZE(tlv320aic23_snd_controls)); | ||
722 | tlv320aic23_add_widgets(codec); | 707 | tlv320aic23_add_widgets(codec); |
723 | ret = snd_soc_init_card(socdev); | 708 | ret = snd_soc_init_card(socdev); |
724 | if (ret < 0) { | 709 | if (ret < 0) { |
@@ -746,7 +731,7 @@ static int tlv320aic23_codec_probe(struct i2c_client *i2c, | |||
746 | const struct i2c_device_id *i2c_id) | 731 | const struct i2c_device_id *i2c_id) |
747 | { | 732 | { |
748 | struct snd_soc_device *socdev = tlv320aic23_socdev; | 733 | struct snd_soc_device *socdev = tlv320aic23_socdev; |
749 | struct snd_soc_codec *codec = socdev->codec; | 734 | struct snd_soc_codec *codec = socdev->card->codec; |
750 | int ret; | 735 | int ret; |
751 | 736 | ||
752 | if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | 737 | if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
@@ -804,7 +789,7 @@ static int tlv320aic23_probe(struct platform_device *pdev) | |||
804 | if (aic23 == NULL) | 789 | if (aic23 == NULL) |
805 | return -ENOMEM; | 790 | return -ENOMEM; |
806 | codec = &aic23->codec; | 791 | codec = &aic23->codec; |
807 | socdev->codec = codec; | 792 | socdev->card->codec = codec; |
808 | mutex_init(&codec->mutex); | 793 | mutex_init(&codec->mutex); |
809 | INIT_LIST_HEAD(&codec->dapm_widgets); | 794 | INIT_LIST_HEAD(&codec->dapm_widgets); |
810 | INIT_LIST_HEAD(&codec->dapm_paths); | 795 | INIT_LIST_HEAD(&codec->dapm_paths); |
@@ -823,7 +808,7 @@ static int tlv320aic23_probe(struct platform_device *pdev) | |||
823 | static int tlv320aic23_remove(struct platform_device *pdev) | 808 | static int tlv320aic23_remove(struct platform_device *pdev) |
824 | { | 809 | { |
825 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 810 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
826 | struct snd_soc_codec *codec = socdev->codec; | 811 | struct snd_soc_codec *codec = socdev->card->codec; |
827 | struct aic23 *aic23 = container_of(codec, struct aic23, codec); | 812 | struct aic23 *aic23 = container_of(codec, struct aic23, codec); |
828 | 813 | ||
829 | if (codec->control_data) | 814 | if (codec->control_data) |
diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c index 29f2f1a017fd..3387d9e736ea 100644 --- a/sound/soc/codecs/tlv320aic26.c +++ b/sound/soc/codecs/tlv320aic26.c | |||
@@ -130,7 +130,7 @@ static int aic26_hw_params(struct snd_pcm_substream *substream, | |||
130 | { | 130 | { |
131 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 131 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
132 | struct snd_soc_device *socdev = rtd->socdev; | 132 | struct snd_soc_device *socdev = rtd->socdev; |
133 | struct snd_soc_codec *codec = socdev->codec; | 133 | struct snd_soc_codec *codec = socdev->card->codec; |
134 | struct aic26 *aic26 = codec->private_data; | 134 | struct aic26 *aic26 = codec->private_data; |
135 | int fsref, divisor, wlen, pval, jval, dval, qval; | 135 | int fsref, divisor, wlen, pval, jval, dval, qval; |
136 | u16 reg; | 136 | u16 reg; |
@@ -270,6 +270,13 @@ static int aic26_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) | |||
270 | #define AIC26_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE |\ | 270 | #define AIC26_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE |\ |
271 | SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S32_BE) | 271 | SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S32_BE) |
272 | 272 | ||
273 | static struct snd_soc_dai_ops aic26_dai_ops = { | ||
274 | .hw_params = aic26_hw_params, | ||
275 | .digital_mute = aic26_mute, | ||
276 | .set_sysclk = aic26_set_sysclk, | ||
277 | .set_fmt = aic26_set_fmt, | ||
278 | }; | ||
279 | |||
273 | struct snd_soc_dai aic26_dai = { | 280 | struct snd_soc_dai aic26_dai = { |
274 | .name = "tlv320aic26", | 281 | .name = "tlv320aic26", |
275 | .playback = { | 282 | .playback = { |
@@ -286,12 +293,7 @@ struct snd_soc_dai aic26_dai = { | |||
286 | .rates = AIC26_RATES, | 293 | .rates = AIC26_RATES, |
287 | .formats = AIC26_FORMATS, | 294 | .formats = AIC26_FORMATS, |
288 | }, | 295 | }, |
289 | .ops = { | 296 | .ops = &aic26_dai_ops, |
290 | .hw_params = aic26_hw_params, | ||
291 | .digital_mute = aic26_mute, | ||
292 | .set_sysclk = aic26_set_sysclk, | ||
293 | .set_fmt = aic26_set_fmt, | ||
294 | }, | ||
295 | }; | 297 | }; |
296 | EXPORT_SYMBOL_GPL(aic26_dai); | 298 | EXPORT_SYMBOL_GPL(aic26_dai); |
297 | 299 | ||
@@ -322,9 +324,8 @@ static int aic26_probe(struct platform_device *pdev) | |||
322 | { | 324 | { |
323 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 325 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
324 | struct snd_soc_codec *codec; | 326 | struct snd_soc_codec *codec; |
325 | struct snd_kcontrol *kcontrol; | ||
326 | struct aic26 *aic26; | 327 | struct aic26 *aic26; |
327 | int i, ret, err; | 328 | int ret, err; |
328 | 329 | ||
329 | dev_info(&pdev->dev, "Probing AIC26 SoC CODEC driver\n"); | 330 | dev_info(&pdev->dev, "Probing AIC26 SoC CODEC driver\n"); |
330 | dev_dbg(&pdev->dev, "socdev=%p\n", socdev); | 331 | dev_dbg(&pdev->dev, "socdev=%p\n", socdev); |
@@ -338,7 +339,7 @@ static int aic26_probe(struct platform_device *pdev) | |||
338 | return -ENODEV; | 339 | return -ENODEV; |
339 | } | 340 | } |
340 | codec = &aic26->codec; | 341 | codec = &aic26->codec; |
341 | socdev->codec = codec; | 342 | socdev->card->codec = codec; |
342 | 343 | ||
343 | dev_dbg(&pdev->dev, "Registering PCMs, dev=%p, socdev->dev=%p\n", | 344 | dev_dbg(&pdev->dev, "Registering PCMs, dev=%p, socdev->dev=%p\n", |
344 | &pdev->dev, socdev->dev); | 345 | &pdev->dev, socdev->dev); |
@@ -351,11 +352,9 @@ static int aic26_probe(struct platform_device *pdev) | |||
351 | 352 | ||
352 | /* register controls */ | 353 | /* register controls */ |
353 | dev_dbg(&pdev->dev, "Registering controls\n"); | 354 | dev_dbg(&pdev->dev, "Registering controls\n"); |
354 | for (i = 0; i < ARRAY_SIZE(aic26_snd_controls); i++) { | 355 | err = snd_soc_add_controls(codec, aic26_snd_controls, |
355 | kcontrol = snd_soc_cnew(&aic26_snd_controls[i], codec, NULL); | 356 | ARRAY_SIZE(aic26_snd_controls)); |
356 | err = snd_ctl_add(codec->card, kcontrol); | 357 | WARN_ON(err < 0); |
357 | WARN_ON(err < 0); | ||
358 | } | ||
359 | 358 | ||
360 | /* CODEC is setup, we can register the card now */ | 359 | /* CODEC is setup, we can register the card now */ |
361 | dev_dbg(&pdev->dev, "Registering card\n"); | 360 | dev_dbg(&pdev->dev, "Registering card\n"); |
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index aea0cb72d80a..ab099f482487 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include <sound/soc.h> | 45 | #include <sound/soc.h> |
46 | #include <sound/soc-dapm.h> | 46 | #include <sound/soc-dapm.h> |
47 | #include <sound/initval.h> | 47 | #include <sound/initval.h> |
48 | #include <sound/tlv.h> | ||
48 | 49 | ||
49 | #include "tlv320aic3x.h" | 50 | #include "tlv320aic3x.h" |
50 | 51 | ||
@@ -250,56 +251,86 @@ static const struct soc_enum aic3x_enum[] = { | |||
250 | SOC_ENUM_DOUBLE(AIC3X_CODEC_DFILT_CTRL, 6, 4, 4, aic3x_adc_hpf), | 251 | SOC_ENUM_DOUBLE(AIC3X_CODEC_DFILT_CTRL, 6, 4, 4, aic3x_adc_hpf), |
251 | }; | 252 | }; |
252 | 253 | ||
254 | /* | ||
255 | * DAC digital volumes. From -63.5 to 0 dB in 0.5 dB steps | ||
256 | */ | ||
257 | static DECLARE_TLV_DB_SCALE(dac_tlv, -6350, 50, 0); | ||
258 | /* ADC PGA gain volumes. From 0 to 59.5 dB in 0.5 dB steps */ | ||
259 | static DECLARE_TLV_DB_SCALE(adc_tlv, 0, 50, 0); | ||
260 | /* | ||
261 | * Output stage volumes. From -78.3 to 0 dB. Muted below -78.3 dB. | ||
262 | * Step size is approximately 0.5 dB over most of the scale but increasing | ||
263 | * near the very low levels. | ||
264 | * Define dB scale so that it is mostly correct for range about -55 to 0 dB | ||
265 | * but having increasing dB difference below that (and where it doesn't count | ||
266 | * so much). This setting shows -50 dB (actual is -50.3 dB) for register | ||
267 | * value 100 and -58.5 dB (actual is -78.3 dB) for register value 117. | ||
268 | */ | ||
269 | static DECLARE_TLV_DB_SCALE(output_stage_tlv, -5900, 50, 1); | ||
270 | |||
253 | static const struct snd_kcontrol_new aic3x_snd_controls[] = { | 271 | static const struct snd_kcontrol_new aic3x_snd_controls[] = { |
254 | /* Output */ | 272 | /* Output */ |
255 | SOC_DOUBLE_R("PCM Playback Volume", LDAC_VOL, RDAC_VOL, 0, 0x7f, 1), | 273 | SOC_DOUBLE_R_TLV("PCM Playback Volume", |
274 | LDAC_VOL, RDAC_VOL, 0, 0x7f, 1, dac_tlv), | ||
256 | 275 | ||
257 | SOC_DOUBLE_R("Line DAC Playback Volume", DACL1_2_LLOPM_VOL, | 276 | SOC_DOUBLE_R_TLV("Line DAC Playback Volume", |
258 | DACR1_2_RLOPM_VOL, 0, 0x7f, 1), | 277 | DACL1_2_LLOPM_VOL, DACR1_2_RLOPM_VOL, |
278 | 0, 118, 1, output_stage_tlv), | ||
259 | SOC_SINGLE("LineL Playback Switch", LLOPM_CTRL, 3, 0x01, 0), | 279 | SOC_SINGLE("LineL Playback Switch", LLOPM_CTRL, 3, 0x01, 0), |
260 | SOC_SINGLE("LineR Playback Switch", RLOPM_CTRL, 3, 0x01, 0), | 280 | SOC_SINGLE("LineR Playback Switch", RLOPM_CTRL, 3, 0x01, 0), |
261 | SOC_DOUBLE_R("LineL DAC Playback Volume", DACL1_2_LLOPM_VOL, | 281 | SOC_DOUBLE_R_TLV("LineL DAC Playback Volume", |
262 | DACR1_2_LLOPM_VOL, 0, 0x7f, 1), | 282 | DACL1_2_LLOPM_VOL, DACR1_2_LLOPM_VOL, |
263 | SOC_SINGLE("LineL Left PGA Bypass Playback Volume", PGAL_2_LLOPM_VOL, | 283 | 0, 118, 1, output_stage_tlv), |
264 | 0, 0x7f, 1), | 284 | SOC_SINGLE_TLV("LineL Left PGA Bypass Playback Volume", |
265 | SOC_SINGLE("LineR Right PGA Bypass Playback Volume", PGAR_2_RLOPM_VOL, | 285 | PGAL_2_LLOPM_VOL, 0, 118, 1, output_stage_tlv), |
266 | 0, 0x7f, 1), | 286 | SOC_SINGLE_TLV("LineR Right PGA Bypass Playback Volume", |
267 | SOC_DOUBLE_R("LineL Line2 Bypass Playback Volume", LINE2L_2_LLOPM_VOL, | 287 | PGAR_2_RLOPM_VOL, 0, 118, 1, output_stage_tlv), |
268 | LINE2R_2_LLOPM_VOL, 0, 0x7f, 1), | 288 | SOC_DOUBLE_R_TLV("LineL Line2 Bypass Playback Volume", |
269 | SOC_DOUBLE_R("LineR Line2 Bypass Playback Volume", LINE2L_2_RLOPM_VOL, | 289 | LINE2L_2_LLOPM_VOL, LINE2R_2_LLOPM_VOL, |
270 | LINE2R_2_RLOPM_VOL, 0, 0x7f, 1), | 290 | 0, 118, 1, output_stage_tlv), |
271 | 291 | SOC_DOUBLE_R_TLV("LineR Line2 Bypass Playback Volume", | |
272 | SOC_DOUBLE_R("Mono DAC Playback Volume", DACL1_2_MONOLOPM_VOL, | 292 | LINE2L_2_RLOPM_VOL, LINE2R_2_RLOPM_VOL, |
273 | DACR1_2_MONOLOPM_VOL, 0, 0x7f, 1), | 293 | 0, 118, 1, output_stage_tlv), |
294 | |||
295 | SOC_DOUBLE_R_TLV("Mono DAC Playback Volume", | ||
296 | DACL1_2_MONOLOPM_VOL, DACR1_2_MONOLOPM_VOL, | ||
297 | 0, 118, 1, output_stage_tlv), | ||
274 | SOC_SINGLE("Mono DAC Playback Switch", MONOLOPM_CTRL, 3, 0x01, 0), | 298 | SOC_SINGLE("Mono DAC Playback Switch", MONOLOPM_CTRL, 3, 0x01, 0), |
275 | SOC_DOUBLE_R("Mono PGA Bypass Playback Volume", PGAL_2_MONOLOPM_VOL, | 299 | SOC_DOUBLE_R_TLV("Mono PGA Bypass Playback Volume", |
276 | PGAR_2_MONOLOPM_VOL, 0, 0x7f, 1), | 300 | PGAL_2_MONOLOPM_VOL, PGAR_2_MONOLOPM_VOL, |
277 | SOC_DOUBLE_R("Mono Line2 Bypass Playback Volume", LINE2L_2_MONOLOPM_VOL, | 301 | 0, 118, 1, output_stage_tlv), |
278 | LINE2R_2_MONOLOPM_VOL, 0, 0x7f, 1), | 302 | SOC_DOUBLE_R_TLV("Mono Line2 Bypass Playback Volume", |
279 | 303 | LINE2L_2_MONOLOPM_VOL, LINE2R_2_MONOLOPM_VOL, | |
280 | SOC_DOUBLE_R("HP DAC Playback Volume", DACL1_2_HPLOUT_VOL, | 304 | 0, 118, 1, output_stage_tlv), |
281 | DACR1_2_HPROUT_VOL, 0, 0x7f, 1), | 305 | |
306 | SOC_DOUBLE_R_TLV("HP DAC Playback Volume", | ||
307 | DACL1_2_HPLOUT_VOL, DACR1_2_HPROUT_VOL, | ||
308 | 0, 118, 1, output_stage_tlv), | ||
282 | SOC_DOUBLE_R("HP DAC Playback Switch", HPLOUT_CTRL, HPROUT_CTRL, 3, | 309 | SOC_DOUBLE_R("HP DAC Playback Switch", HPLOUT_CTRL, HPROUT_CTRL, 3, |
283 | 0x01, 0), | 310 | 0x01, 0), |
284 | SOC_DOUBLE_R("HP Right PGA Bypass Playback Volume", PGAR_2_HPLOUT_VOL, | 311 | SOC_DOUBLE_R_TLV("HP Right PGA Bypass Playback Volume", |
285 | PGAR_2_HPROUT_VOL, 0, 0x7f, 1), | 312 | PGAR_2_HPLOUT_VOL, PGAR_2_HPROUT_VOL, |
286 | SOC_SINGLE("HPL PGA Bypass Playback Volume", PGAL_2_HPLOUT_VOL, | 313 | 0, 118, 1, output_stage_tlv), |
287 | 0, 0x7f, 1), | 314 | SOC_SINGLE_TLV("HPL PGA Bypass Playback Volume", |
288 | SOC_SINGLE("HPR PGA Bypass Playback Volume", PGAL_2_HPROUT_VOL, | 315 | PGAL_2_HPLOUT_VOL, 0, 118, 1, output_stage_tlv), |
289 | 0, 0x7f, 1), | 316 | SOC_SINGLE_TLV("HPR PGA Bypass Playback Volume", |
290 | SOC_DOUBLE_R("HP Line2 Bypass Playback Volume", LINE2L_2_HPLOUT_VOL, | 317 | PGAL_2_HPROUT_VOL, 0, 118, 1, output_stage_tlv), |
291 | LINE2R_2_HPROUT_VOL, 0, 0x7f, 1), | 318 | SOC_DOUBLE_R_TLV("HP Line2 Bypass Playback Volume", |
292 | 319 | LINE2L_2_HPLOUT_VOL, LINE2R_2_HPROUT_VOL, | |
293 | SOC_DOUBLE_R("HPCOM DAC Playback Volume", DACL1_2_HPLCOM_VOL, | 320 | 0, 118, 1, output_stage_tlv), |
294 | DACR1_2_HPRCOM_VOL, 0, 0x7f, 1), | 321 | |
322 | SOC_DOUBLE_R_TLV("HPCOM DAC Playback Volume", | ||
323 | DACL1_2_HPLCOM_VOL, DACR1_2_HPRCOM_VOL, | ||
324 | 0, 118, 1, output_stage_tlv), | ||
295 | SOC_DOUBLE_R("HPCOM DAC Playback Switch", HPLCOM_CTRL, HPRCOM_CTRL, 3, | 325 | SOC_DOUBLE_R("HPCOM DAC Playback Switch", HPLCOM_CTRL, HPRCOM_CTRL, 3, |
296 | 0x01, 0), | 326 | 0x01, 0), |
297 | SOC_SINGLE("HPLCOM PGA Bypass Playback Volume", PGAL_2_HPLCOM_VOL, | 327 | SOC_SINGLE_TLV("HPLCOM PGA Bypass Playback Volume", |
298 | 0, 0x7f, 1), | 328 | PGAL_2_HPLCOM_VOL, 0, 118, 1, output_stage_tlv), |
299 | SOC_SINGLE("HPRCOM PGA Bypass Playback Volume", PGAL_2_HPRCOM_VOL, | 329 | SOC_SINGLE_TLV("HPRCOM PGA Bypass Playback Volume", |
300 | 0, 0x7f, 1), | 330 | PGAL_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv), |
301 | SOC_DOUBLE_R("HPCOM Line2 Bypass Playback Volume", LINE2L_2_HPLCOM_VOL, | 331 | SOC_DOUBLE_R_TLV("HPCOM Line2 Bypass Playback Volume", |
302 | LINE2R_2_HPRCOM_VOL, 0, 0x7f, 1), | 332 | LINE2L_2_HPLCOM_VOL, LINE2R_2_HPRCOM_VOL, |
333 | 0, 118, 1, output_stage_tlv), | ||
303 | 334 | ||
304 | /* | 335 | /* |
305 | * Note: enable Automatic input Gain Controller with care. It can | 336 | * Note: enable Automatic input Gain Controller with care. It can |
@@ -308,28 +339,13 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = { | |||
308 | SOC_DOUBLE_R("AGC Switch", LAGC_CTRL_A, RAGC_CTRL_A, 7, 0x01, 0), | 339 | SOC_DOUBLE_R("AGC Switch", LAGC_CTRL_A, RAGC_CTRL_A, 7, 0x01, 0), |
309 | 340 | ||
310 | /* Input */ | 341 | /* Input */ |
311 | SOC_DOUBLE_R("PGA Capture Volume", LADC_VOL, RADC_VOL, 0, 0x7f, 0), | 342 | SOC_DOUBLE_R_TLV("PGA Capture Volume", LADC_VOL, RADC_VOL, |
343 | 0, 119, 0, adc_tlv), | ||
312 | SOC_DOUBLE_R("PGA Capture Switch", LADC_VOL, RADC_VOL, 7, 0x01, 1), | 344 | SOC_DOUBLE_R("PGA Capture Switch", LADC_VOL, RADC_VOL, 7, 0x01, 1), |
313 | 345 | ||
314 | SOC_ENUM("ADC HPF Cut-off", aic3x_enum[ADC_HPF_ENUM]), | 346 | SOC_ENUM("ADC HPF Cut-off", aic3x_enum[ADC_HPF_ENUM]), |
315 | }; | 347 | }; |
316 | 348 | ||
317 | /* add non dapm controls */ | ||
318 | static int aic3x_add_controls(struct snd_soc_codec *codec) | ||
319 | { | ||
320 | int err, i; | ||
321 | |||
322 | for (i = 0; i < ARRAY_SIZE(aic3x_snd_controls); i++) { | ||
323 | err = snd_ctl_add(codec->card, | ||
324 | snd_soc_cnew(&aic3x_snd_controls[i], | ||
325 | codec, NULL)); | ||
326 | if (err < 0) | ||
327 | return err; | ||
328 | } | ||
329 | |||
330 | return 0; | ||
331 | } | ||
332 | |||
333 | /* Left DAC Mux */ | 349 | /* Left DAC Mux */ |
334 | static const struct snd_kcontrol_new aic3x_left_dac_mux_controls = | 350 | static const struct snd_kcontrol_new aic3x_left_dac_mux_controls = |
335 | SOC_DAPM_ENUM("Route", aic3x_enum[LDAC_ENUM]); | 351 | SOC_DAPM_ENUM("Route", aic3x_enum[LDAC_ENUM]); |
@@ -746,7 +762,7 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream, | |||
746 | { | 762 | { |
747 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 763 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
748 | struct snd_soc_device *socdev = rtd->socdev; | 764 | struct snd_soc_device *socdev = rtd->socdev; |
749 | struct snd_soc_codec *codec = socdev->codec; | 765 | struct snd_soc_codec *codec = socdev->card->codec; |
750 | struct aic3x_priv *aic3x = codec->private_data; | 766 | struct aic3x_priv *aic3x = codec->private_data; |
751 | int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0; | 767 | int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0; |
752 | u8 data, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1; | 768 | u8 data, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1; |
@@ -1072,6 +1088,13 @@ EXPORT_SYMBOL_GPL(aic3x_button_pressed); | |||
1072 | #define AIC3X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ | 1088 | #define AIC3X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ |
1073 | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) | 1089 | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) |
1074 | 1090 | ||
1091 | static struct snd_soc_dai_ops aic3x_dai_ops = { | ||
1092 | .hw_params = aic3x_hw_params, | ||
1093 | .digital_mute = aic3x_mute, | ||
1094 | .set_sysclk = aic3x_set_dai_sysclk, | ||
1095 | .set_fmt = aic3x_set_dai_fmt, | ||
1096 | }; | ||
1097 | |||
1075 | struct snd_soc_dai aic3x_dai = { | 1098 | struct snd_soc_dai aic3x_dai = { |
1076 | .name = "tlv320aic3x", | 1099 | .name = "tlv320aic3x", |
1077 | .playback = { | 1100 | .playback = { |
@@ -1086,19 +1109,14 @@ struct snd_soc_dai aic3x_dai = { | |||
1086 | .channels_max = 2, | 1109 | .channels_max = 2, |
1087 | .rates = AIC3X_RATES, | 1110 | .rates = AIC3X_RATES, |
1088 | .formats = AIC3X_FORMATS,}, | 1111 | .formats = AIC3X_FORMATS,}, |
1089 | .ops = { | 1112 | .ops = &aic3x_dai_ops, |
1090 | .hw_params = aic3x_hw_params, | ||
1091 | .digital_mute = aic3x_mute, | ||
1092 | .set_sysclk = aic3x_set_dai_sysclk, | ||
1093 | .set_fmt = aic3x_set_dai_fmt, | ||
1094 | } | ||
1095 | }; | 1113 | }; |
1096 | EXPORT_SYMBOL_GPL(aic3x_dai); | 1114 | EXPORT_SYMBOL_GPL(aic3x_dai); |
1097 | 1115 | ||
1098 | static int aic3x_suspend(struct platform_device *pdev, pm_message_t state) | 1116 | static int aic3x_suspend(struct platform_device *pdev, pm_message_t state) |
1099 | { | 1117 | { |
1100 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1118 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
1101 | struct snd_soc_codec *codec = socdev->codec; | 1119 | struct snd_soc_codec *codec = socdev->card->codec; |
1102 | 1120 | ||
1103 | aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1121 | aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1104 | 1122 | ||
@@ -1108,7 +1126,7 @@ static int aic3x_suspend(struct platform_device *pdev, pm_message_t state) | |||
1108 | static int aic3x_resume(struct platform_device *pdev) | 1126 | static int aic3x_resume(struct platform_device *pdev) |
1109 | { | 1127 | { |
1110 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1128 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
1111 | struct snd_soc_codec *codec = socdev->codec; | 1129 | struct snd_soc_codec *codec = socdev->card->codec; |
1112 | int i; | 1130 | int i; |
1113 | u8 data[2]; | 1131 | u8 data[2]; |
1114 | u8 *cache = codec->reg_cache; | 1132 | u8 *cache = codec->reg_cache; |
@@ -1131,7 +1149,7 @@ static int aic3x_resume(struct platform_device *pdev) | |||
1131 | */ | 1149 | */ |
1132 | static int aic3x_init(struct snd_soc_device *socdev) | 1150 | static int aic3x_init(struct snd_soc_device *socdev) |
1133 | { | 1151 | { |
1134 | struct snd_soc_codec *codec = socdev->codec; | 1152 | struct snd_soc_codec *codec = socdev->card->codec; |
1135 | struct aic3x_setup_data *setup = socdev->codec_data; | 1153 | struct aic3x_setup_data *setup = socdev->codec_data; |
1136 | int reg, ret = 0; | 1154 | int reg, ret = 0; |
1137 | 1155 | ||
@@ -1227,7 +1245,8 @@ static int aic3x_init(struct snd_soc_device *socdev) | |||
1227 | aic3x_write(codec, AIC3X_GPIO1_REG, (setup->gpio_func[0] & 0xf) << 4); | 1245 | aic3x_write(codec, AIC3X_GPIO1_REG, (setup->gpio_func[0] & 0xf) << 4); |
1228 | aic3x_write(codec, AIC3X_GPIO2_REG, (setup->gpio_func[1] & 0xf) << 4); | 1246 | aic3x_write(codec, AIC3X_GPIO2_REG, (setup->gpio_func[1] & 0xf) << 4); |
1229 | 1247 | ||
1230 | aic3x_add_controls(codec); | 1248 | snd_soc_add_controls(codec, aic3x_snd_controls, |
1249 | ARRAY_SIZE(aic3x_snd_controls)); | ||
1231 | aic3x_add_widgets(codec); | 1250 | aic3x_add_widgets(codec); |
1232 | ret = snd_soc_init_card(socdev); | 1251 | ret = snd_soc_init_card(socdev); |
1233 | if (ret < 0) { | 1252 | if (ret < 0) { |
@@ -1261,7 +1280,7 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, | |||
1261 | const struct i2c_device_id *id) | 1280 | const struct i2c_device_id *id) |
1262 | { | 1281 | { |
1263 | struct snd_soc_device *socdev = aic3x_socdev; | 1282 | struct snd_soc_device *socdev = aic3x_socdev; |
1264 | struct snd_soc_codec *codec = socdev->codec; | 1283 | struct snd_soc_codec *codec = socdev->card->codec; |
1265 | int ret; | 1284 | int ret; |
1266 | 1285 | ||
1267 | i2c_set_clientdata(i2c, codec); | 1286 | i2c_set_clientdata(i2c, codec); |
@@ -1366,7 +1385,7 @@ static int aic3x_probe(struct platform_device *pdev) | |||
1366 | } | 1385 | } |
1367 | 1386 | ||
1368 | codec->private_data = aic3x; | 1387 | codec->private_data = aic3x; |
1369 | socdev->codec = codec; | 1388 | socdev->card->codec = codec; |
1370 | mutex_init(&codec->mutex); | 1389 | mutex_init(&codec->mutex); |
1371 | INIT_LIST_HEAD(&codec->dapm_widgets); | 1390 | INIT_LIST_HEAD(&codec->dapm_widgets); |
1372 | INIT_LIST_HEAD(&codec->dapm_paths); | 1391 | INIT_LIST_HEAD(&codec->dapm_paths); |
@@ -1392,7 +1411,7 @@ static int aic3x_probe(struct platform_device *pdev) | |||
1392 | static int aic3x_remove(struct platform_device *pdev) | 1411 | static int aic3x_remove(struct platform_device *pdev) |
1393 | { | 1412 | { |
1394 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1413 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
1395 | struct snd_soc_codec *codec = socdev->codec; | 1414 | struct snd_soc_codec *codec = socdev->card->codec; |
1396 | 1415 | ||
1397 | /* power down chip */ | 1416 | /* power down chip */ |
1398 | if (codec->control_data) | 1417 | if (codec->control_data) |
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index ea370a4f86d5..97738e2ece04 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c | |||
@@ -42,7 +42,7 @@ | |||
42 | */ | 42 | */ |
43 | static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = { | 43 | static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = { |
44 | 0x00, /* this register not used */ | 44 | 0x00, /* this register not used */ |
45 | 0x93, /* REG_CODEC_MODE (0x1) */ | 45 | 0x91, /* REG_CODEC_MODE (0x1) */ |
46 | 0xc3, /* REG_OPTION (0x2) */ | 46 | 0xc3, /* REG_OPTION (0x2) */ |
47 | 0x00, /* REG_UNKNOWN (0x3) */ | 47 | 0x00, /* REG_UNKNOWN (0x3) */ |
48 | 0x00, /* REG_MICBIAS_CTL (0x4) */ | 48 | 0x00, /* REG_MICBIAS_CTL (0x4) */ |
@@ -117,6 +117,13 @@ static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = { | |||
117 | 0x00, /* REG_MISC_SET_2 (0x49) */ | 117 | 0x00, /* REG_MISC_SET_2 (0x49) */ |
118 | }; | 118 | }; |
119 | 119 | ||
120 | /* codec private data */ | ||
121 | struct twl4030_priv { | ||
122 | unsigned int bypass_state; | ||
123 | unsigned int codec_powered; | ||
124 | unsigned int codec_muted; | ||
125 | }; | ||
126 | |||
120 | /* | 127 | /* |
121 | * read twl4030 register cache | 128 | * read twl4030 register cache |
122 | */ | 129 | */ |
@@ -125,6 +132,9 @@ static inline unsigned int twl4030_read_reg_cache(struct snd_soc_codec *codec, | |||
125 | { | 132 | { |
126 | u8 *cache = codec->reg_cache; | 133 | u8 *cache = codec->reg_cache; |
127 | 134 | ||
135 | if (reg >= TWL4030_CACHEREGNUM) | ||
136 | return -EIO; | ||
137 | |||
128 | return cache[reg]; | 138 | return cache[reg]; |
129 | } | 139 | } |
130 | 140 | ||
@@ -151,26 +161,22 @@ static int twl4030_write(struct snd_soc_codec *codec, | |||
151 | return twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, value, reg); | 161 | return twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, value, reg); |
152 | } | 162 | } |
153 | 163 | ||
154 | static void twl4030_clear_codecpdz(struct snd_soc_codec *codec) | 164 | static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable) |
155 | { | 165 | { |
166 | struct twl4030_priv *twl4030 = codec->private_data; | ||
156 | u8 mode; | 167 | u8 mode; |
157 | 168 | ||
158 | mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE); | 169 | if (enable == twl4030->codec_powered) |
159 | twl4030_write(codec, TWL4030_REG_CODEC_MODE, | 170 | return; |
160 | mode & ~TWL4030_CODECPDZ); | ||
161 | |||
162 | /* REVISIT: this delay is present in TI sample drivers */ | ||
163 | /* but there seems to be no TRM requirement for it */ | ||
164 | udelay(10); | ||
165 | } | ||
166 | |||
167 | static void twl4030_set_codecpdz(struct snd_soc_codec *codec) | ||
168 | { | ||
169 | u8 mode; | ||
170 | 171 | ||
171 | mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE); | 172 | mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE); |
172 | twl4030_write(codec, TWL4030_REG_CODEC_MODE, | 173 | if (enable) |
173 | mode | TWL4030_CODECPDZ); | 174 | mode |= TWL4030_CODECPDZ; |
175 | else | ||
176 | mode &= ~TWL4030_CODECPDZ; | ||
177 | |||
178 | twl4030_write(codec, TWL4030_REG_CODEC_MODE, mode); | ||
179 | twl4030->codec_powered = enable; | ||
174 | 180 | ||
175 | /* REVISIT: this delay is present in TI sample drivers */ | 181 | /* REVISIT: this delay is present in TI sample drivers */ |
176 | /* but there seems to be no TRM requirement for it */ | 182 | /* but there seems to be no TRM requirement for it */ |
@@ -182,7 +188,7 @@ static void twl4030_init_chip(struct snd_soc_codec *codec) | |||
182 | int i; | 188 | int i; |
183 | 189 | ||
184 | /* clear CODECPDZ prior to setting register defaults */ | 190 | /* clear CODECPDZ prior to setting register defaults */ |
185 | twl4030_clear_codecpdz(codec); | 191 | twl4030_codec_enable(codec, 0); |
186 | 192 | ||
187 | /* set all audio section registers to reasonable defaults */ | 193 | /* set all audio section registers to reasonable defaults */ |
188 | for (i = TWL4030_REG_OPTION; i <= TWL4030_REG_MISC_SET_2; i++) | 194 | for (i = TWL4030_REG_OPTION; i <= TWL4030_REG_MISC_SET_2; i++) |
@@ -190,6 +196,122 @@ static void twl4030_init_chip(struct snd_soc_codec *codec) | |||
190 | 196 | ||
191 | } | 197 | } |
192 | 198 | ||
199 | static void twl4030_codec_mute(struct snd_soc_codec *codec, int mute) | ||
200 | { | ||
201 | struct twl4030_priv *twl4030 = codec->private_data; | ||
202 | u8 reg_val; | ||
203 | |||
204 | if (mute == twl4030->codec_muted) | ||
205 | return; | ||
206 | |||
207 | if (mute) { | ||
208 | /* Bypass the reg_cache and mute the volumes | ||
209 | * Headset mute is done in it's own event handler | ||
210 | * Things to mute: Earpiece, PreDrivL/R, CarkitL/R | ||
211 | */ | ||
212 | reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_EAR_CTL); | ||
213 | twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, | ||
214 | reg_val & (~TWL4030_EAR_GAIN), | ||
215 | TWL4030_REG_EAR_CTL); | ||
216 | |||
217 | reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_PREDL_CTL); | ||
218 | twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, | ||
219 | reg_val & (~TWL4030_PREDL_GAIN), | ||
220 | TWL4030_REG_PREDL_CTL); | ||
221 | reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_PREDR_CTL); | ||
222 | twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, | ||
223 | reg_val & (~TWL4030_PREDR_GAIN), | ||
224 | TWL4030_REG_PREDL_CTL); | ||
225 | |||
226 | reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_PRECKL_CTL); | ||
227 | twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, | ||
228 | reg_val & (~TWL4030_PRECKL_GAIN), | ||
229 | TWL4030_REG_PRECKL_CTL); | ||
230 | reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_PRECKR_CTL); | ||
231 | twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, | ||
232 | reg_val & (~TWL4030_PRECKL_GAIN), | ||
233 | TWL4030_REG_PRECKR_CTL); | ||
234 | |||
235 | /* Disable PLL */ | ||
236 | reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_APLL_CTL); | ||
237 | reg_val &= ~TWL4030_APLL_EN; | ||
238 | twl4030_write(codec, TWL4030_REG_APLL_CTL, reg_val); | ||
239 | } else { | ||
240 | /* Restore the volumes | ||
241 | * Headset mute is done in it's own event handler | ||
242 | * Things to restore: Earpiece, PreDrivL/R, CarkitL/R | ||
243 | */ | ||
244 | twl4030_write(codec, TWL4030_REG_EAR_CTL, | ||
245 | twl4030_read_reg_cache(codec, TWL4030_REG_EAR_CTL)); | ||
246 | |||
247 | twl4030_write(codec, TWL4030_REG_PREDL_CTL, | ||
248 | twl4030_read_reg_cache(codec, TWL4030_REG_PREDL_CTL)); | ||
249 | twl4030_write(codec, TWL4030_REG_PREDR_CTL, | ||
250 | twl4030_read_reg_cache(codec, TWL4030_REG_PREDR_CTL)); | ||
251 | |||
252 | twl4030_write(codec, TWL4030_REG_PRECKL_CTL, | ||
253 | twl4030_read_reg_cache(codec, TWL4030_REG_PRECKL_CTL)); | ||
254 | twl4030_write(codec, TWL4030_REG_PRECKR_CTL, | ||
255 | twl4030_read_reg_cache(codec, TWL4030_REG_PRECKR_CTL)); | ||
256 | |||
257 | /* Enable PLL */ | ||
258 | reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_APLL_CTL); | ||
259 | reg_val |= TWL4030_APLL_EN; | ||
260 | twl4030_write(codec, TWL4030_REG_APLL_CTL, reg_val); | ||
261 | } | ||
262 | |||
263 | twl4030->codec_muted = mute; | ||
264 | } | ||
265 | |||
266 | static void twl4030_power_up(struct snd_soc_codec *codec) | ||
267 | { | ||
268 | struct twl4030_priv *twl4030 = codec->private_data; | ||
269 | u8 anamicl, regmisc1, byte; | ||
270 | int i = 0; | ||
271 | |||
272 | if (twl4030->codec_powered) | ||
273 | return; | ||
274 | |||
275 | /* set CODECPDZ to turn on codec */ | ||
276 | twl4030_codec_enable(codec, 1); | ||
277 | |||
278 | /* initiate offset cancellation */ | ||
279 | anamicl = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL); | ||
280 | twl4030_write(codec, TWL4030_REG_ANAMICL, | ||
281 | anamicl | TWL4030_CNCL_OFFSET_START); | ||
282 | |||
283 | /* wait for offset cancellation to complete */ | ||
284 | do { | ||
285 | /* this takes a little while, so don't slam i2c */ | ||
286 | udelay(2000); | ||
287 | twl4030_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte, | ||
288 | TWL4030_REG_ANAMICL); | ||
289 | } while ((i++ < 100) && | ||
290 | ((byte & TWL4030_CNCL_OFFSET_START) == | ||
291 | TWL4030_CNCL_OFFSET_START)); | ||
292 | |||
293 | /* Make sure that the reg_cache has the same value as the HW */ | ||
294 | twl4030_write_reg_cache(codec, TWL4030_REG_ANAMICL, byte); | ||
295 | |||
296 | /* anti-pop when changing analog gain */ | ||
297 | regmisc1 = twl4030_read_reg_cache(codec, TWL4030_REG_MISC_SET_1); | ||
298 | twl4030_write(codec, TWL4030_REG_MISC_SET_1, | ||
299 | regmisc1 | TWL4030_SMOOTH_ANAVOL_EN); | ||
300 | |||
301 | /* toggle CODECPDZ as per TRM */ | ||
302 | twl4030_codec_enable(codec, 0); | ||
303 | twl4030_codec_enable(codec, 1); | ||
304 | } | ||
305 | |||
306 | /* | ||
307 | * Unconditional power down | ||
308 | */ | ||
309 | static void twl4030_power_down(struct snd_soc_codec *codec) | ||
310 | { | ||
311 | /* power down */ | ||
312 | twl4030_codec_enable(codec, 0); | ||
313 | } | ||
314 | |||
193 | /* Earpiece */ | 315 | /* Earpiece */ |
194 | static const char *twl4030_earpiece_texts[] = | 316 | static const char *twl4030_earpiece_texts[] = |
195 | {"Off", "DACL1", "DACL2", "DACR1"}; | 317 | {"Off", "DACL1", "DACL2", "DACR1"}; |
@@ -366,6 +488,41 @@ static const struct soc_enum twl4030_micpathtx2_enum = | |||
366 | static const struct snd_kcontrol_new twl4030_dapm_micpathtx2_control = | 488 | static const struct snd_kcontrol_new twl4030_dapm_micpathtx2_control = |
367 | SOC_DAPM_ENUM("Route", twl4030_micpathtx2_enum); | 489 | SOC_DAPM_ENUM("Route", twl4030_micpathtx2_enum); |
368 | 490 | ||
491 | /* Analog bypass for AudioR1 */ | ||
492 | static const struct snd_kcontrol_new twl4030_dapm_abypassr1_control = | ||
493 | SOC_DAPM_SINGLE("Switch", TWL4030_REG_ARXR1_APGA_CTL, 2, 1, 0); | ||
494 | |||
495 | /* Analog bypass for AudioL1 */ | ||
496 | static const struct snd_kcontrol_new twl4030_dapm_abypassl1_control = | ||
497 | SOC_DAPM_SINGLE("Switch", TWL4030_REG_ARXL1_APGA_CTL, 2, 1, 0); | ||
498 | |||
499 | /* Analog bypass for AudioR2 */ | ||
500 | static const struct snd_kcontrol_new twl4030_dapm_abypassr2_control = | ||
501 | SOC_DAPM_SINGLE("Switch", TWL4030_REG_ARXR2_APGA_CTL, 2, 1, 0); | ||
502 | |||
503 | /* Analog bypass for AudioL2 */ | ||
504 | static const struct snd_kcontrol_new twl4030_dapm_abypassl2_control = | ||
505 | SOC_DAPM_SINGLE("Switch", TWL4030_REG_ARXL2_APGA_CTL, 2, 1, 0); | ||
506 | |||
507 | /* Digital bypass gain, 0 mutes the bypass */ | ||
508 | static const unsigned int twl4030_dapm_dbypass_tlv[] = { | ||
509 | TLV_DB_RANGE_HEAD(2), | ||
510 | 0, 3, TLV_DB_SCALE_ITEM(-2400, 0, 1), | ||
511 | 4, 7, TLV_DB_SCALE_ITEM(-1800, 600, 0), | ||
512 | }; | ||
513 | |||
514 | /* Digital bypass left (TX1L -> RX2L) */ | ||
515 | static const struct snd_kcontrol_new twl4030_dapm_dbypassl_control = | ||
516 | SOC_DAPM_SINGLE_TLV("Volume", | ||
517 | TWL4030_REG_ATX2ARXPGA, 3, 7, 0, | ||
518 | twl4030_dapm_dbypass_tlv); | ||
519 | |||
520 | /* Digital bypass right (TX1R -> RX2R) */ | ||
521 | static const struct snd_kcontrol_new twl4030_dapm_dbypassr_control = | ||
522 | SOC_DAPM_SINGLE_TLV("Volume", | ||
523 | TWL4030_REG_ATX2ARXPGA, 0, 7, 0, | ||
524 | twl4030_dapm_dbypass_tlv); | ||
525 | |||
369 | static int micpath_event(struct snd_soc_dapm_widget *w, | 526 | static int micpath_event(struct snd_soc_dapm_widget *w, |
370 | struct snd_kcontrol *kcontrol, int event) | 527 | struct snd_kcontrol *kcontrol, int event) |
371 | { | 528 | { |
@@ -420,6 +577,79 @@ static int handsfree_event(struct snd_soc_dapm_widget *w, | |||
420 | return 0; | 577 | return 0; |
421 | } | 578 | } |
422 | 579 | ||
580 | static int headsetl_event(struct snd_soc_dapm_widget *w, | ||
581 | struct snd_kcontrol *kcontrol, int event) | ||
582 | { | ||
583 | unsigned char hs_gain, hs_pop; | ||
584 | |||
585 | /* Save the current volume */ | ||
586 | hs_gain = twl4030_read_reg_cache(w->codec, TWL4030_REG_HS_GAIN_SET); | ||
587 | hs_pop = twl4030_read_reg_cache(w->codec, TWL4030_REG_HS_POPN_SET); | ||
588 | |||
589 | switch (event) { | ||
590 | case SND_SOC_DAPM_POST_PMU: | ||
591 | /* Do the anti-pop/bias ramp enable according to the TRM */ | ||
592 | hs_pop |= TWL4030_VMID_EN; | ||
593 | twl4030_write(w->codec, TWL4030_REG_HS_POPN_SET, hs_pop); | ||
594 | /* Is this needed? Can we just use whatever gain here? */ | ||
595 | twl4030_write(w->codec, TWL4030_REG_HS_GAIN_SET, | ||
596 | (hs_gain & (~0x0f)) | 0x0a); | ||
597 | hs_pop |= TWL4030_RAMP_EN; | ||
598 | twl4030_write(w->codec, TWL4030_REG_HS_POPN_SET, hs_pop); | ||
599 | |||
600 | /* Restore the original volume */ | ||
601 | twl4030_write(w->codec, TWL4030_REG_HS_GAIN_SET, hs_gain); | ||
602 | break; | ||
603 | case SND_SOC_DAPM_POST_PMD: | ||
604 | /* Do the anti-pop/bias ramp disable according to the TRM */ | ||
605 | hs_pop &= ~TWL4030_RAMP_EN; | ||
606 | twl4030_write(w->codec, TWL4030_REG_HS_POPN_SET, hs_pop); | ||
607 | /* Bypass the reg_cache to mute the headset */ | ||
608 | twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, | ||
609 | hs_gain & (~0x0f), | ||
610 | TWL4030_REG_HS_GAIN_SET); | ||
611 | hs_pop &= ~TWL4030_VMID_EN; | ||
612 | twl4030_write(w->codec, TWL4030_REG_HS_POPN_SET, hs_pop); | ||
613 | break; | ||
614 | } | ||
615 | return 0; | ||
616 | } | ||
617 | |||
618 | static int bypass_event(struct snd_soc_dapm_widget *w, | ||
619 | struct snd_kcontrol *kcontrol, int event) | ||
620 | { | ||
621 | struct soc_mixer_control *m = | ||
622 | (struct soc_mixer_control *)w->kcontrols->private_value; | ||
623 | struct twl4030_priv *twl4030 = w->codec->private_data; | ||
624 | unsigned char reg; | ||
625 | |||
626 | reg = twl4030_read_reg_cache(w->codec, m->reg); | ||
627 | |||
628 | if (m->reg <= TWL4030_REG_ARXR2_APGA_CTL) { | ||
629 | /* Analog bypass */ | ||
630 | if (reg & (1 << m->shift)) | ||
631 | twl4030->bypass_state |= | ||
632 | (1 << (m->reg - TWL4030_REG_ARXL1_APGA_CTL)); | ||
633 | else | ||
634 | twl4030->bypass_state &= | ||
635 | ~(1 << (m->reg - TWL4030_REG_ARXL1_APGA_CTL)); | ||
636 | } else { | ||
637 | /* Digital bypass */ | ||
638 | if (reg & (0x7 << m->shift)) | ||
639 | twl4030->bypass_state |= (1 << (m->shift ? 5 : 4)); | ||
640 | else | ||
641 | twl4030->bypass_state &= ~(1 << (m->shift ? 5 : 4)); | ||
642 | } | ||
643 | |||
644 | if (w->codec->bias_level == SND_SOC_BIAS_STANDBY) { | ||
645 | if (twl4030->bypass_state) | ||
646 | twl4030_codec_mute(w->codec, 0); | ||
647 | else | ||
648 | twl4030_codec_mute(w->codec, 1); | ||
649 | } | ||
650 | return 0; | ||
651 | } | ||
652 | |||
423 | /* | 653 | /* |
424 | * Some of the gain controls in TWL (mostly those which are associated with | 654 | * Some of the gain controls in TWL (mostly those which are associated with |
425 | * the outputs) are implemented in an interesting way: | 655 | * the outputs) are implemented in an interesting way: |
@@ -614,6 +844,17 @@ static DECLARE_TLV_DB_SCALE(digital_capture_tlv, 0, 100, 0); | |||
614 | */ | 844 | */ |
615 | static DECLARE_TLV_DB_SCALE(input_gain_tlv, 0, 600, 0); | 845 | static DECLARE_TLV_DB_SCALE(input_gain_tlv, 0, 600, 0); |
616 | 846 | ||
847 | static const char *twl4030_rampdelay_texts[] = { | ||
848 | "27/20/14 ms", "55/40/27 ms", "109/81/55 ms", "218/161/109 ms", | ||
849 | "437/323/218 ms", "874/645/437 ms", "1748/1291/874 ms", | ||
850 | "3495/2581/1748 ms" | ||
851 | }; | ||
852 | |||
853 | static const struct soc_enum twl4030_rampdelay_enum = | ||
854 | SOC_ENUM_SINGLE(TWL4030_REG_HS_POPN_SET, 2, | ||
855 | ARRAY_SIZE(twl4030_rampdelay_texts), | ||
856 | twl4030_rampdelay_texts); | ||
857 | |||
617 | static const struct snd_kcontrol_new twl4030_snd_controls[] = { | 858 | static const struct snd_kcontrol_new twl4030_snd_controls[] = { |
618 | /* Common playback gain controls */ | 859 | /* Common playback gain controls */ |
619 | SOC_DOUBLE_R_TLV("DAC1 Digital Fine Playback Volume", | 860 | SOC_DOUBLE_R_TLV("DAC1 Digital Fine Playback Volume", |
@@ -668,23 +909,9 @@ static const struct snd_kcontrol_new twl4030_snd_controls[] = { | |||
668 | 909 | ||
669 | SOC_DOUBLE_TLV("Analog Capture Volume", TWL4030_REG_ANAMIC_GAIN, | 910 | SOC_DOUBLE_TLV("Analog Capture Volume", TWL4030_REG_ANAMIC_GAIN, |
670 | 0, 3, 5, 0, input_gain_tlv), | 911 | 0, 3, 5, 0, input_gain_tlv), |
671 | }; | ||
672 | |||
673 | /* add non dapm controls */ | ||
674 | static int twl4030_add_controls(struct snd_soc_codec *codec) | ||
675 | { | ||
676 | int err, i; | ||
677 | |||
678 | for (i = 0; i < ARRAY_SIZE(twl4030_snd_controls); i++) { | ||
679 | err = snd_ctl_add(codec->card, | ||
680 | snd_soc_cnew(&twl4030_snd_controls[i], | ||
681 | codec, NULL)); | ||
682 | if (err < 0) | ||
683 | return err; | ||
684 | } | ||
685 | 912 | ||
686 | return 0; | 913 | SOC_ENUM("HS ramp delay", twl4030_rampdelay_enum), |
687 | } | 914 | }; |
688 | 915 | ||
689 | static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { | 916 | static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { |
690 | /* Left channel inputs */ | 917 | /* Left channel inputs */ |
@@ -714,13 +941,13 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { | |||
714 | 941 | ||
715 | /* DACs */ | 942 | /* DACs */ |
716 | SND_SOC_DAPM_DAC("DAC Right1", "Right Front Playback", | 943 | SND_SOC_DAPM_DAC("DAC Right1", "Right Front Playback", |
717 | TWL4030_REG_AVDAC_CTL, 0, 0), | 944 | SND_SOC_NOPM, 0, 0), |
718 | SND_SOC_DAPM_DAC("DAC Left1", "Left Front Playback", | 945 | SND_SOC_DAPM_DAC("DAC Left1", "Left Front Playback", |
719 | TWL4030_REG_AVDAC_CTL, 1, 0), | 946 | SND_SOC_NOPM, 0, 0), |
720 | SND_SOC_DAPM_DAC("DAC Right2", "Right Rear Playback", | 947 | SND_SOC_DAPM_DAC("DAC Right2", "Right Rear Playback", |
721 | TWL4030_REG_AVDAC_CTL, 2, 0), | 948 | SND_SOC_NOPM, 0, 0), |
722 | SND_SOC_DAPM_DAC("DAC Left2", "Left Rear Playback", | 949 | SND_SOC_DAPM_DAC("DAC Left2", "Left Rear Playback", |
723 | TWL4030_REG_AVDAC_CTL, 3, 0), | 950 | SND_SOC_NOPM, 0, 0), |
724 | 951 | ||
725 | /* Analog PGAs */ | 952 | /* Analog PGAs */ |
726 | SND_SOC_DAPM_PGA("ARXR1_APGA", TWL4030_REG_ARXR1_APGA_CTL, | 953 | SND_SOC_DAPM_PGA("ARXR1_APGA", TWL4030_REG_ARXR1_APGA_CTL, |
@@ -732,6 +959,37 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { | |||
732 | SND_SOC_DAPM_PGA("ARXL2_APGA", TWL4030_REG_ARXL2_APGA_CTL, | 959 | SND_SOC_DAPM_PGA("ARXL2_APGA", TWL4030_REG_ARXL2_APGA_CTL, |
733 | 0, 0, NULL, 0), | 960 | 0, 0, NULL, 0), |
734 | 961 | ||
962 | /* Analog bypasses */ | ||
963 | SND_SOC_DAPM_SWITCH_E("Right1 Analog Loopback", SND_SOC_NOPM, 0, 0, | ||
964 | &twl4030_dapm_abypassr1_control, bypass_event, | ||
965 | SND_SOC_DAPM_POST_REG), | ||
966 | SND_SOC_DAPM_SWITCH_E("Left1 Analog Loopback", SND_SOC_NOPM, 0, 0, | ||
967 | &twl4030_dapm_abypassl1_control, | ||
968 | bypass_event, SND_SOC_DAPM_POST_REG), | ||
969 | SND_SOC_DAPM_SWITCH_E("Right2 Analog Loopback", SND_SOC_NOPM, 0, 0, | ||
970 | &twl4030_dapm_abypassr2_control, | ||
971 | bypass_event, SND_SOC_DAPM_POST_REG), | ||
972 | SND_SOC_DAPM_SWITCH_E("Left2 Analog Loopback", SND_SOC_NOPM, 0, 0, | ||
973 | &twl4030_dapm_abypassl2_control, | ||
974 | bypass_event, SND_SOC_DAPM_POST_REG), | ||
975 | |||
976 | /* Digital bypasses */ | ||
977 | SND_SOC_DAPM_SWITCH_E("Left Digital Loopback", SND_SOC_NOPM, 0, 0, | ||
978 | &twl4030_dapm_dbypassl_control, bypass_event, | ||
979 | SND_SOC_DAPM_POST_REG), | ||
980 | SND_SOC_DAPM_SWITCH_E("Right Digital Loopback", SND_SOC_NOPM, 0, 0, | ||
981 | &twl4030_dapm_dbypassr_control, bypass_event, | ||
982 | SND_SOC_DAPM_POST_REG), | ||
983 | |||
984 | SND_SOC_DAPM_MIXER("Analog R1 Playback Mixer", TWL4030_REG_AVDAC_CTL, | ||
985 | 0, 0, NULL, 0), | ||
986 | SND_SOC_DAPM_MIXER("Analog L1 Playback Mixer", TWL4030_REG_AVDAC_CTL, | ||
987 | 1, 0, NULL, 0), | ||
988 | SND_SOC_DAPM_MIXER("Analog R2 Playback Mixer", TWL4030_REG_AVDAC_CTL, | ||
989 | 2, 0, NULL, 0), | ||
990 | SND_SOC_DAPM_MIXER("Analog L2 Playback Mixer", TWL4030_REG_AVDAC_CTL, | ||
991 | 3, 0, NULL, 0), | ||
992 | |||
735 | /* Output MUX controls */ | 993 | /* Output MUX controls */ |
736 | /* Earpiece */ | 994 | /* Earpiece */ |
737 | SND_SOC_DAPM_VALUE_MUX("Earpiece Mux", SND_SOC_NOPM, 0, 0, | 995 | SND_SOC_DAPM_VALUE_MUX("Earpiece Mux", SND_SOC_NOPM, 0, 0, |
@@ -742,8 +1000,9 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { | |||
742 | SND_SOC_DAPM_VALUE_MUX("PredriveR Mux", SND_SOC_NOPM, 0, 0, | 1000 | SND_SOC_DAPM_VALUE_MUX("PredriveR Mux", SND_SOC_NOPM, 0, 0, |
743 | &twl4030_dapm_predriver_control), | 1001 | &twl4030_dapm_predriver_control), |
744 | /* HeadsetL/R */ | 1002 | /* HeadsetL/R */ |
745 | SND_SOC_DAPM_MUX("HeadsetL Mux", SND_SOC_NOPM, 0, 0, | 1003 | SND_SOC_DAPM_MUX_E("HeadsetL Mux", SND_SOC_NOPM, 0, 0, |
746 | &twl4030_dapm_hsol_control), | 1004 | &twl4030_dapm_hsol_control, headsetl_event, |
1005 | SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), | ||
747 | SND_SOC_DAPM_MUX("HeadsetR Mux", SND_SOC_NOPM, 0, 0, | 1006 | SND_SOC_DAPM_MUX("HeadsetR Mux", SND_SOC_NOPM, 0, 0, |
748 | &twl4030_dapm_hsor_control), | 1007 | &twl4030_dapm_hsor_control), |
749 | /* CarkitL/R */ | 1008 | /* CarkitL/R */ |
@@ -782,16 +1041,16 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { | |||
782 | SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD| | 1041 | SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD| |
783 | SND_SOC_DAPM_POST_REG), | 1042 | SND_SOC_DAPM_POST_REG), |
784 | 1043 | ||
785 | /* Analog input muxes with power switch for the physical ADCL/R */ | 1044 | /* Analog input muxes with switch for the capture amplifiers */ |
786 | SND_SOC_DAPM_VALUE_MUX("Analog Left Capture Route", | 1045 | SND_SOC_DAPM_VALUE_MUX("Analog Left Capture Route", |
787 | TWL4030_REG_AVADC_CTL, 3, 0, &twl4030_dapm_analoglmic_control), | 1046 | TWL4030_REG_ANAMICL, 4, 0, &twl4030_dapm_analoglmic_control), |
788 | SND_SOC_DAPM_VALUE_MUX("Analog Right Capture Route", | 1047 | SND_SOC_DAPM_VALUE_MUX("Analog Right Capture Route", |
789 | TWL4030_REG_AVADC_CTL, 1, 0, &twl4030_dapm_analogrmic_control), | 1048 | TWL4030_REG_ANAMICR, 4, 0, &twl4030_dapm_analogrmic_control), |
790 | 1049 | ||
791 | SND_SOC_DAPM_PGA("Analog Left Amplifier", | 1050 | SND_SOC_DAPM_PGA("ADC Physical Left", |
792 | TWL4030_REG_ANAMICL, 4, 0, NULL, 0), | 1051 | TWL4030_REG_AVADC_CTL, 3, 0, NULL, 0), |
793 | SND_SOC_DAPM_PGA("Analog Right Amplifier", | 1052 | SND_SOC_DAPM_PGA("ADC Physical Right", |
794 | TWL4030_REG_ANAMICR, 4, 0, NULL, 0), | 1053 | TWL4030_REG_AVADC_CTL, 1, 0, NULL, 0), |
795 | 1054 | ||
796 | SND_SOC_DAPM_PGA("Digimic0 Enable", | 1055 | SND_SOC_DAPM_PGA("Digimic0 Enable", |
797 | TWL4030_REG_ADCMICSEL, 1, 0, NULL, 0), | 1056 | TWL4030_REG_ADCMICSEL, 1, 0, NULL, 0), |
@@ -801,13 +1060,19 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { | |||
801 | SND_SOC_DAPM_MICBIAS("Mic Bias 1", TWL4030_REG_MICBIAS_CTL, 0, 0), | 1060 | SND_SOC_DAPM_MICBIAS("Mic Bias 1", TWL4030_REG_MICBIAS_CTL, 0, 0), |
802 | SND_SOC_DAPM_MICBIAS("Mic Bias 2", TWL4030_REG_MICBIAS_CTL, 1, 0), | 1061 | SND_SOC_DAPM_MICBIAS("Mic Bias 2", TWL4030_REG_MICBIAS_CTL, 1, 0), |
803 | SND_SOC_DAPM_MICBIAS("Headset Mic Bias", TWL4030_REG_MICBIAS_CTL, 2, 0), | 1062 | SND_SOC_DAPM_MICBIAS("Headset Mic Bias", TWL4030_REG_MICBIAS_CTL, 2, 0), |
1063 | |||
804 | }; | 1064 | }; |
805 | 1065 | ||
806 | static const struct snd_soc_dapm_route intercon[] = { | 1066 | static const struct snd_soc_dapm_route intercon[] = { |
807 | {"ARXL1_APGA", NULL, "DAC Left1"}, | 1067 | {"Analog L1 Playback Mixer", NULL, "DAC Left1"}, |
808 | {"ARXR1_APGA", NULL, "DAC Right1"}, | 1068 | {"Analog R1 Playback Mixer", NULL, "DAC Right1"}, |
809 | {"ARXL2_APGA", NULL, "DAC Left2"}, | 1069 | {"Analog L2 Playback Mixer", NULL, "DAC Left2"}, |
810 | {"ARXR2_APGA", NULL, "DAC Right2"}, | 1070 | {"Analog R2 Playback Mixer", NULL, "DAC Right2"}, |
1071 | |||
1072 | {"ARXL1_APGA", NULL, "Analog L1 Playback Mixer"}, | ||
1073 | {"ARXR1_APGA", NULL, "Analog R1 Playback Mixer"}, | ||
1074 | {"ARXL2_APGA", NULL, "Analog L2 Playback Mixer"}, | ||
1075 | {"ARXR2_APGA", NULL, "Analog R2 Playback Mixer"}, | ||
811 | 1076 | ||
812 | /* Internal playback routings */ | 1077 | /* Internal playback routings */ |
813 | /* Earpiece */ | 1078 | /* Earpiece */ |
@@ -865,23 +1130,23 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
865 | {"Analog Right Capture Route", "Sub mic", "SUBMIC"}, | 1130 | {"Analog Right Capture Route", "Sub mic", "SUBMIC"}, |
866 | {"Analog Right Capture Route", "AUXR", "AUXR"}, | 1131 | {"Analog Right Capture Route", "AUXR", "AUXR"}, |
867 | 1132 | ||
868 | {"Analog Left Amplifier", NULL, "Analog Left Capture Route"}, | 1133 | {"ADC Physical Left", NULL, "Analog Left Capture Route"}, |
869 | {"Analog Right Amplifier", NULL, "Analog Right Capture Route"}, | 1134 | {"ADC Physical Right", NULL, "Analog Right Capture Route"}, |
870 | 1135 | ||
871 | {"Digimic0 Enable", NULL, "DIGIMIC0"}, | 1136 | {"Digimic0 Enable", NULL, "DIGIMIC0"}, |
872 | {"Digimic1 Enable", NULL, "DIGIMIC1"}, | 1137 | {"Digimic1 Enable", NULL, "DIGIMIC1"}, |
873 | 1138 | ||
874 | /* TX1 Left capture path */ | 1139 | /* TX1 Left capture path */ |
875 | {"TX1 Capture Route", "Analog", "Analog Left Amplifier"}, | 1140 | {"TX1 Capture Route", "Analog", "ADC Physical Left"}, |
876 | {"TX1 Capture Route", "Digimic0", "Digimic0 Enable"}, | 1141 | {"TX1 Capture Route", "Digimic0", "Digimic0 Enable"}, |
877 | /* TX1 Right capture path */ | 1142 | /* TX1 Right capture path */ |
878 | {"TX1 Capture Route", "Analog", "Analog Right Amplifier"}, | 1143 | {"TX1 Capture Route", "Analog", "ADC Physical Right"}, |
879 | {"TX1 Capture Route", "Digimic0", "Digimic0 Enable"}, | 1144 | {"TX1 Capture Route", "Digimic0", "Digimic0 Enable"}, |
880 | /* TX2 Left capture path */ | 1145 | /* TX2 Left capture path */ |
881 | {"TX2 Capture Route", "Analog", "Analog Left Amplifier"}, | 1146 | {"TX2 Capture Route", "Analog", "ADC Physical Left"}, |
882 | {"TX2 Capture Route", "Digimic1", "Digimic1 Enable"}, | 1147 | {"TX2 Capture Route", "Digimic1", "Digimic1 Enable"}, |
883 | /* TX2 Right capture path */ | 1148 | /* TX2 Right capture path */ |
884 | {"TX2 Capture Route", "Analog", "Analog Right Amplifier"}, | 1149 | {"TX2 Capture Route", "Analog", "ADC Physical Right"}, |
885 | {"TX2 Capture Route", "Digimic1", "Digimic1 Enable"}, | 1150 | {"TX2 Capture Route", "Digimic1", "Digimic1 Enable"}, |
886 | 1151 | ||
887 | {"ADC Virtual Left1", NULL, "TX1 Capture Route"}, | 1152 | {"ADC Virtual Left1", NULL, "TX1 Capture Route"}, |
@@ -889,6 +1154,24 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
889 | {"ADC Virtual Left2", NULL, "TX2 Capture Route"}, | 1154 | {"ADC Virtual Left2", NULL, "TX2 Capture Route"}, |
890 | {"ADC Virtual Right2", NULL, "TX2 Capture Route"}, | 1155 | {"ADC Virtual Right2", NULL, "TX2 Capture Route"}, |
891 | 1156 | ||
1157 | /* Analog bypass routes */ | ||
1158 | {"Right1 Analog Loopback", "Switch", "Analog Right Capture Route"}, | ||
1159 | {"Left1 Analog Loopback", "Switch", "Analog Left Capture Route"}, | ||
1160 | {"Right2 Analog Loopback", "Switch", "Analog Right Capture Route"}, | ||
1161 | {"Left2 Analog Loopback", "Switch", "Analog Left Capture Route"}, | ||
1162 | |||
1163 | {"Analog R1 Playback Mixer", NULL, "Right1 Analog Loopback"}, | ||
1164 | {"Analog L1 Playback Mixer", NULL, "Left1 Analog Loopback"}, | ||
1165 | {"Analog R2 Playback Mixer", NULL, "Right2 Analog Loopback"}, | ||
1166 | {"Analog L2 Playback Mixer", NULL, "Left2 Analog Loopback"}, | ||
1167 | |||
1168 | /* Digital bypass routes */ | ||
1169 | {"Right Digital Loopback", "Volume", "TX1 Capture Route"}, | ||
1170 | {"Left Digital Loopback", "Volume", "TX1 Capture Route"}, | ||
1171 | |||
1172 | {"Analog R2 Playback Mixer", NULL, "Right Digital Loopback"}, | ||
1173 | {"Analog L2 Playback Mixer", NULL, "Left Digital Loopback"}, | ||
1174 | |||
892 | }; | 1175 | }; |
893 | 1176 | ||
894 | static int twl4030_add_widgets(struct snd_soc_codec *codec) | 1177 | static int twl4030_add_widgets(struct snd_soc_codec *codec) |
@@ -902,82 +1185,28 @@ static int twl4030_add_widgets(struct snd_soc_codec *codec) | |||
902 | return 0; | 1185 | return 0; |
903 | } | 1186 | } |
904 | 1187 | ||
905 | static void twl4030_power_up(struct snd_soc_codec *codec) | ||
906 | { | ||
907 | u8 anamicl, regmisc1, byte, popn; | ||
908 | int i = 0; | ||
909 | |||
910 | /* set CODECPDZ to turn on codec */ | ||
911 | twl4030_set_codecpdz(codec); | ||
912 | |||
913 | /* initiate offset cancellation */ | ||
914 | anamicl = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL); | ||
915 | twl4030_write(codec, TWL4030_REG_ANAMICL, | ||
916 | anamicl | TWL4030_CNCL_OFFSET_START); | ||
917 | |||
918 | |||
919 | /* wait for offset cancellation to complete */ | ||
920 | do { | ||
921 | /* this takes a little while, so don't slam i2c */ | ||
922 | udelay(2000); | ||
923 | twl4030_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte, | ||
924 | TWL4030_REG_ANAMICL); | ||
925 | } while ((i++ < 100) && | ||
926 | ((byte & TWL4030_CNCL_OFFSET_START) == | ||
927 | TWL4030_CNCL_OFFSET_START)); | ||
928 | |||
929 | /* anti-pop when changing analog gain */ | ||
930 | regmisc1 = twl4030_read_reg_cache(codec, TWL4030_REG_MISC_SET_1); | ||
931 | twl4030_write(codec, TWL4030_REG_MISC_SET_1, | ||
932 | regmisc1 | TWL4030_SMOOTH_ANAVOL_EN); | ||
933 | |||
934 | /* toggle CODECPDZ as per TRM */ | ||
935 | twl4030_clear_codecpdz(codec); | ||
936 | twl4030_set_codecpdz(codec); | ||
937 | |||
938 | /* program anti-pop with bias ramp delay */ | ||
939 | popn = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET); | ||
940 | popn &= TWL4030_RAMP_DELAY; | ||
941 | popn |= TWL4030_RAMP_DELAY_645MS; | ||
942 | twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn); | ||
943 | popn |= TWL4030_VMID_EN; | ||
944 | twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn); | ||
945 | |||
946 | /* enable anti-pop ramp */ | ||
947 | popn |= TWL4030_RAMP_EN; | ||
948 | twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn); | ||
949 | } | ||
950 | |||
951 | static void twl4030_power_down(struct snd_soc_codec *codec) | ||
952 | { | ||
953 | u8 popn; | ||
954 | |||
955 | /* disable anti-pop ramp */ | ||
956 | popn = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET); | ||
957 | popn &= ~TWL4030_RAMP_EN; | ||
958 | twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn); | ||
959 | |||
960 | /* disable bias out */ | ||
961 | popn &= ~TWL4030_VMID_EN; | ||
962 | twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn); | ||
963 | |||
964 | /* power down */ | ||
965 | twl4030_clear_codecpdz(codec); | ||
966 | } | ||
967 | |||
968 | static int twl4030_set_bias_level(struct snd_soc_codec *codec, | 1188 | static int twl4030_set_bias_level(struct snd_soc_codec *codec, |
969 | enum snd_soc_bias_level level) | 1189 | enum snd_soc_bias_level level) |
970 | { | 1190 | { |
1191 | struct twl4030_priv *twl4030 = codec->private_data; | ||
1192 | |||
971 | switch (level) { | 1193 | switch (level) { |
972 | case SND_SOC_BIAS_ON: | 1194 | case SND_SOC_BIAS_ON: |
973 | twl4030_power_up(codec); | 1195 | twl4030_codec_mute(codec, 0); |
974 | break; | 1196 | break; |
975 | case SND_SOC_BIAS_PREPARE: | 1197 | case SND_SOC_BIAS_PREPARE: |
976 | /* TODO: develop a twl4030_prepare function */ | 1198 | twl4030_power_up(codec); |
1199 | if (twl4030->bypass_state) | ||
1200 | twl4030_codec_mute(codec, 0); | ||
1201 | else | ||
1202 | twl4030_codec_mute(codec, 1); | ||
977 | break; | 1203 | break; |
978 | case SND_SOC_BIAS_STANDBY: | 1204 | case SND_SOC_BIAS_STANDBY: |
979 | /* TODO: develop a twl4030_standby function */ | 1205 | twl4030_power_up(codec); |
980 | twl4030_power_down(codec); | 1206 | if (twl4030->bypass_state) |
1207 | twl4030_codec_mute(codec, 0); | ||
1208 | else | ||
1209 | twl4030_codec_mute(codec, 1); | ||
981 | break; | 1210 | break; |
982 | case SND_SOC_BIAS_OFF: | 1211 | case SND_SOC_BIAS_OFF: |
983 | twl4030_power_down(codec); | 1212 | twl4030_power_down(codec); |
@@ -994,10 +1223,9 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream, | |||
994 | { | 1223 | { |
995 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1224 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
996 | struct snd_soc_device *socdev = rtd->socdev; | 1225 | struct snd_soc_device *socdev = rtd->socdev; |
997 | struct snd_soc_codec *codec = socdev->codec; | 1226 | struct snd_soc_codec *codec = socdev->card->codec; |
998 | u8 mode, old_mode, format, old_format; | 1227 | u8 mode, old_mode, format, old_format; |
999 | 1228 | ||
1000 | |||
1001 | /* bit rate */ | 1229 | /* bit rate */ |
1002 | old_mode = twl4030_read_reg_cache(codec, | 1230 | old_mode = twl4030_read_reg_cache(codec, |
1003 | TWL4030_REG_CODEC_MODE) & ~TWL4030_CODECPDZ; | 1231 | TWL4030_REG_CODEC_MODE) & ~TWL4030_CODECPDZ; |
@@ -1039,8 +1267,9 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream, | |||
1039 | 1267 | ||
1040 | if (mode != old_mode) { | 1268 | if (mode != old_mode) { |
1041 | /* change rate and set CODECPDZ */ | 1269 | /* change rate and set CODECPDZ */ |
1270 | twl4030_codec_enable(codec, 0); | ||
1042 | twl4030_write(codec, TWL4030_REG_CODEC_MODE, mode); | 1271 | twl4030_write(codec, TWL4030_REG_CODEC_MODE, mode); |
1043 | twl4030_set_codecpdz(codec); | 1272 | twl4030_codec_enable(codec, 1); |
1044 | } | 1273 | } |
1045 | 1274 | ||
1046 | /* sample size */ | 1275 | /* sample size */ |
@@ -1063,13 +1292,13 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream, | |||
1063 | if (format != old_format) { | 1292 | if (format != old_format) { |
1064 | 1293 | ||
1065 | /* clear CODECPDZ before changing format (codec requirement) */ | 1294 | /* clear CODECPDZ before changing format (codec requirement) */ |
1066 | twl4030_clear_codecpdz(codec); | 1295 | twl4030_codec_enable(codec, 0); |
1067 | 1296 | ||
1068 | /* change format */ | 1297 | /* change format */ |
1069 | twl4030_write(codec, TWL4030_REG_AUDIO_IF, format); | 1298 | twl4030_write(codec, TWL4030_REG_AUDIO_IF, format); |
1070 | 1299 | ||
1071 | /* set CODECPDZ afterwards */ | 1300 | /* set CODECPDZ afterwards */ |
1072 | twl4030_set_codecpdz(codec); | 1301 | twl4030_codec_enable(codec, 1); |
1073 | } | 1302 | } |
1074 | return 0; | 1303 | return 0; |
1075 | } | 1304 | } |
@@ -1139,13 +1368,13 @@ static int twl4030_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
1139 | if (format != old_format) { | 1368 | if (format != old_format) { |
1140 | 1369 | ||
1141 | /* clear CODECPDZ before changing format (codec requirement) */ | 1370 | /* clear CODECPDZ before changing format (codec requirement) */ |
1142 | twl4030_clear_codecpdz(codec); | 1371 | twl4030_codec_enable(codec, 0); |
1143 | 1372 | ||
1144 | /* change format */ | 1373 | /* change format */ |
1145 | twl4030_write(codec, TWL4030_REG_AUDIO_IF, format); | 1374 | twl4030_write(codec, TWL4030_REG_AUDIO_IF, format); |
1146 | 1375 | ||
1147 | /* set CODECPDZ afterwards */ | 1376 | /* set CODECPDZ afterwards */ |
1148 | twl4030_set_codecpdz(codec); | 1377 | twl4030_codec_enable(codec, 1); |
1149 | } | 1378 | } |
1150 | 1379 | ||
1151 | return 0; | 1380 | return 0; |
@@ -1154,6 +1383,12 @@ static int twl4030_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
1154 | #define TWL4030_RATES (SNDRV_PCM_RATE_8000_48000) | 1383 | #define TWL4030_RATES (SNDRV_PCM_RATE_8000_48000) |
1155 | #define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE) | 1384 | #define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE) |
1156 | 1385 | ||
1386 | static struct snd_soc_dai_ops twl4030_dai_ops = { | ||
1387 | .hw_params = twl4030_hw_params, | ||
1388 | .set_sysclk = twl4030_set_dai_sysclk, | ||
1389 | .set_fmt = twl4030_set_dai_fmt, | ||
1390 | }; | ||
1391 | |||
1157 | struct snd_soc_dai twl4030_dai = { | 1392 | struct snd_soc_dai twl4030_dai = { |
1158 | .name = "twl4030", | 1393 | .name = "twl4030", |
1159 | .playback = { | 1394 | .playback = { |
@@ -1168,18 +1403,14 @@ struct snd_soc_dai twl4030_dai = { | |||
1168 | .channels_max = 2, | 1403 | .channels_max = 2, |
1169 | .rates = TWL4030_RATES, | 1404 | .rates = TWL4030_RATES, |
1170 | .formats = TWL4030_FORMATS,}, | 1405 | .formats = TWL4030_FORMATS,}, |
1171 | .ops = { | 1406 | .ops = &twl4030_dai_ops, |
1172 | .hw_params = twl4030_hw_params, | ||
1173 | .set_sysclk = twl4030_set_dai_sysclk, | ||
1174 | .set_fmt = twl4030_set_dai_fmt, | ||
1175 | } | ||
1176 | }; | 1407 | }; |
1177 | EXPORT_SYMBOL_GPL(twl4030_dai); | 1408 | EXPORT_SYMBOL_GPL(twl4030_dai); |
1178 | 1409 | ||
1179 | static int twl4030_suspend(struct platform_device *pdev, pm_message_t state) | 1410 | static int twl4030_suspend(struct platform_device *pdev, pm_message_t state) |
1180 | { | 1411 | { |
1181 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1412 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
1182 | struct snd_soc_codec *codec = socdev->codec; | 1413 | struct snd_soc_codec *codec = socdev->card->codec; |
1183 | 1414 | ||
1184 | twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1415 | twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1185 | 1416 | ||
@@ -1189,7 +1420,7 @@ static int twl4030_suspend(struct platform_device *pdev, pm_message_t state) | |||
1189 | static int twl4030_resume(struct platform_device *pdev) | 1420 | static int twl4030_resume(struct platform_device *pdev) |
1190 | { | 1421 | { |
1191 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1422 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
1192 | struct snd_soc_codec *codec = socdev->codec; | 1423 | struct snd_soc_codec *codec = socdev->card->codec; |
1193 | 1424 | ||
1194 | twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1425 | twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1195 | twl4030_set_bias_level(codec, codec->suspend_bias_level); | 1426 | twl4030_set_bias_level(codec, codec->suspend_bias_level); |
@@ -1203,7 +1434,7 @@ static int twl4030_resume(struct platform_device *pdev) | |||
1203 | 1434 | ||
1204 | static int twl4030_init(struct snd_soc_device *socdev) | 1435 | static int twl4030_init(struct snd_soc_device *socdev) |
1205 | { | 1436 | { |
1206 | struct snd_soc_codec *codec = socdev->codec; | 1437 | struct snd_soc_codec *codec = socdev->card->codec; |
1207 | int ret = 0; | 1438 | int ret = 0; |
1208 | 1439 | ||
1209 | printk(KERN_INFO "TWL4030 Audio Codec init \n"); | 1440 | printk(KERN_INFO "TWL4030 Audio Codec init \n"); |
@@ -1233,7 +1464,8 @@ static int twl4030_init(struct snd_soc_device *socdev) | |||
1233 | /* power on device */ | 1464 | /* power on device */ |
1234 | twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1465 | twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1235 | 1466 | ||
1236 | twl4030_add_controls(codec); | 1467 | snd_soc_add_controls(codec, twl4030_snd_controls, |
1468 | ARRAY_SIZE(twl4030_snd_controls)); | ||
1237 | twl4030_add_widgets(codec); | 1469 | twl4030_add_widgets(codec); |
1238 | 1470 | ||
1239 | ret = snd_soc_init_card(socdev); | 1471 | ret = snd_soc_init_card(socdev); |
@@ -1258,12 +1490,20 @@ static int twl4030_probe(struct platform_device *pdev) | |||
1258 | { | 1490 | { |
1259 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1491 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
1260 | struct snd_soc_codec *codec; | 1492 | struct snd_soc_codec *codec; |
1493 | struct twl4030_priv *twl4030; | ||
1261 | 1494 | ||
1262 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | 1495 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); |
1263 | if (codec == NULL) | 1496 | if (codec == NULL) |
1264 | return -ENOMEM; | 1497 | return -ENOMEM; |
1265 | 1498 | ||
1266 | socdev->codec = codec; | 1499 | twl4030 = kzalloc(sizeof(struct twl4030_priv), GFP_KERNEL); |
1500 | if (twl4030 == NULL) { | ||
1501 | kfree(codec); | ||
1502 | return -ENOMEM; | ||
1503 | } | ||
1504 | |||
1505 | codec->private_data = twl4030; | ||
1506 | socdev->card->codec = codec; | ||
1267 | mutex_init(&codec->mutex); | 1507 | mutex_init(&codec->mutex); |
1268 | INIT_LIST_HEAD(&codec->dapm_widgets); | 1508 | INIT_LIST_HEAD(&codec->dapm_widgets); |
1269 | INIT_LIST_HEAD(&codec->dapm_paths); | 1509 | INIT_LIST_HEAD(&codec->dapm_paths); |
@@ -1277,11 +1517,13 @@ static int twl4030_probe(struct platform_device *pdev) | |||
1277 | static int twl4030_remove(struct platform_device *pdev) | 1517 | static int twl4030_remove(struct platform_device *pdev) |
1278 | { | 1518 | { |
1279 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1519 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
1280 | struct snd_soc_codec *codec = socdev->codec; | 1520 | struct snd_soc_codec *codec = socdev->card->codec; |
1281 | 1521 | ||
1282 | printk(KERN_INFO "TWL4030 Audio Codec remove\n"); | 1522 | printk(KERN_INFO "TWL4030 Audio Codec remove\n"); |
1523 | twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1283 | snd_soc_free_pcms(socdev); | 1524 | snd_soc_free_pcms(socdev); |
1284 | snd_soc_dapm_free(socdev); | 1525 | snd_soc_dapm_free(socdev); |
1526 | kfree(codec->private_data); | ||
1285 | kfree(codec); | 1527 | kfree(codec); |
1286 | 1528 | ||
1287 | return 0; | 1529 | return 0; |
diff --git a/sound/soc/codecs/twl4030.h b/sound/soc/codecs/twl4030.h index 442e5a828617..33dbb144dad1 100644 --- a/sound/soc/codecs/twl4030.h +++ b/sound/soc/codecs/twl4030.h | |||
@@ -170,6 +170,9 @@ | |||
170 | #define TWL4030_CLK256FS_EN 0x02 | 170 | #define TWL4030_CLK256FS_EN 0x02 |
171 | #define TWL4030_AIF_EN 0x01 | 171 | #define TWL4030_AIF_EN 0x01 |
172 | 172 | ||
173 | /* EAR_CTL (0x21) */ | ||
174 | #define TWL4030_EAR_GAIN 0x30 | ||
175 | |||
173 | /* HS_GAIN_SET (0x23) Fields */ | 176 | /* HS_GAIN_SET (0x23) Fields */ |
174 | 177 | ||
175 | #define TWL4030_HSR_GAIN 0x0C | 178 | #define TWL4030_HSR_GAIN 0x0C |
@@ -198,6 +201,18 @@ | |||
198 | #define TWL4030_RAMP_DELAY_2581MS 0x1C | 201 | #define TWL4030_RAMP_DELAY_2581MS 0x1C |
199 | #define TWL4030_RAMP_EN 0x02 | 202 | #define TWL4030_RAMP_EN 0x02 |
200 | 203 | ||
204 | /* PREDL_CTL (0x25) */ | ||
205 | #define TWL4030_PREDL_GAIN 0x30 | ||
206 | |||
207 | /* PREDR_CTL (0x26) */ | ||
208 | #define TWL4030_PREDR_GAIN 0x30 | ||
209 | |||
210 | /* PRECKL_CTL (0x27) */ | ||
211 | #define TWL4030_PRECKL_GAIN 0x30 | ||
212 | |||
213 | /* PRECKR_CTL (0x28) */ | ||
214 | #define TWL4030_PRECKR_GAIN 0x30 | ||
215 | |||
201 | /* HFL_CTL (0x29, 0x2A) Fields */ | 216 | /* HFL_CTL (0x29, 0x2A) Fields */ |
202 | #define TWL4030_HF_CTL_HB_EN 0x04 | 217 | #define TWL4030_HF_CTL_HB_EN 0x04 |
203 | #define TWL4030_HF_CTL_LOOP_EN 0x08 | 218 | #define TWL4030_HF_CTL_LOOP_EN 0x08 |
diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c index a2c5064a774b..ddefb8f80145 100644 --- a/sound/soc/codecs/uda134x.c +++ b/sound/soc/codecs/uda134x.c | |||
@@ -173,7 +173,7 @@ static int uda134x_startup(struct snd_pcm_substream *substream, | |||
173 | { | 173 | { |
174 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 174 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
175 | struct snd_soc_device *socdev = rtd->socdev; | 175 | struct snd_soc_device *socdev = rtd->socdev; |
176 | struct snd_soc_codec *codec = socdev->codec; | 176 | struct snd_soc_codec *codec = socdev->card->codec; |
177 | struct uda134x_priv *uda134x = codec->private_data; | 177 | struct uda134x_priv *uda134x = codec->private_data; |
178 | struct snd_pcm_runtime *master_runtime; | 178 | struct snd_pcm_runtime *master_runtime; |
179 | 179 | ||
@@ -206,7 +206,7 @@ static void uda134x_shutdown(struct snd_pcm_substream *substream, | |||
206 | { | 206 | { |
207 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 207 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
208 | struct snd_soc_device *socdev = rtd->socdev; | 208 | struct snd_soc_device *socdev = rtd->socdev; |
209 | struct snd_soc_codec *codec = socdev->codec; | 209 | struct snd_soc_codec *codec = socdev->card->codec; |
210 | struct uda134x_priv *uda134x = codec->private_data; | 210 | struct uda134x_priv *uda134x = codec->private_data; |
211 | 211 | ||
212 | if (uda134x->master_substream == substream) | 212 | if (uda134x->master_substream == substream) |
@@ -221,7 +221,7 @@ static int uda134x_hw_params(struct snd_pcm_substream *substream, | |||
221 | { | 221 | { |
222 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 222 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
223 | struct snd_soc_device *socdev = rtd->socdev; | 223 | struct snd_soc_device *socdev = rtd->socdev; |
224 | struct snd_soc_codec *codec = socdev->codec; | 224 | struct snd_soc_codec *codec = socdev->card->codec; |
225 | struct uda134x_priv *uda134x = codec->private_data; | 225 | struct uda134x_priv *uda134x = codec->private_data; |
226 | u8 hw_params; | 226 | u8 hw_params; |
227 | 227 | ||
@@ -431,38 +431,14 @@ SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]), | |||
431 | SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0), | 431 | SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0), |
432 | }; | 432 | }; |
433 | 433 | ||
434 | static int uda134x_add_controls(struct snd_soc_codec *codec) | 434 | static struct snd_soc_dai_ops uda134x_dai_ops = { |
435 | { | 435 | .startup = uda134x_startup, |
436 | int err, i, n; | 436 | .shutdown = uda134x_shutdown, |
437 | const struct snd_kcontrol_new *ctrls; | 437 | .hw_params = uda134x_hw_params, |
438 | struct uda134x_platform_data *pd = codec->control_data; | 438 | .digital_mute = uda134x_mute, |
439 | 439 | .set_sysclk = uda134x_set_dai_sysclk, | |
440 | switch (pd->model) { | 440 | .set_fmt = uda134x_set_dai_fmt, |
441 | case UDA134X_UDA1340: | 441 | }; |
442 | case UDA134X_UDA1344: | ||
443 | n = ARRAY_SIZE(uda1340_snd_controls); | ||
444 | ctrls = uda1340_snd_controls; | ||
445 | break; | ||
446 | case UDA134X_UDA1341: | ||
447 | n = ARRAY_SIZE(uda1341_snd_controls); | ||
448 | ctrls = uda1341_snd_controls; | ||
449 | break; | ||
450 | default: | ||
451 | printk(KERN_ERR "%s unkown codec type: %d", | ||
452 | __func__, pd->model); | ||
453 | return -EINVAL; | ||
454 | } | ||
455 | |||
456 | for (i = 0; i < n; i++) { | ||
457 | err = snd_ctl_add(codec->card, | ||
458 | snd_soc_cnew(&ctrls[i], | ||
459 | codec, NULL)); | ||
460 | if (err < 0) | ||
461 | return err; | ||
462 | } | ||
463 | |||
464 | return 0; | ||
465 | } | ||
466 | 442 | ||
467 | struct snd_soc_dai uda134x_dai = { | 443 | struct snd_soc_dai uda134x_dai = { |
468 | .name = "UDA134X", | 444 | .name = "UDA134X", |
@@ -483,14 +459,7 @@ struct snd_soc_dai uda134x_dai = { | |||
483 | .formats = UDA134X_FORMATS, | 459 | .formats = UDA134X_FORMATS, |
484 | }, | 460 | }, |
485 | /* pcm operations */ | 461 | /* pcm operations */ |
486 | .ops = { | 462 | .ops = &uda134x_dai_ops, |
487 | .startup = uda134x_startup, | ||
488 | .shutdown = uda134x_shutdown, | ||
489 | .hw_params = uda134x_hw_params, | ||
490 | .digital_mute = uda134x_mute, | ||
491 | .set_sysclk = uda134x_set_dai_sysclk, | ||
492 | .set_fmt = uda134x_set_dai_fmt, | ||
493 | } | ||
494 | }; | 463 | }; |
495 | EXPORT_SYMBOL(uda134x_dai); | 464 | EXPORT_SYMBOL(uda134x_dai); |
496 | 465 | ||
@@ -525,11 +494,11 @@ static int uda134x_soc_probe(struct platform_device *pdev) | |||
525 | return -EINVAL; | 494 | return -EINVAL; |
526 | } | 495 | } |
527 | 496 | ||
528 | socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | 497 | socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); |
529 | if (socdev->codec == NULL) | 498 | if (socdev->card->codec == NULL) |
530 | return ret; | 499 | return ret; |
531 | 500 | ||
532 | codec = socdev->codec; | 501 | codec = socdev->card->codec; |
533 | 502 | ||
534 | uda134x = kzalloc(sizeof(struct uda134x_priv), GFP_KERNEL); | 503 | uda134x = kzalloc(sizeof(struct uda134x_priv), GFP_KERNEL); |
535 | if (uda134x == NULL) | 504 | if (uda134x == NULL) |
@@ -572,7 +541,22 @@ static int uda134x_soc_probe(struct platform_device *pdev) | |||
572 | goto pcm_err; | 541 | goto pcm_err; |
573 | } | 542 | } |
574 | 543 | ||
575 | ret = uda134x_add_controls(codec); | 544 | switch (pd->model) { |
545 | case UDA134X_UDA1340: | ||
546 | case UDA134X_UDA1344: | ||
547 | ret = snd_soc_add_controls(codec, uda1340_snd_controls, | ||
548 | ARRAY_SIZE(uda1340_snd_controls)); | ||
549 | break; | ||
550 | case UDA134X_UDA1341: | ||
551 | ret = snd_soc_add_controls(codec, uda1341_snd_controls, | ||
552 | ARRAY_SIZE(uda1341_snd_controls)); | ||
553 | break; | ||
554 | default: | ||
555 | printk(KERN_ERR "%s unkown codec type: %d", | ||
556 | __func__, pd->model); | ||
557 | return -EINVAL; | ||
558 | } | ||
559 | |||
576 | if (ret < 0) { | 560 | if (ret < 0) { |
577 | printk(KERN_ERR "UDA134X: failed to register controls\n"); | 561 | printk(KERN_ERR "UDA134X: failed to register controls\n"); |
578 | goto pcm_err; | 562 | goto pcm_err; |
@@ -602,7 +586,7 @@ priv_err: | |||
602 | static int uda134x_soc_remove(struct platform_device *pdev) | 586 | static int uda134x_soc_remove(struct platform_device *pdev) |
603 | { | 587 | { |
604 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 588 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
605 | struct snd_soc_codec *codec = socdev->codec; | 589 | struct snd_soc_codec *codec = socdev->card->codec; |
606 | 590 | ||
607 | uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 591 | uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
608 | uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF); | 592 | uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF); |
@@ -622,7 +606,7 @@ static int uda134x_soc_suspend(struct platform_device *pdev, | |||
622 | pm_message_t state) | 606 | pm_message_t state) |
623 | { | 607 | { |
624 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 608 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
625 | struct snd_soc_codec *codec = socdev->codec; | 609 | struct snd_soc_codec *codec = socdev->card->codec; |
626 | 610 | ||
627 | uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 611 | uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
628 | uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF); | 612 | uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF); |
@@ -632,7 +616,7 @@ static int uda134x_soc_suspend(struct platform_device *pdev, | |||
632 | static int uda134x_soc_resume(struct platform_device *pdev) | 616 | static int uda134x_soc_resume(struct platform_device *pdev) |
633 | { | 617 | { |
634 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 618 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
635 | struct snd_soc_codec *codec = socdev->codec; | 619 | struct snd_soc_codec *codec = socdev->card->codec; |
636 | 620 | ||
637 | uda134x_set_bias_level(codec, SND_SOC_BIAS_PREPARE); | 621 | uda134x_set_bias_level(codec, SND_SOC_BIAS_PREPARE); |
638 | uda134x_set_bias_level(codec, SND_SOC_BIAS_ON); | 622 | uda134x_set_bias_level(codec, SND_SOC_BIAS_ON); |
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c index e6bf0844fbf3..5b21594e0e58 100644 --- a/sound/soc/codecs/uda1380.c +++ b/sound/soc/codecs/uda1380.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/ioctl.h> | 25 | #include <linux/ioctl.h> |
26 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
27 | #include <linux/i2c.h> | 27 | #include <linux/i2c.h> |
28 | #include <linux/workqueue.h> | ||
28 | #include <sound/core.h> | 29 | #include <sound/core.h> |
29 | #include <sound/control.h> | 30 | #include <sound/control.h> |
30 | #include <sound/initval.h> | 31 | #include <sound/initval.h> |
@@ -35,7 +36,8 @@ | |||
35 | 36 | ||
36 | #include "uda1380.h" | 37 | #include "uda1380.h" |
37 | 38 | ||
38 | #define UDA1380_VERSION "0.6" | 39 | static struct work_struct uda1380_work; |
40 | static struct snd_soc_codec *uda1380_codec; | ||
39 | 41 | ||
40 | /* | 42 | /* |
41 | * uda1380 register cache | 43 | * uda1380 register cache |
@@ -52,6 +54,8 @@ static const u16 uda1380_reg[UDA1380_CACHEREGNUM] = { | |||
52 | 0x0000, 0x8000, 0x0002, 0x0000, | 54 | 0x0000, 0x8000, 0x0002, 0x0000, |
53 | }; | 55 | }; |
54 | 56 | ||
57 | static unsigned long uda1380_cache_dirty; | ||
58 | |||
55 | /* | 59 | /* |
56 | * read uda1380 register cache | 60 | * read uda1380 register cache |
57 | */ | 61 | */ |
@@ -73,8 +77,11 @@ static inline void uda1380_write_reg_cache(struct snd_soc_codec *codec, | |||
73 | u16 reg, unsigned int value) | 77 | u16 reg, unsigned int value) |
74 | { | 78 | { |
75 | u16 *cache = codec->reg_cache; | 79 | u16 *cache = codec->reg_cache; |
80 | |||
76 | if (reg >= UDA1380_CACHEREGNUM) | 81 | if (reg >= UDA1380_CACHEREGNUM) |
77 | return; | 82 | return; |
83 | if ((reg >= 0x10) && (cache[reg] != value)) | ||
84 | set_bit(reg - 0x10, &uda1380_cache_dirty); | ||
78 | cache[reg] = value; | 85 | cache[reg] = value; |
79 | } | 86 | } |
80 | 87 | ||
@@ -113,6 +120,8 @@ static int uda1380_write(struct snd_soc_codec *codec, unsigned int reg, | |||
113 | (data[0]<<8) | data[1]); | 120 | (data[0]<<8) | data[1]); |
114 | return -EIO; | 121 | return -EIO; |
115 | } | 122 | } |
123 | if (reg >= 0x10) | ||
124 | clear_bit(reg - 0x10, &uda1380_cache_dirty); | ||
116 | return 0; | 125 | return 0; |
117 | } else | 126 | } else |
118 | return -EIO; | 127 | return -EIO; |
@@ -120,6 +129,20 @@ static int uda1380_write(struct snd_soc_codec *codec, unsigned int reg, | |||
120 | 129 | ||
121 | #define uda1380_reset(c) uda1380_write(c, UDA1380_RESET, 0) | 130 | #define uda1380_reset(c) uda1380_write(c, UDA1380_RESET, 0) |
122 | 131 | ||
132 | static void uda1380_flush_work(struct work_struct *work) | ||
133 | { | ||
134 | int bit, reg; | ||
135 | |||
136 | for_each_bit(bit, &uda1380_cache_dirty, UDA1380_CACHEREGNUM - 0x10) { | ||
137 | reg = 0x10 + bit; | ||
138 | pr_debug("uda1380: flush reg %x val %x:\n", reg, | ||
139 | uda1380_read_reg_cache(uda1380_codec, reg)); | ||
140 | uda1380_write(uda1380_codec, reg, | ||
141 | uda1380_read_reg_cache(uda1380_codec, reg)); | ||
142 | clear_bit(bit, &uda1380_cache_dirty); | ||
143 | } | ||
144 | } | ||
145 | |||
123 | /* declarations of ALSA reg_elem_REAL controls */ | 146 | /* declarations of ALSA reg_elem_REAL controls */ |
124 | static const char *uda1380_deemp[] = { | 147 | static const char *uda1380_deemp[] = { |
125 | "None", | 148 | "None", |
@@ -254,7 +277,6 @@ static const struct snd_kcontrol_new uda1380_snd_controls[] = { | |||
254 | SOC_SINGLE("DAC Polarity inverting Switch", UDA1380_MIXER, 15, 1, 0), /* DA_POL_INV */ | 277 | SOC_SINGLE("DAC Polarity inverting Switch", UDA1380_MIXER, 15, 1, 0), /* DA_POL_INV */ |
255 | SOC_ENUM("Noise Shaper", uda1380_sel_ns_enum), /* SEL_NS */ | 278 | SOC_ENUM("Noise Shaper", uda1380_sel_ns_enum), /* SEL_NS */ |
256 | SOC_ENUM("Digital Mixer Signal Control", uda1380_mix_enum), /* MIX_POS, MIX */ | 279 | SOC_ENUM("Digital Mixer Signal Control", uda1380_mix_enum), /* MIX_POS, MIX */ |
257 | SOC_SINGLE("Silence Switch", UDA1380_MIXER, 7, 1, 0), /* SILENCE, force DAC output to silence */ | ||
258 | SOC_SINGLE("Silence Detector Switch", UDA1380_MIXER, 6, 1, 0), /* SDET_ON */ | 280 | SOC_SINGLE("Silence Detector Switch", UDA1380_MIXER, 6, 1, 0), /* SDET_ON */ |
259 | SOC_ENUM("Silence Detector Setting", uda1380_sdet_enum), /* SD_VALUE */ | 281 | SOC_ENUM("Silence Detector Setting", uda1380_sdet_enum), /* SD_VALUE */ |
260 | SOC_ENUM("Oversampling Input", uda1380_os_enum), /* OS */ | 282 | SOC_ENUM("Oversampling Input", uda1380_os_enum), /* OS */ |
@@ -271,21 +293,6 @@ static const struct snd_kcontrol_new uda1380_snd_controls[] = { | |||
271 | SOC_SINGLE("AGC Switch", UDA1380_AGC, 0, 1, 0), | 293 | SOC_SINGLE("AGC Switch", UDA1380_AGC, 0, 1, 0), |
272 | }; | 294 | }; |
273 | 295 | ||
274 | /* add non dapm controls */ | ||
275 | static int uda1380_add_controls(struct snd_soc_codec *codec) | ||
276 | { | ||
277 | int err, i; | ||
278 | |||
279 | for (i = 0; i < ARRAY_SIZE(uda1380_snd_controls); i++) { | ||
280 | err = snd_ctl_add(codec->card, | ||
281 | snd_soc_cnew(&uda1380_snd_controls[i], codec, NULL)); | ||
282 | if (err < 0) | ||
283 | return err; | ||
284 | } | ||
285 | |||
286 | return 0; | ||
287 | } | ||
288 | |||
289 | /* Input mux */ | 296 | /* Input mux */ |
290 | static const struct snd_kcontrol_new uda1380_input_mux_control = | 297 | static const struct snd_kcontrol_new uda1380_input_mux_control = |
291 | SOC_DAPM_ENUM("Route", uda1380_input_sel_enum); | 298 | SOC_DAPM_ENUM("Route", uda1380_input_sel_enum); |
@@ -371,7 +378,7 @@ static int uda1380_add_widgets(struct snd_soc_codec *codec) | |||
371 | return 0; | 378 | return 0; |
372 | } | 379 | } |
373 | 380 | ||
374 | static int uda1380_set_dai_fmt(struct snd_soc_dai *codec_dai, | 381 | static int uda1380_set_dai_fmt_both(struct snd_soc_dai *codec_dai, |
375 | unsigned int fmt) | 382 | unsigned int fmt) |
376 | { | 383 | { |
377 | struct snd_soc_codec *codec = codec_dai->codec; | 384 | struct snd_soc_codec *codec = codec_dai->codec; |
@@ -381,61 +388,107 @@ static int uda1380_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
381 | iface = uda1380_read_reg_cache(codec, UDA1380_IFACE); | 388 | iface = uda1380_read_reg_cache(codec, UDA1380_IFACE); |
382 | iface &= ~(R01_SFORI_MASK | R01_SIM | R01_SFORO_MASK); | 389 | iface &= ~(R01_SFORI_MASK | R01_SIM | R01_SFORO_MASK); |
383 | 390 | ||
384 | /* FIXME: how to select I2S for DATAO and MSB for DATAI correctly? */ | ||
385 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | 391 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
386 | case SND_SOC_DAIFMT_I2S: | 392 | case SND_SOC_DAIFMT_I2S: |
387 | iface |= R01_SFORI_I2S | R01_SFORO_I2S; | 393 | iface |= R01_SFORI_I2S | R01_SFORO_I2S; |
388 | break; | 394 | break; |
389 | case SND_SOC_DAIFMT_LSB: | 395 | case SND_SOC_DAIFMT_LSB: |
390 | iface |= R01_SFORI_LSB16 | R01_SFORO_I2S; | 396 | iface |= R01_SFORI_LSB16 | R01_SFORO_LSB16; |
391 | break; | 397 | break; |
392 | case SND_SOC_DAIFMT_MSB: | 398 | case SND_SOC_DAIFMT_MSB: |
393 | iface |= R01_SFORI_MSB | R01_SFORO_I2S; | 399 | iface |= R01_SFORI_MSB | R01_SFORO_MSB; |
394 | } | 400 | } |
395 | 401 | ||
396 | if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) == SND_SOC_DAIFMT_CBM_CFM) | 402 | /* DATAI is slave only, so in single-link mode, this has to be slave */ |
397 | iface |= R01_SIM; | 403 | if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) |
404 | return -EINVAL; | ||
398 | 405 | ||
399 | uda1380_write(codec, UDA1380_IFACE, iface); | 406 | uda1380_write(codec, UDA1380_IFACE, iface); |
400 | 407 | ||
401 | return 0; | 408 | return 0; |
402 | } | 409 | } |
403 | 410 | ||
404 | /* | 411 | static int uda1380_set_dai_fmt_playback(struct snd_soc_dai *codec_dai, |
405 | * Flush reg cache | 412 | unsigned int fmt) |
406 | * We can only write the interpolator and decimator registers | ||
407 | * when the DAI is being clocked by the CPU DAI. It's up to the | ||
408 | * machine and cpu DAI driver to do this before we are called. | ||
409 | */ | ||
410 | static int uda1380_pcm_prepare(struct snd_pcm_substream *substream, | ||
411 | struct snd_soc_dai *dai) | ||
412 | { | 413 | { |
413 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 414 | struct snd_soc_codec *codec = codec_dai->codec; |
414 | struct snd_soc_device *socdev = rtd->socdev; | 415 | int iface; |
415 | struct snd_soc_codec *codec = socdev->codec; | 416 | |
416 | int reg, reg_start, reg_end, clk; | 417 | /* set up DAI based upon fmt */ |
417 | 418 | iface = uda1380_read_reg_cache(codec, UDA1380_IFACE); | |
418 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 419 | iface &= ~R01_SFORI_MASK; |
419 | reg_start = UDA1380_MVOL; | 420 | |
420 | reg_end = UDA1380_MIXER; | 421 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
421 | } else { | 422 | case SND_SOC_DAIFMT_I2S: |
422 | reg_start = UDA1380_DEC; | 423 | iface |= R01_SFORI_I2S; |
423 | reg_end = UDA1380_AGC; | 424 | break; |
425 | case SND_SOC_DAIFMT_LSB: | ||
426 | iface |= R01_SFORI_LSB16; | ||
427 | break; | ||
428 | case SND_SOC_DAIFMT_MSB: | ||
429 | iface |= R01_SFORI_MSB; | ||
424 | } | 430 | } |
425 | 431 | ||
426 | /* FIXME disable DAC_CLK */ | 432 | /* DATAI is slave only, so this has to be slave */ |
427 | clk = uda1380_read_reg_cache(codec, UDA1380_CLK); | 433 | if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) |
428 | uda1380_write(codec, UDA1380_CLK, clk & ~R00_DAC_CLK); | 434 | return -EINVAL; |
435 | |||
436 | uda1380_write(codec, UDA1380_IFACE, iface); | ||
437 | |||
438 | return 0; | ||
439 | } | ||
440 | |||
441 | static int uda1380_set_dai_fmt_capture(struct snd_soc_dai *codec_dai, | ||
442 | unsigned int fmt) | ||
443 | { | ||
444 | struct snd_soc_codec *codec = codec_dai->codec; | ||
445 | int iface; | ||
446 | |||
447 | /* set up DAI based upon fmt */ | ||
448 | iface = uda1380_read_reg_cache(codec, UDA1380_IFACE); | ||
449 | iface &= ~(R01_SIM | R01_SFORO_MASK); | ||
429 | 450 | ||
430 | for (reg = reg_start; reg <= reg_end; reg++) { | 451 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
431 | pr_debug("uda1380: flush reg %x val %x:", reg, | 452 | case SND_SOC_DAIFMT_I2S: |
432 | uda1380_read_reg_cache(codec, reg)); | 453 | iface |= R01_SFORO_I2S; |
433 | uda1380_write(codec, reg, uda1380_read_reg_cache(codec, reg)); | 454 | break; |
455 | case SND_SOC_DAIFMT_LSB: | ||
456 | iface |= R01_SFORO_LSB16; | ||
457 | break; | ||
458 | case SND_SOC_DAIFMT_MSB: | ||
459 | iface |= R01_SFORO_MSB; | ||
434 | } | 460 | } |
435 | 461 | ||
436 | /* FIXME enable DAC_CLK */ | 462 | if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) == SND_SOC_DAIFMT_CBM_CFM) |
437 | uda1380_write(codec, UDA1380_CLK, clk | R00_DAC_CLK); | 463 | iface |= R01_SIM; |
438 | 464 | ||
465 | uda1380_write(codec, UDA1380_IFACE, iface); | ||
466 | |||
467 | return 0; | ||
468 | } | ||
469 | |||
470 | static int uda1380_trigger(struct snd_pcm_substream *substream, int cmd, | ||
471 | struct snd_soc_dai *dai) | ||
472 | { | ||
473 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
474 | struct snd_soc_device *socdev = rtd->socdev; | ||
475 | struct snd_soc_codec *codec = socdev->card->codec; | ||
476 | int mixer = uda1380_read_reg_cache(codec, UDA1380_MIXER); | ||
477 | |||
478 | switch (cmd) { | ||
479 | case SNDRV_PCM_TRIGGER_START: | ||
480 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
481 | uda1380_write_reg_cache(codec, UDA1380_MIXER, | ||
482 | mixer & ~R14_SILENCE); | ||
483 | schedule_work(&uda1380_work); | ||
484 | break; | ||
485 | case SNDRV_PCM_TRIGGER_STOP: | ||
486 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
487 | uda1380_write_reg_cache(codec, UDA1380_MIXER, | ||
488 | mixer | R14_SILENCE); | ||
489 | schedule_work(&uda1380_work); | ||
490 | break; | ||
491 | } | ||
439 | return 0; | 492 | return 0; |
440 | } | 493 | } |
441 | 494 | ||
@@ -445,7 +498,7 @@ static int uda1380_pcm_hw_params(struct snd_pcm_substream *substream, | |||
445 | { | 498 | { |
446 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 499 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
447 | struct snd_soc_device *socdev = rtd->socdev; | 500 | struct snd_soc_device *socdev = rtd->socdev; |
448 | struct snd_soc_codec *codec = socdev->codec; | 501 | struct snd_soc_codec *codec = socdev->card->codec; |
449 | u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK); | 502 | u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK); |
450 | 503 | ||
451 | /* set WSPLL power and divider if running from this clock */ | 504 | /* set WSPLL power and divider if running from this clock */ |
@@ -484,7 +537,7 @@ static void uda1380_pcm_shutdown(struct snd_pcm_substream *substream, | |||
484 | { | 537 | { |
485 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 538 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
486 | struct snd_soc_device *socdev = rtd->socdev; | 539 | struct snd_soc_device *socdev = rtd->socdev; |
487 | struct snd_soc_codec *codec = socdev->codec; | 540 | struct snd_soc_codec *codec = socdev->card->codec; |
488 | u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK); | 541 | u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK); |
489 | 542 | ||
490 | /* shut down WSPLL power if running from this clock */ | 543 | /* shut down WSPLL power if running from this clock */ |
@@ -501,24 +554,6 @@ static void uda1380_pcm_shutdown(struct snd_pcm_substream *substream, | |||
501 | uda1380_write(codec, UDA1380_CLK, clk); | 554 | uda1380_write(codec, UDA1380_CLK, clk); |
502 | } | 555 | } |
503 | 556 | ||
504 | static int uda1380_mute(struct snd_soc_dai *codec_dai, int mute) | ||
505 | { | ||
506 | struct snd_soc_codec *codec = codec_dai->codec; | ||
507 | u16 mute_reg = uda1380_read_reg_cache(codec, UDA1380_DEEMP) & ~R13_MTM; | ||
508 | |||
509 | /* FIXME: mute(codec,0) is called when the magician clock is already | ||
510 | * set to WSPLL, but for some unknown reason writing to interpolator | ||
511 | * registers works only when clocked by SYSCLK */ | ||
512 | u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK); | ||
513 | uda1380_write(codec, UDA1380_CLK, ~R00_DAC_CLK & clk); | ||
514 | if (mute) | ||
515 | uda1380_write(codec, UDA1380_DEEMP, mute_reg | R13_MTM); | ||
516 | else | ||
517 | uda1380_write(codec, UDA1380_DEEMP, mute_reg); | ||
518 | uda1380_write(codec, UDA1380_CLK, clk); | ||
519 | return 0; | ||
520 | } | ||
521 | |||
522 | static int uda1380_set_bias_level(struct snd_soc_codec *codec, | 557 | static int uda1380_set_bias_level(struct snd_soc_codec *codec, |
523 | enum snd_soc_bias_level level) | 558 | enum snd_soc_bias_level level) |
524 | { | 559 | { |
@@ -544,6 +579,27 @@ static int uda1380_set_bias_level(struct snd_soc_codec *codec, | |||
544 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\ | 579 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\ |
545 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) | 580 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) |
546 | 581 | ||
582 | static struct snd_soc_dai_ops uda1380_dai_ops = { | ||
583 | .hw_params = uda1380_pcm_hw_params, | ||
584 | .shutdown = uda1380_pcm_shutdown, | ||
585 | .trigger = uda1380_trigger, | ||
586 | .set_fmt = uda1380_set_dai_fmt_both, | ||
587 | }; | ||
588 | |||
589 | static struct snd_soc_dai_ops uda1380_dai_ops_playback = { | ||
590 | .hw_params = uda1380_pcm_hw_params, | ||
591 | .shutdown = uda1380_pcm_shutdown, | ||
592 | .trigger = uda1380_trigger, | ||
593 | .set_fmt = uda1380_set_dai_fmt_playback, | ||
594 | }; | ||
595 | |||
596 | static struct snd_soc_dai_ops uda1380_dai_ops_capture = { | ||
597 | .hw_params = uda1380_pcm_hw_params, | ||
598 | .shutdown = uda1380_pcm_shutdown, | ||
599 | .trigger = uda1380_trigger, | ||
600 | .set_fmt = uda1380_set_dai_fmt_capture, | ||
601 | }; | ||
602 | |||
547 | struct snd_soc_dai uda1380_dai[] = { | 603 | struct snd_soc_dai uda1380_dai[] = { |
548 | { | 604 | { |
549 | .name = "UDA1380", | 605 | .name = "UDA1380", |
@@ -559,13 +615,7 @@ struct snd_soc_dai uda1380_dai[] = { | |||
559 | .channels_max = 2, | 615 | .channels_max = 2, |
560 | .rates = UDA1380_RATES, | 616 | .rates = UDA1380_RATES, |
561 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | 617 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, |
562 | .ops = { | 618 | .ops = &uda1380_dai_ops, |
563 | .hw_params = uda1380_pcm_hw_params, | ||
564 | .shutdown = uda1380_pcm_shutdown, | ||
565 | .prepare = uda1380_pcm_prepare, | ||
566 | .digital_mute = uda1380_mute, | ||
567 | .set_fmt = uda1380_set_dai_fmt, | ||
568 | }, | ||
569 | }, | 619 | }, |
570 | { /* playback only - dual interface */ | 620 | { /* playback only - dual interface */ |
571 | .name = "UDA1380", | 621 | .name = "UDA1380", |
@@ -576,13 +626,7 @@ struct snd_soc_dai uda1380_dai[] = { | |||
576 | .rates = UDA1380_RATES, | 626 | .rates = UDA1380_RATES, |
577 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 627 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
578 | }, | 628 | }, |
579 | .ops = { | 629 | .ops = &uda1380_dai_ops_playback, |
580 | .hw_params = uda1380_pcm_hw_params, | ||
581 | .shutdown = uda1380_pcm_shutdown, | ||
582 | .prepare = uda1380_pcm_prepare, | ||
583 | .digital_mute = uda1380_mute, | ||
584 | .set_fmt = uda1380_set_dai_fmt, | ||
585 | }, | ||
586 | }, | 630 | }, |
587 | { /* capture only - dual interface*/ | 631 | { /* capture only - dual interface*/ |
588 | .name = "UDA1380", | 632 | .name = "UDA1380", |
@@ -593,12 +637,7 @@ struct snd_soc_dai uda1380_dai[] = { | |||
593 | .rates = UDA1380_RATES, | 637 | .rates = UDA1380_RATES, |
594 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 638 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
595 | }, | 639 | }, |
596 | .ops = { | 640 | .ops = &uda1380_dai_ops_capture, |
597 | .hw_params = uda1380_pcm_hw_params, | ||
598 | .shutdown = uda1380_pcm_shutdown, | ||
599 | .prepare = uda1380_pcm_prepare, | ||
600 | .set_fmt = uda1380_set_dai_fmt, | ||
601 | }, | ||
602 | }, | 641 | }, |
603 | }; | 642 | }; |
604 | EXPORT_SYMBOL_GPL(uda1380_dai); | 643 | EXPORT_SYMBOL_GPL(uda1380_dai); |
@@ -606,7 +645,7 @@ EXPORT_SYMBOL_GPL(uda1380_dai); | |||
606 | static int uda1380_suspend(struct platform_device *pdev, pm_message_t state) | 645 | static int uda1380_suspend(struct platform_device *pdev, pm_message_t state) |
607 | { | 646 | { |
608 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 647 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
609 | struct snd_soc_codec *codec = socdev->codec; | 648 | struct snd_soc_codec *codec = socdev->card->codec; |
610 | 649 | ||
611 | uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF); | 650 | uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF); |
612 | return 0; | 651 | return 0; |
@@ -615,7 +654,7 @@ static int uda1380_suspend(struct platform_device *pdev, pm_message_t state) | |||
615 | static int uda1380_resume(struct platform_device *pdev) | 654 | static int uda1380_resume(struct platform_device *pdev) |
616 | { | 655 | { |
617 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 656 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
618 | struct snd_soc_codec *codec = socdev->codec; | 657 | struct snd_soc_codec *codec = socdev->card->codec; |
619 | int i; | 658 | int i; |
620 | u8 data[2]; | 659 | u8 data[2]; |
621 | u16 *cache = codec->reg_cache; | 660 | u16 *cache = codec->reg_cache; |
@@ -637,7 +676,7 @@ static int uda1380_resume(struct platform_device *pdev) | |||
637 | */ | 676 | */ |
638 | static int uda1380_init(struct snd_soc_device *socdev, int dac_clk) | 677 | static int uda1380_init(struct snd_soc_device *socdev, int dac_clk) |
639 | { | 678 | { |
640 | struct snd_soc_codec *codec = socdev->codec; | 679 | struct snd_soc_codec *codec = socdev->card->codec; |
641 | int ret = 0; | 680 | int ret = 0; |
642 | 681 | ||
643 | codec->name = "UDA1380"; | 682 | codec->name = "UDA1380"; |
@@ -655,6 +694,9 @@ static int uda1380_init(struct snd_soc_device *socdev, int dac_clk) | |||
655 | codec->reg_cache_step = 1; | 694 | codec->reg_cache_step = 1; |
656 | uda1380_reset(codec); | 695 | uda1380_reset(codec); |
657 | 696 | ||
697 | uda1380_codec = codec; | ||
698 | INIT_WORK(&uda1380_work, uda1380_flush_work); | ||
699 | |||
658 | /* register pcms */ | 700 | /* register pcms */ |
659 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | 701 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); |
660 | if (ret < 0) { | 702 | if (ret < 0) { |
@@ -675,7 +717,8 @@ static int uda1380_init(struct snd_soc_device *socdev, int dac_clk) | |||
675 | } | 717 | } |
676 | 718 | ||
677 | /* uda1380 init */ | 719 | /* uda1380 init */ |
678 | uda1380_add_controls(codec); | 720 | snd_soc_add_controls(codec, uda1380_snd_controls, |
721 | ARRAY_SIZE(uda1380_snd_controls)); | ||
679 | uda1380_add_widgets(codec); | 722 | uda1380_add_widgets(codec); |
680 | ret = snd_soc_init_card(socdev); | 723 | ret = snd_soc_init_card(socdev); |
681 | if (ret < 0) { | 724 | if (ret < 0) { |
@@ -702,7 +745,7 @@ static int uda1380_i2c_probe(struct i2c_client *i2c, | |||
702 | { | 745 | { |
703 | struct snd_soc_device *socdev = uda1380_socdev; | 746 | struct snd_soc_device *socdev = uda1380_socdev; |
704 | struct uda1380_setup_data *setup = socdev->codec_data; | 747 | struct uda1380_setup_data *setup = socdev->codec_data; |
705 | struct snd_soc_codec *codec = socdev->codec; | 748 | struct snd_soc_codec *codec = socdev->card->codec; |
706 | int ret; | 749 | int ret; |
707 | 750 | ||
708 | i2c_set_clientdata(i2c, codec); | 751 | i2c_set_clientdata(i2c, codec); |
@@ -786,14 +829,12 @@ static int uda1380_probe(struct platform_device *pdev) | |||
786 | struct snd_soc_codec *codec; | 829 | struct snd_soc_codec *codec; |
787 | int ret; | 830 | int ret; |
788 | 831 | ||
789 | pr_info("UDA1380 Audio Codec %s", UDA1380_VERSION); | ||
790 | |||
791 | setup = socdev->codec_data; | 832 | setup = socdev->codec_data; |
792 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | 833 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); |
793 | if (codec == NULL) | 834 | if (codec == NULL) |
794 | return -ENOMEM; | 835 | return -ENOMEM; |
795 | 836 | ||
796 | socdev->codec = codec; | 837 | socdev->card->codec = codec; |
797 | mutex_init(&codec->mutex); | 838 | mutex_init(&codec->mutex); |
798 | INIT_LIST_HEAD(&codec->dapm_widgets); | 839 | INIT_LIST_HEAD(&codec->dapm_widgets); |
799 | INIT_LIST_HEAD(&codec->dapm_paths); | 840 | INIT_LIST_HEAD(&codec->dapm_paths); |
@@ -817,7 +858,7 @@ static int uda1380_probe(struct platform_device *pdev) | |||
817 | static int uda1380_remove(struct platform_device *pdev) | 858 | static int uda1380_remove(struct platform_device *pdev) |
818 | { | 859 | { |
819 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 860 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
820 | struct snd_soc_codec *codec = socdev->codec; | 861 | struct snd_soc_codec *codec = socdev->card->codec; |
821 | 862 | ||
822 | if (codec->control_data) | 863 | if (codec->control_data) |
823 | uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF); | 864 | uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF); |
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index 35d99750c383..3b1d0993bed9 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c | |||
@@ -51,10 +51,17 @@ struct wm8350_output { | |||
51 | u16 mute; | 51 | u16 mute; |
52 | }; | 52 | }; |
53 | 53 | ||
54 | struct wm8350_jack_data { | ||
55 | struct snd_soc_jack *jack; | ||
56 | int report; | ||
57 | }; | ||
58 | |||
54 | struct wm8350_data { | 59 | struct wm8350_data { |
55 | struct snd_soc_codec codec; | 60 | struct snd_soc_codec codec; |
56 | struct wm8350_output out1; | 61 | struct wm8350_output out1; |
57 | struct wm8350_output out2; | 62 | struct wm8350_output out2; |
63 | struct wm8350_jack_data hpl; | ||
64 | struct wm8350_jack_data hpr; | ||
58 | struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; | 65 | struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; |
59 | }; | 66 | }; |
60 | 67 | ||
@@ -775,21 +782,6 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
775 | {"Beep", NULL, "IN3R PGA"}, | 782 | {"Beep", NULL, "IN3R PGA"}, |
776 | }; | 783 | }; |
777 | 784 | ||
778 | static int wm8350_add_controls(struct snd_soc_codec *codec) | ||
779 | { | ||
780 | int err, i; | ||
781 | |||
782 | for (i = 0; i < ARRAY_SIZE(wm8350_snd_controls); i++) { | ||
783 | err = snd_ctl_add(codec->card, | ||
784 | snd_soc_cnew(&wm8350_snd_controls[i], | ||
785 | codec, NULL)); | ||
786 | if (err < 0) | ||
787 | return err; | ||
788 | } | ||
789 | |||
790 | return 0; | ||
791 | } | ||
792 | |||
793 | static int wm8350_add_widgets(struct snd_soc_codec *codec) | 785 | static int wm8350_add_widgets(struct snd_soc_codec *codec) |
794 | { | 786 | { |
795 | int ret; | 787 | int ret; |
@@ -1309,7 +1301,7 @@ static int wm8350_set_bias_level(struct snd_soc_codec *codec, | |||
1309 | static int wm8350_suspend(struct platform_device *pdev, pm_message_t state) | 1301 | static int wm8350_suspend(struct platform_device *pdev, pm_message_t state) |
1310 | { | 1302 | { |
1311 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1303 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
1312 | struct snd_soc_codec *codec = socdev->codec; | 1304 | struct snd_soc_codec *codec = socdev->card->codec; |
1313 | 1305 | ||
1314 | wm8350_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1306 | wm8350_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1315 | return 0; | 1307 | return 0; |
@@ -1318,7 +1310,7 @@ static int wm8350_suspend(struct platform_device *pdev, pm_message_t state) | |||
1318 | static int wm8350_resume(struct platform_device *pdev) | 1310 | static int wm8350_resume(struct platform_device *pdev) |
1319 | { | 1311 | { |
1320 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1312 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
1321 | struct snd_soc_codec *codec = socdev->codec; | 1313 | struct snd_soc_codec *codec = socdev->card->codec; |
1322 | 1314 | ||
1323 | wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1315 | wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1324 | 1316 | ||
@@ -1328,6 +1320,95 @@ static int wm8350_resume(struct platform_device *pdev) | |||
1328 | return 0; | 1320 | return 0; |
1329 | } | 1321 | } |
1330 | 1322 | ||
1323 | static void wm8350_hp_jack_handler(struct wm8350 *wm8350, int irq, void *data) | ||
1324 | { | ||
1325 | struct wm8350_data *priv = data; | ||
1326 | u16 reg; | ||
1327 | int report; | ||
1328 | int mask; | ||
1329 | struct wm8350_jack_data *jack = NULL; | ||
1330 | |||
1331 | switch (irq) { | ||
1332 | case WM8350_IRQ_CODEC_JCK_DET_L: | ||
1333 | jack = &priv->hpl; | ||
1334 | mask = WM8350_JACK_L_LVL; | ||
1335 | break; | ||
1336 | |||
1337 | case WM8350_IRQ_CODEC_JCK_DET_R: | ||
1338 | jack = &priv->hpr; | ||
1339 | mask = WM8350_JACK_R_LVL; | ||
1340 | break; | ||
1341 | |||
1342 | default: | ||
1343 | BUG(); | ||
1344 | } | ||
1345 | |||
1346 | if (!jack->jack) { | ||
1347 | dev_warn(wm8350->dev, "Jack interrupt called with no jack\n"); | ||
1348 | return; | ||
1349 | } | ||
1350 | |||
1351 | /* Debounce */ | ||
1352 | msleep(200); | ||
1353 | |||
1354 | reg = wm8350_reg_read(wm8350, WM8350_JACK_PIN_STATUS); | ||
1355 | if (reg & mask) | ||
1356 | report = jack->report; | ||
1357 | else | ||
1358 | report = 0; | ||
1359 | |||
1360 | snd_soc_jack_report(jack->jack, report, jack->report); | ||
1361 | } | ||
1362 | |||
1363 | /** | ||
1364 | * wm8350_hp_jack_detect - Enable headphone jack detection. | ||
1365 | * | ||
1366 | * @codec: WM8350 codec | ||
1367 | * @which: left or right jack detect signal | ||
1368 | * @jack: jack to report detection events on | ||
1369 | * @report: value to report | ||
1370 | * | ||
1371 | * Enables the headphone jack detection of the WM8350. | ||
1372 | */ | ||
1373 | int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which, | ||
1374 | struct snd_soc_jack *jack, int report) | ||
1375 | { | ||
1376 | struct wm8350_data *priv = codec->private_data; | ||
1377 | struct wm8350 *wm8350 = codec->control_data; | ||
1378 | int irq; | ||
1379 | int ena; | ||
1380 | |||
1381 | switch (which) { | ||
1382 | case WM8350_JDL: | ||
1383 | priv->hpl.jack = jack; | ||
1384 | priv->hpl.report = report; | ||
1385 | irq = WM8350_IRQ_CODEC_JCK_DET_L; | ||
1386 | ena = WM8350_JDL_ENA; | ||
1387 | break; | ||
1388 | |||
1389 | case WM8350_JDR: | ||
1390 | priv->hpr.jack = jack; | ||
1391 | priv->hpr.report = report; | ||
1392 | irq = WM8350_IRQ_CODEC_JCK_DET_R; | ||
1393 | ena = WM8350_JDR_ENA; | ||
1394 | break; | ||
1395 | |||
1396 | default: | ||
1397 | return -EINVAL; | ||
1398 | } | ||
1399 | |||
1400 | wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_TOCLK_ENA); | ||
1401 | wm8350_set_bits(wm8350, WM8350_JACK_DETECT, ena); | ||
1402 | |||
1403 | /* Sync status */ | ||
1404 | wm8350_hp_jack_handler(wm8350, irq, priv); | ||
1405 | |||
1406 | wm8350_unmask_irq(wm8350, irq); | ||
1407 | |||
1408 | return 0; | ||
1409 | } | ||
1410 | EXPORT_SYMBOL_GPL(wm8350_hp_jack_detect); | ||
1411 | |||
1331 | static struct snd_soc_codec *wm8350_codec; | 1412 | static struct snd_soc_codec *wm8350_codec; |
1332 | 1413 | ||
1333 | static int wm8350_probe(struct platform_device *pdev) | 1414 | static int wm8350_probe(struct platform_device *pdev) |
@@ -1342,8 +1423,8 @@ static int wm8350_probe(struct platform_device *pdev) | |||
1342 | 1423 | ||
1343 | BUG_ON(!wm8350_codec); | 1424 | BUG_ON(!wm8350_codec); |
1344 | 1425 | ||
1345 | socdev->codec = wm8350_codec; | 1426 | socdev->card->codec = wm8350_codec; |
1346 | codec = socdev->codec; | 1427 | codec = socdev->card->codec; |
1347 | wm8350 = codec->control_data; | 1428 | wm8350 = codec->control_data; |
1348 | priv = codec->private_data; | 1429 | priv = codec->private_data; |
1349 | 1430 | ||
@@ -1381,13 +1462,21 @@ static int wm8350_probe(struct platform_device *pdev) | |||
1381 | wm8350_set_bits(wm8350, WM8350_ROUT2_VOLUME, | 1462 | wm8350_set_bits(wm8350, WM8350_ROUT2_VOLUME, |
1382 | WM8350_OUT2_VU | WM8350_OUT2R_MUTE); | 1463 | WM8350_OUT2_VU | WM8350_OUT2R_MUTE); |
1383 | 1464 | ||
1465 | wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L); | ||
1466 | wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R); | ||
1467 | wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L, | ||
1468 | wm8350_hp_jack_handler, priv); | ||
1469 | wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R, | ||
1470 | wm8350_hp_jack_handler, priv); | ||
1471 | |||
1384 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | 1472 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); |
1385 | if (ret < 0) { | 1473 | if (ret < 0) { |
1386 | dev_err(&pdev->dev, "failed to create pcms\n"); | 1474 | dev_err(&pdev->dev, "failed to create pcms\n"); |
1387 | return ret; | 1475 | return ret; |
1388 | } | 1476 | } |
1389 | 1477 | ||
1390 | wm8350_add_controls(codec); | 1478 | snd_soc_add_controls(codec, wm8350_snd_controls, |
1479 | ARRAY_SIZE(wm8350_snd_controls)); | ||
1391 | wm8350_add_widgets(codec); | 1480 | wm8350_add_widgets(codec); |
1392 | 1481 | ||
1393 | wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1482 | wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
@@ -1409,10 +1498,23 @@ card_err: | |||
1409 | static int wm8350_remove(struct platform_device *pdev) | 1498 | static int wm8350_remove(struct platform_device *pdev) |
1410 | { | 1499 | { |
1411 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1500 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
1412 | struct snd_soc_codec *codec = socdev->codec; | 1501 | struct snd_soc_codec *codec = socdev->card->codec; |
1413 | struct wm8350 *wm8350 = codec->control_data; | 1502 | struct wm8350 *wm8350 = codec->control_data; |
1503 | struct wm8350_data *priv = codec->private_data; | ||
1414 | int ret; | 1504 | int ret; |
1415 | 1505 | ||
1506 | wm8350_clear_bits(wm8350, WM8350_JACK_DETECT, | ||
1507 | WM8350_JDL_ENA | WM8350_JDR_ENA); | ||
1508 | wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_TOCLK_ENA); | ||
1509 | |||
1510 | wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L); | ||
1511 | wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R); | ||
1512 | wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L); | ||
1513 | wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R); | ||
1514 | |||
1515 | priv->hpl.jack = NULL; | ||
1516 | priv->hpr.jack = NULL; | ||
1517 | |||
1416 | /* cancel any work waiting to be queued. */ | 1518 | /* cancel any work waiting to be queued. */ |
1417 | ret = cancel_delayed_work(&codec->delayed_work); | 1519 | ret = cancel_delayed_work(&codec->delayed_work); |
1418 | 1520 | ||
@@ -1436,6 +1538,16 @@ static int wm8350_remove(struct platform_device *pdev) | |||
1436 | SNDRV_PCM_FMTBIT_S20_3LE |\ | 1538 | SNDRV_PCM_FMTBIT_S20_3LE |\ |
1437 | SNDRV_PCM_FMTBIT_S24_LE) | 1539 | SNDRV_PCM_FMTBIT_S24_LE) |
1438 | 1540 | ||
1541 | static struct snd_soc_dai_ops wm8350_dai_ops = { | ||
1542 | .hw_params = wm8350_pcm_hw_params, | ||
1543 | .digital_mute = wm8350_mute, | ||
1544 | .trigger = wm8350_pcm_trigger, | ||
1545 | .set_fmt = wm8350_set_dai_fmt, | ||
1546 | .set_sysclk = wm8350_set_dai_sysclk, | ||
1547 | .set_pll = wm8350_set_fll, | ||
1548 | .set_clkdiv = wm8350_set_clkdiv, | ||
1549 | }; | ||
1550 | |||
1439 | struct snd_soc_dai wm8350_dai = { | 1551 | struct snd_soc_dai wm8350_dai = { |
1440 | .name = "WM8350", | 1552 | .name = "WM8350", |
1441 | .playback = { | 1553 | .playback = { |
@@ -1452,15 +1564,7 @@ struct snd_soc_dai wm8350_dai = { | |||
1452 | .rates = WM8350_RATES, | 1564 | .rates = WM8350_RATES, |
1453 | .formats = WM8350_FORMATS, | 1565 | .formats = WM8350_FORMATS, |
1454 | }, | 1566 | }, |
1455 | .ops = { | 1567 | .ops = &wm8350_dai_ops, |
1456 | .hw_params = wm8350_pcm_hw_params, | ||
1457 | .digital_mute = wm8350_mute, | ||
1458 | .trigger = wm8350_pcm_trigger, | ||
1459 | .set_fmt = wm8350_set_dai_fmt, | ||
1460 | .set_sysclk = wm8350_set_dai_sysclk, | ||
1461 | .set_pll = wm8350_set_fll, | ||
1462 | .set_clkdiv = wm8350_set_clkdiv, | ||
1463 | }, | ||
1464 | }; | 1568 | }; |
1465 | EXPORT_SYMBOL_GPL(wm8350_dai); | 1569 | EXPORT_SYMBOL_GPL(wm8350_dai); |
1466 | 1570 | ||
@@ -1472,7 +1576,7 @@ struct snd_soc_codec_device soc_codec_dev_wm8350 = { | |||
1472 | }; | 1576 | }; |
1473 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8350); | 1577 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8350); |
1474 | 1578 | ||
1475 | static int wm8350_codec_probe(struct platform_device *pdev) | 1579 | static __devinit int wm8350_codec_probe(struct platform_device *pdev) |
1476 | { | 1580 | { |
1477 | struct wm8350 *wm8350 = platform_get_drvdata(pdev); | 1581 | struct wm8350 *wm8350 = platform_get_drvdata(pdev); |
1478 | struct wm8350_data *priv; | 1582 | struct wm8350_data *priv; |
diff --git a/sound/soc/codecs/wm8350.h b/sound/soc/codecs/wm8350.h index cc2887aa6c38..d11bd9288cf9 100644 --- a/sound/soc/codecs/wm8350.h +++ b/sound/soc/codecs/wm8350.h | |||
@@ -17,4 +17,12 @@ | |||
17 | extern struct snd_soc_dai wm8350_dai; | 17 | extern struct snd_soc_dai wm8350_dai; |
18 | extern struct snd_soc_codec_device soc_codec_dev_wm8350; | 18 | extern struct snd_soc_codec_device soc_codec_dev_wm8350; |
19 | 19 | ||
20 | enum wm8350_jack { | ||
21 | WM8350_JDL = 1, | ||
22 | WM8350_JDR = 2, | ||
23 | }; | ||
24 | |||
25 | int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which, | ||
26 | struct snd_soc_jack *jack, int report); | ||
27 | |||
20 | #endif | 28 | #endif |
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c new file mode 100644 index 000000000000..510efa604008 --- /dev/null +++ b/sound/soc/codecs/wm8400.c | |||
@@ -0,0 +1,1582 @@ | |||
1 | /* | ||
2 | * wm8400.c -- WM8400 ALSA Soc Audio driver | ||
3 | * | ||
4 | * Copyright 2008, 2009 Wolfson Microelectronics PLC. | ||
5 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/moduleparam.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/delay.h> | ||
19 | #include <linux/pm.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/regulator/consumer.h> | ||
22 | #include <linux/mfd/wm8400-audio.h> | ||
23 | #include <linux/mfd/wm8400-private.h> | ||
24 | #include <sound/core.h> | ||
25 | #include <sound/pcm.h> | ||
26 | #include <sound/pcm_params.h> | ||
27 | #include <sound/soc.h> | ||
28 | #include <sound/soc-dapm.h> | ||
29 | #include <sound/initval.h> | ||
30 | #include <sound/tlv.h> | ||
31 | |||
32 | #include "wm8400.h" | ||
33 | |||
34 | /* Fake register for internal state */ | ||
35 | #define WM8400_INTDRIVBITS (WM8400_REGISTER_COUNT + 1) | ||
36 | #define WM8400_INMIXL_PWR 0 | ||
37 | #define WM8400_AINLMUX_PWR 1 | ||
38 | #define WM8400_INMIXR_PWR 2 | ||
39 | #define WM8400_AINRMUX_PWR 3 | ||
40 | |||
41 | static struct regulator_bulk_data power[] = { | ||
42 | { | ||
43 | .supply = "I2S1VDD", | ||
44 | }, | ||
45 | { | ||
46 | .supply = "I2S2VDD", | ||
47 | }, | ||
48 | { | ||
49 | .supply = "DCVDD", | ||
50 | }, | ||
51 | { | ||
52 | .supply = "AVDD", | ||
53 | }, | ||
54 | { | ||
55 | .supply = "FLLVDD", | ||
56 | }, | ||
57 | { | ||
58 | .supply = "HPVDD", | ||
59 | }, | ||
60 | { | ||
61 | .supply = "SPKVDD", | ||
62 | }, | ||
63 | }; | ||
64 | |||
65 | /* codec private data */ | ||
66 | struct wm8400_priv { | ||
67 | struct snd_soc_codec codec; | ||
68 | struct wm8400 *wm8400; | ||
69 | u16 fake_register; | ||
70 | unsigned int sysclk; | ||
71 | unsigned int pcmclk; | ||
72 | struct work_struct work; | ||
73 | int fll_in, fll_out; | ||
74 | }; | ||
75 | |||
76 | static inline unsigned int wm8400_read(struct snd_soc_codec *codec, | ||
77 | unsigned int reg) | ||
78 | { | ||
79 | struct wm8400_priv *wm8400 = codec->private_data; | ||
80 | |||
81 | if (reg == WM8400_INTDRIVBITS) | ||
82 | return wm8400->fake_register; | ||
83 | else | ||
84 | return wm8400_reg_read(wm8400->wm8400, reg); | ||
85 | } | ||
86 | |||
87 | /* | ||
88 | * write to the wm8400 register space | ||
89 | */ | ||
90 | static int wm8400_write(struct snd_soc_codec *codec, unsigned int reg, | ||
91 | unsigned int value) | ||
92 | { | ||
93 | struct wm8400_priv *wm8400 = codec->private_data; | ||
94 | |||
95 | if (reg == WM8400_INTDRIVBITS) { | ||
96 | wm8400->fake_register = value; | ||
97 | return 0; | ||
98 | } else | ||
99 | return wm8400_set_bits(wm8400->wm8400, reg, 0xffff, value); | ||
100 | } | ||
101 | |||
102 | static void wm8400_codec_reset(struct snd_soc_codec *codec) | ||
103 | { | ||
104 | struct wm8400_priv *wm8400 = codec->private_data; | ||
105 | |||
106 | wm8400_reset_codec_reg_cache(wm8400->wm8400); | ||
107 | } | ||
108 | |||
109 | static const DECLARE_TLV_DB_LINEAR(rec_mix_tlv, -1500, 600); | ||
110 | |||
111 | static const DECLARE_TLV_DB_LINEAR(in_pga_tlv, -1650, 3000); | ||
112 | |||
113 | static const DECLARE_TLV_DB_LINEAR(out_mix_tlv, -2100, 0); | ||
114 | |||
115 | static const DECLARE_TLV_DB_LINEAR(out_pga_tlv, -7300, 600); | ||
116 | |||
117 | static const DECLARE_TLV_DB_LINEAR(out_omix_tlv, -600, 0); | ||
118 | |||
119 | static const DECLARE_TLV_DB_LINEAR(out_dac_tlv, -7163, 0); | ||
120 | |||
121 | static const DECLARE_TLV_DB_LINEAR(in_adc_tlv, -7163, 1763); | ||
122 | |||
123 | static const DECLARE_TLV_DB_LINEAR(out_sidetone_tlv, -3600, 0); | ||
124 | |||
125 | static int wm8400_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol, | ||
126 | struct snd_ctl_elem_value *ucontrol) | ||
127 | { | ||
128 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
129 | struct soc_mixer_control *mc = | ||
130 | (struct soc_mixer_control *)kcontrol->private_value; | ||
131 | int reg = mc->reg; | ||
132 | int ret; | ||
133 | u16 val; | ||
134 | |||
135 | ret = snd_soc_put_volsw(kcontrol, ucontrol); | ||
136 | if (ret < 0) | ||
137 | return ret; | ||
138 | |||
139 | /* now hit the volume update bits (always bit 8) */ | ||
140 | val = wm8400_read(codec, reg); | ||
141 | return wm8400_write(codec, reg, val | 0x0100); | ||
142 | } | ||
143 | |||
144 | #define WM8400_OUTPGA_SINGLE_R_TLV(xname, reg, shift, max, invert, tlv_array) \ | ||
145 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ | ||
146 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ | ||
147 | SNDRV_CTL_ELEM_ACCESS_READWRITE,\ | ||
148 | .tlv.p = (tlv_array), \ | ||
149 | .info = snd_soc_info_volsw, \ | ||
150 | .get = snd_soc_get_volsw, .put = wm8400_outpga_put_volsw_vu, \ | ||
151 | .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } | ||
152 | |||
153 | |||
154 | static const char *wm8400_digital_sidetone[] = | ||
155 | {"None", "Left ADC", "Right ADC", "Reserved"}; | ||
156 | |||
157 | static const struct soc_enum wm8400_left_digital_sidetone_enum = | ||
158 | SOC_ENUM_SINGLE(WM8400_DIGITAL_SIDE_TONE, | ||
159 | WM8400_ADC_TO_DACL_SHIFT, 2, wm8400_digital_sidetone); | ||
160 | |||
161 | static const struct soc_enum wm8400_right_digital_sidetone_enum = | ||
162 | SOC_ENUM_SINGLE(WM8400_DIGITAL_SIDE_TONE, | ||
163 | WM8400_ADC_TO_DACR_SHIFT, 2, wm8400_digital_sidetone); | ||
164 | |||
165 | static const char *wm8400_adcmode[] = | ||
166 | {"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"}; | ||
167 | |||
168 | static const struct soc_enum wm8400_right_adcmode_enum = | ||
169 | SOC_ENUM_SINGLE(WM8400_ADC_CTRL, WM8400_ADC_HPF_CUT_SHIFT, 3, wm8400_adcmode); | ||
170 | |||
171 | static const struct snd_kcontrol_new wm8400_snd_controls[] = { | ||
172 | /* INMIXL */ | ||
173 | SOC_SINGLE("LIN12 PGA Boost", WM8400_INPUT_MIXER3, WM8400_L12MNBST_SHIFT, | ||
174 | 1, 0), | ||
175 | SOC_SINGLE("LIN34 PGA Boost", WM8400_INPUT_MIXER3, WM8400_L34MNBST_SHIFT, | ||
176 | 1, 0), | ||
177 | /* INMIXR */ | ||
178 | SOC_SINGLE("RIN12 PGA Boost", WM8400_INPUT_MIXER3, WM8400_R12MNBST_SHIFT, | ||
179 | 1, 0), | ||
180 | SOC_SINGLE("RIN34 PGA Boost", WM8400_INPUT_MIXER3, WM8400_R34MNBST_SHIFT, | ||
181 | 1, 0), | ||
182 | |||
183 | /* LOMIX */ | ||
184 | SOC_SINGLE_TLV("LOMIX LIN3 Bypass Volume", WM8400_OUTPUT_MIXER3, | ||
185 | WM8400_LLI3LOVOL_SHIFT, 7, 0, out_mix_tlv), | ||
186 | SOC_SINGLE_TLV("LOMIX RIN12 PGA Bypass Volume", WM8400_OUTPUT_MIXER3, | ||
187 | WM8400_LR12LOVOL_SHIFT, 7, 0, out_mix_tlv), | ||
188 | SOC_SINGLE_TLV("LOMIX LIN12 PGA Bypass Volume", WM8400_OUTPUT_MIXER3, | ||
189 | WM8400_LL12LOVOL_SHIFT, 7, 0, out_mix_tlv), | ||
190 | SOC_SINGLE_TLV("LOMIX RIN3 Bypass Volume", WM8400_OUTPUT_MIXER5, | ||
191 | WM8400_LRI3LOVOL_SHIFT, 7, 0, out_mix_tlv), | ||
192 | SOC_SINGLE_TLV("LOMIX AINRMUX Bypass Volume", WM8400_OUTPUT_MIXER5, | ||
193 | WM8400_LRBLOVOL_SHIFT, 7, 0, out_mix_tlv), | ||
194 | SOC_SINGLE_TLV("LOMIX AINLMUX Bypass Volume", WM8400_OUTPUT_MIXER5, | ||
195 | WM8400_LRBLOVOL_SHIFT, 7, 0, out_mix_tlv), | ||
196 | |||
197 | /* ROMIX */ | ||
198 | SOC_SINGLE_TLV("ROMIX RIN3 Bypass Volume", WM8400_OUTPUT_MIXER4, | ||
199 | WM8400_RRI3ROVOL_SHIFT, 7, 0, out_mix_tlv), | ||
200 | SOC_SINGLE_TLV("ROMIX LIN12 PGA Bypass Volume", WM8400_OUTPUT_MIXER4, | ||
201 | WM8400_RL12ROVOL_SHIFT, 7, 0, out_mix_tlv), | ||
202 | SOC_SINGLE_TLV("ROMIX RIN12 PGA Bypass Volume", WM8400_OUTPUT_MIXER4, | ||
203 | WM8400_RR12ROVOL_SHIFT, 7, 0, out_mix_tlv), | ||
204 | SOC_SINGLE_TLV("ROMIX LIN3 Bypass Volume", WM8400_OUTPUT_MIXER6, | ||
205 | WM8400_RLI3ROVOL_SHIFT, 7, 0, out_mix_tlv), | ||
206 | SOC_SINGLE_TLV("ROMIX AINLMUX Bypass Volume", WM8400_OUTPUT_MIXER6, | ||
207 | WM8400_RLBROVOL_SHIFT, 7, 0, out_mix_tlv), | ||
208 | SOC_SINGLE_TLV("ROMIX AINRMUX Bypass Volume", WM8400_OUTPUT_MIXER6, | ||
209 | WM8400_RRBROVOL_SHIFT, 7, 0, out_mix_tlv), | ||
210 | |||
211 | /* LOUT */ | ||
212 | WM8400_OUTPGA_SINGLE_R_TLV("LOUT Volume", WM8400_LEFT_OUTPUT_VOLUME, | ||
213 | WM8400_LOUTVOL_SHIFT, WM8400_LOUTVOL_MASK, 0, out_pga_tlv), | ||
214 | SOC_SINGLE("LOUT ZC", WM8400_LEFT_OUTPUT_VOLUME, WM8400_LOZC_SHIFT, 1, 0), | ||
215 | |||
216 | /* ROUT */ | ||
217 | WM8400_OUTPGA_SINGLE_R_TLV("ROUT Volume", WM8400_RIGHT_OUTPUT_VOLUME, | ||
218 | WM8400_ROUTVOL_SHIFT, WM8400_ROUTVOL_MASK, 0, out_pga_tlv), | ||
219 | SOC_SINGLE("ROUT ZC", WM8400_RIGHT_OUTPUT_VOLUME, WM8400_ROZC_SHIFT, 1, 0), | ||
220 | |||
221 | /* LOPGA */ | ||
222 | WM8400_OUTPGA_SINGLE_R_TLV("LOPGA Volume", WM8400_LEFT_OPGA_VOLUME, | ||
223 | WM8400_LOPGAVOL_SHIFT, WM8400_LOPGAVOL_MASK, 0, out_pga_tlv), | ||
224 | SOC_SINGLE("LOPGA ZC Switch", WM8400_LEFT_OPGA_VOLUME, | ||
225 | WM8400_LOPGAZC_SHIFT, 1, 0), | ||
226 | |||
227 | /* ROPGA */ | ||
228 | WM8400_OUTPGA_SINGLE_R_TLV("ROPGA Volume", WM8400_RIGHT_OPGA_VOLUME, | ||
229 | WM8400_ROPGAVOL_SHIFT, WM8400_ROPGAVOL_MASK, 0, out_pga_tlv), | ||
230 | SOC_SINGLE("ROPGA ZC Switch", WM8400_RIGHT_OPGA_VOLUME, | ||
231 | WM8400_ROPGAZC_SHIFT, 1, 0), | ||
232 | |||
233 | SOC_SINGLE("LON Mute Switch", WM8400_LINE_OUTPUTS_VOLUME, | ||
234 | WM8400_LONMUTE_SHIFT, 1, 0), | ||
235 | SOC_SINGLE("LOP Mute Switch", WM8400_LINE_OUTPUTS_VOLUME, | ||
236 | WM8400_LOPMUTE_SHIFT, 1, 0), | ||
237 | SOC_SINGLE("LOP Attenuation Switch", WM8400_LINE_OUTPUTS_VOLUME, | ||
238 | WM8400_LOATTN_SHIFT, 1, 0), | ||
239 | SOC_SINGLE("RON Mute Switch", WM8400_LINE_OUTPUTS_VOLUME, | ||
240 | WM8400_RONMUTE_SHIFT, 1, 0), | ||
241 | SOC_SINGLE("ROP Mute Switch", WM8400_LINE_OUTPUTS_VOLUME, | ||
242 | WM8400_ROPMUTE_SHIFT, 1, 0), | ||
243 | SOC_SINGLE("ROP Attenuation Switch", WM8400_LINE_OUTPUTS_VOLUME, | ||
244 | WM8400_ROATTN_SHIFT, 1, 0), | ||
245 | |||
246 | SOC_SINGLE("OUT3 Mute Switch", WM8400_OUT3_4_VOLUME, | ||
247 | WM8400_OUT3MUTE_SHIFT, 1, 0), | ||
248 | SOC_SINGLE("OUT3 Attenuation Switch", WM8400_OUT3_4_VOLUME, | ||
249 | WM8400_OUT3ATTN_SHIFT, 1, 0), | ||
250 | |||
251 | SOC_SINGLE("OUT4 Mute Switch", WM8400_OUT3_4_VOLUME, | ||
252 | WM8400_OUT4MUTE_SHIFT, 1, 0), | ||
253 | SOC_SINGLE("OUT4 Attenuation Switch", WM8400_OUT3_4_VOLUME, | ||
254 | WM8400_OUT4ATTN_SHIFT, 1, 0), | ||
255 | |||
256 | SOC_SINGLE("Speaker Mode Switch", WM8400_CLASSD1, | ||
257 | WM8400_CDMODE_SHIFT, 1, 0), | ||
258 | |||
259 | SOC_SINGLE("Speaker Output Attenuation Volume", WM8400_SPEAKER_VOLUME, | ||
260 | WM8400_SPKATTN_SHIFT, WM8400_SPKATTN_MASK, 0), | ||
261 | SOC_SINGLE("Speaker DC Boost Volume", WM8400_CLASSD3, | ||
262 | WM8400_DCGAIN_SHIFT, 6, 0), | ||
263 | SOC_SINGLE("Speaker AC Boost Volume", WM8400_CLASSD3, | ||
264 | WM8400_ACGAIN_SHIFT, 6, 0), | ||
265 | |||
266 | WM8400_OUTPGA_SINGLE_R_TLV("Left DAC Digital Volume", | ||
267 | WM8400_LEFT_DAC_DIGITAL_VOLUME, WM8400_DACL_VOL_SHIFT, | ||
268 | 127, 0, out_dac_tlv), | ||
269 | |||
270 | WM8400_OUTPGA_SINGLE_R_TLV("Right DAC Digital Volume", | ||
271 | WM8400_RIGHT_DAC_DIGITAL_VOLUME, WM8400_DACR_VOL_SHIFT, | ||
272 | 127, 0, out_dac_tlv), | ||
273 | |||
274 | SOC_ENUM("Left Digital Sidetone", wm8400_left_digital_sidetone_enum), | ||
275 | SOC_ENUM("Right Digital Sidetone", wm8400_right_digital_sidetone_enum), | ||
276 | |||
277 | SOC_SINGLE_TLV("Left Digital Sidetone Volume", WM8400_DIGITAL_SIDE_TONE, | ||
278 | WM8400_ADCL_DAC_SVOL_SHIFT, 15, 0, out_sidetone_tlv), | ||
279 | SOC_SINGLE_TLV("Right Digital Sidetone Volume", WM8400_DIGITAL_SIDE_TONE, | ||
280 | WM8400_ADCR_DAC_SVOL_SHIFT, 15, 0, out_sidetone_tlv), | ||
281 | |||
282 | SOC_SINGLE("ADC Digital High Pass Filter Switch", WM8400_ADC_CTRL, | ||
283 | WM8400_ADC_HPF_ENA_SHIFT, 1, 0), | ||
284 | |||
285 | SOC_ENUM("ADC HPF Mode", wm8400_right_adcmode_enum), | ||
286 | |||
287 | WM8400_OUTPGA_SINGLE_R_TLV("Left ADC Digital Volume", | ||
288 | WM8400_LEFT_ADC_DIGITAL_VOLUME, | ||
289 | WM8400_ADCL_VOL_SHIFT, | ||
290 | WM8400_ADCL_VOL_MASK, | ||
291 | 0, | ||
292 | in_adc_tlv), | ||
293 | |||
294 | WM8400_OUTPGA_SINGLE_R_TLV("Right ADC Digital Volume", | ||
295 | WM8400_RIGHT_ADC_DIGITAL_VOLUME, | ||
296 | WM8400_ADCR_VOL_SHIFT, | ||
297 | WM8400_ADCR_VOL_MASK, | ||
298 | 0, | ||
299 | in_adc_tlv), | ||
300 | |||
301 | WM8400_OUTPGA_SINGLE_R_TLV("LIN12 Volume", | ||
302 | WM8400_LEFT_LINE_INPUT_1_2_VOLUME, | ||
303 | WM8400_LIN12VOL_SHIFT, | ||
304 | WM8400_LIN12VOL_MASK, | ||
305 | 0, | ||
306 | in_pga_tlv), | ||
307 | |||
308 | SOC_SINGLE("LIN12 ZC Switch", WM8400_LEFT_LINE_INPUT_1_2_VOLUME, | ||
309 | WM8400_LI12ZC_SHIFT, 1, 0), | ||
310 | |||
311 | SOC_SINGLE("LIN12 Mute Switch", WM8400_LEFT_LINE_INPUT_1_2_VOLUME, | ||
312 | WM8400_LI12MUTE_SHIFT, 1, 0), | ||
313 | |||
314 | WM8400_OUTPGA_SINGLE_R_TLV("LIN34 Volume", | ||
315 | WM8400_LEFT_LINE_INPUT_3_4_VOLUME, | ||
316 | WM8400_LIN34VOL_SHIFT, | ||
317 | WM8400_LIN34VOL_MASK, | ||
318 | 0, | ||
319 | in_pga_tlv), | ||
320 | |||
321 | SOC_SINGLE("LIN34 ZC Switch", WM8400_LEFT_LINE_INPUT_3_4_VOLUME, | ||
322 | WM8400_LI34ZC_SHIFT, 1, 0), | ||
323 | |||
324 | SOC_SINGLE("LIN34 Mute Switch", WM8400_LEFT_LINE_INPUT_3_4_VOLUME, | ||
325 | WM8400_LI34MUTE_SHIFT, 1, 0), | ||
326 | |||
327 | WM8400_OUTPGA_SINGLE_R_TLV("RIN12 Volume", | ||
328 | WM8400_RIGHT_LINE_INPUT_1_2_VOLUME, | ||
329 | WM8400_RIN12VOL_SHIFT, | ||
330 | WM8400_RIN12VOL_MASK, | ||
331 | 0, | ||
332 | in_pga_tlv), | ||
333 | |||
334 | SOC_SINGLE("RIN12 ZC Switch", WM8400_RIGHT_LINE_INPUT_1_2_VOLUME, | ||
335 | WM8400_RI12ZC_SHIFT, 1, 0), | ||
336 | |||
337 | SOC_SINGLE("RIN12 Mute Switch", WM8400_RIGHT_LINE_INPUT_1_2_VOLUME, | ||
338 | WM8400_RI12MUTE_SHIFT, 1, 0), | ||
339 | |||
340 | WM8400_OUTPGA_SINGLE_R_TLV("RIN34 Volume", | ||
341 | WM8400_RIGHT_LINE_INPUT_3_4_VOLUME, | ||
342 | WM8400_RIN34VOL_SHIFT, | ||
343 | WM8400_RIN34VOL_MASK, | ||
344 | 0, | ||
345 | in_pga_tlv), | ||
346 | |||
347 | SOC_SINGLE("RIN34 ZC Switch", WM8400_RIGHT_LINE_INPUT_3_4_VOLUME, | ||
348 | WM8400_RI34ZC_SHIFT, 1, 0), | ||
349 | |||
350 | SOC_SINGLE("RIN34 Mute Switch", WM8400_RIGHT_LINE_INPUT_3_4_VOLUME, | ||
351 | WM8400_RI34MUTE_SHIFT, 1, 0), | ||
352 | |||
353 | }; | ||
354 | |||
355 | /* add non dapm controls */ | ||
356 | static int wm8400_add_controls(struct snd_soc_codec *codec) | ||
357 | { | ||
358 | return snd_soc_add_controls(codec, wm8400_snd_controls, | ||
359 | ARRAY_SIZE(wm8400_snd_controls)); | ||
360 | } | ||
361 | |||
362 | /* | ||
363 | * _DAPM_ Controls | ||
364 | */ | ||
365 | |||
366 | static int inmixer_event (struct snd_soc_dapm_widget *w, | ||
367 | struct snd_kcontrol *kcontrol, int event) | ||
368 | { | ||
369 | u16 reg, fakepower; | ||
370 | |||
371 | reg = wm8400_read(w->codec, WM8400_POWER_MANAGEMENT_2); | ||
372 | fakepower = wm8400_read(w->codec, WM8400_INTDRIVBITS); | ||
373 | |||
374 | if (fakepower & ((1 << WM8400_INMIXL_PWR) | | ||
375 | (1 << WM8400_AINLMUX_PWR))) { | ||
376 | reg |= WM8400_AINL_ENA; | ||
377 | } else { | ||
378 | reg &= ~WM8400_AINL_ENA; | ||
379 | } | ||
380 | |||
381 | if (fakepower & ((1 << WM8400_INMIXR_PWR) | | ||
382 | (1 << WM8400_AINRMUX_PWR))) { | ||
383 | reg |= WM8400_AINR_ENA; | ||
384 | } else { | ||
385 | reg &= ~WM8400_AINL_ENA; | ||
386 | } | ||
387 | wm8400_write(w->codec, WM8400_POWER_MANAGEMENT_2, reg); | ||
388 | |||
389 | return 0; | ||
390 | } | ||
391 | |||
392 | static int outmixer_event (struct snd_soc_dapm_widget *w, | ||
393 | struct snd_kcontrol * kcontrol, int event) | ||
394 | { | ||
395 | struct soc_mixer_control *mc = | ||
396 | (struct soc_mixer_control *)kcontrol->private_value; | ||
397 | u32 reg_shift = mc->shift; | ||
398 | int ret = 0; | ||
399 | u16 reg; | ||
400 | |||
401 | switch (reg_shift) { | ||
402 | case WM8400_SPEAKER_MIXER | (WM8400_LDSPK << 8) : | ||
403 | reg = wm8400_read(w->codec, WM8400_OUTPUT_MIXER1); | ||
404 | if (reg & WM8400_LDLO) { | ||
405 | printk(KERN_WARNING | ||
406 | "Cannot set as Output Mixer 1 LDLO Set\n"); | ||
407 | ret = -1; | ||
408 | } | ||
409 | break; | ||
410 | case WM8400_SPEAKER_MIXER | (WM8400_RDSPK << 8): | ||
411 | reg = wm8400_read(w->codec, WM8400_OUTPUT_MIXER2); | ||
412 | if (reg & WM8400_RDRO) { | ||
413 | printk(KERN_WARNING | ||
414 | "Cannot set as Output Mixer 2 RDRO Set\n"); | ||
415 | ret = -1; | ||
416 | } | ||
417 | break; | ||
418 | case WM8400_OUTPUT_MIXER1 | (WM8400_LDLO << 8): | ||
419 | reg = wm8400_read(w->codec, WM8400_SPEAKER_MIXER); | ||
420 | if (reg & WM8400_LDSPK) { | ||
421 | printk(KERN_WARNING | ||
422 | "Cannot set as Speaker Mixer LDSPK Set\n"); | ||
423 | ret = -1; | ||
424 | } | ||
425 | break; | ||
426 | case WM8400_OUTPUT_MIXER2 | (WM8400_RDRO << 8): | ||
427 | reg = wm8400_read(w->codec, WM8400_SPEAKER_MIXER); | ||
428 | if (reg & WM8400_RDSPK) { | ||
429 | printk(KERN_WARNING | ||
430 | "Cannot set as Speaker Mixer RDSPK Set\n"); | ||
431 | ret = -1; | ||
432 | } | ||
433 | break; | ||
434 | } | ||
435 | |||
436 | return ret; | ||
437 | } | ||
438 | |||
439 | /* INMIX dB values */ | ||
440 | static const unsigned int in_mix_tlv[] = { | ||
441 | TLV_DB_RANGE_HEAD(1), | ||
442 | 0,7, TLV_DB_LINEAR_ITEM(-1200, 600), | ||
443 | }; | ||
444 | |||
445 | /* Left In PGA Connections */ | ||
446 | static const struct snd_kcontrol_new wm8400_dapm_lin12_pga_controls[] = { | ||
447 | SOC_DAPM_SINGLE("LIN1 Switch", WM8400_INPUT_MIXER2, WM8400_LMN1_SHIFT, 1, 0), | ||
448 | SOC_DAPM_SINGLE("LIN2 Switch", WM8400_INPUT_MIXER2, WM8400_LMP2_SHIFT, 1, 0), | ||
449 | }; | ||
450 | |||
451 | static const struct snd_kcontrol_new wm8400_dapm_lin34_pga_controls[] = { | ||
452 | SOC_DAPM_SINGLE("LIN3 Switch", WM8400_INPUT_MIXER2, WM8400_LMN3_SHIFT, 1, 0), | ||
453 | SOC_DAPM_SINGLE("LIN4 Switch", WM8400_INPUT_MIXER2, WM8400_LMP4_SHIFT, 1, 0), | ||
454 | }; | ||
455 | |||
456 | /* Right In PGA Connections */ | ||
457 | static const struct snd_kcontrol_new wm8400_dapm_rin12_pga_controls[] = { | ||
458 | SOC_DAPM_SINGLE("RIN1 Switch", WM8400_INPUT_MIXER2, WM8400_RMN1_SHIFT, 1, 0), | ||
459 | SOC_DAPM_SINGLE("RIN2 Switch", WM8400_INPUT_MIXER2, WM8400_RMP2_SHIFT, 1, 0), | ||
460 | }; | ||
461 | |||
462 | static const struct snd_kcontrol_new wm8400_dapm_rin34_pga_controls[] = { | ||
463 | SOC_DAPM_SINGLE("RIN3 Switch", WM8400_INPUT_MIXER2, WM8400_RMN3_SHIFT, 1, 0), | ||
464 | SOC_DAPM_SINGLE("RIN4 Switch", WM8400_INPUT_MIXER2, WM8400_RMP4_SHIFT, 1, 0), | ||
465 | }; | ||
466 | |||
467 | /* INMIXL */ | ||
468 | static const struct snd_kcontrol_new wm8400_dapm_inmixl_controls[] = { | ||
469 | SOC_DAPM_SINGLE_TLV("Record Left Volume", WM8400_INPUT_MIXER3, | ||
470 | WM8400_LDBVOL_SHIFT, WM8400_LDBVOL_MASK, 0, in_mix_tlv), | ||
471 | SOC_DAPM_SINGLE_TLV("LIN2 Volume", WM8400_INPUT_MIXER5, WM8400_LI2BVOL_SHIFT, | ||
472 | 7, 0, in_mix_tlv), | ||
473 | SOC_DAPM_SINGLE("LINPGA12 Switch", WM8400_INPUT_MIXER3, WM8400_L12MNB_SHIFT, | ||
474 | 1, 0), | ||
475 | SOC_DAPM_SINGLE("LINPGA34 Switch", WM8400_INPUT_MIXER3, WM8400_L34MNB_SHIFT, | ||
476 | 1, 0), | ||
477 | }; | ||
478 | |||
479 | /* INMIXR */ | ||
480 | static const struct snd_kcontrol_new wm8400_dapm_inmixr_controls[] = { | ||
481 | SOC_DAPM_SINGLE_TLV("Record Right Volume", WM8400_INPUT_MIXER4, | ||
482 | WM8400_RDBVOL_SHIFT, WM8400_RDBVOL_MASK, 0, in_mix_tlv), | ||
483 | SOC_DAPM_SINGLE_TLV("RIN2 Volume", WM8400_INPUT_MIXER6, WM8400_RI2BVOL_SHIFT, | ||
484 | 7, 0, in_mix_tlv), | ||
485 | SOC_DAPM_SINGLE("RINPGA12 Switch", WM8400_INPUT_MIXER3, WM8400_L12MNB_SHIFT, | ||
486 | 1, 0), | ||
487 | SOC_DAPM_SINGLE("RINPGA34 Switch", WM8400_INPUT_MIXER3, WM8400_L34MNB_SHIFT, | ||
488 | 1, 0), | ||
489 | }; | ||
490 | |||
491 | /* AINLMUX */ | ||
492 | static const char *wm8400_ainlmux[] = | ||
493 | {"INMIXL Mix", "RXVOICE Mix", "DIFFINL Mix"}; | ||
494 | |||
495 | static const struct soc_enum wm8400_ainlmux_enum = | ||
496 | SOC_ENUM_SINGLE( WM8400_INPUT_MIXER1, WM8400_AINLMODE_SHIFT, | ||
497 | ARRAY_SIZE(wm8400_ainlmux), wm8400_ainlmux); | ||
498 | |||
499 | static const struct snd_kcontrol_new wm8400_dapm_ainlmux_controls = | ||
500 | SOC_DAPM_ENUM("Route", wm8400_ainlmux_enum); | ||
501 | |||
502 | /* DIFFINL */ | ||
503 | |||
504 | /* AINRMUX */ | ||
505 | static const char *wm8400_ainrmux[] = | ||
506 | {"INMIXR Mix", "RXVOICE Mix", "DIFFINR Mix"}; | ||
507 | |||
508 | static const struct soc_enum wm8400_ainrmux_enum = | ||
509 | SOC_ENUM_SINGLE( WM8400_INPUT_MIXER1, WM8400_AINRMODE_SHIFT, | ||
510 | ARRAY_SIZE(wm8400_ainrmux), wm8400_ainrmux); | ||
511 | |||
512 | static const struct snd_kcontrol_new wm8400_dapm_ainrmux_controls = | ||
513 | SOC_DAPM_ENUM("Route", wm8400_ainrmux_enum); | ||
514 | |||
515 | /* RXVOICE */ | ||
516 | static const struct snd_kcontrol_new wm8400_dapm_rxvoice_controls[] = { | ||
517 | SOC_DAPM_SINGLE_TLV("LIN4/RXN", WM8400_INPUT_MIXER5, WM8400_LR4BVOL_SHIFT, | ||
518 | WM8400_LR4BVOL_MASK, 0, in_mix_tlv), | ||
519 | SOC_DAPM_SINGLE_TLV("RIN4/RXP", WM8400_INPUT_MIXER6, WM8400_RL4BVOL_SHIFT, | ||
520 | WM8400_RL4BVOL_MASK, 0, in_mix_tlv), | ||
521 | }; | ||
522 | |||
523 | /* LOMIX */ | ||
524 | static const struct snd_kcontrol_new wm8400_dapm_lomix_controls[] = { | ||
525 | SOC_DAPM_SINGLE("LOMIX Right ADC Bypass Switch", WM8400_OUTPUT_MIXER1, | ||
526 | WM8400_LRBLO_SHIFT, 1, 0), | ||
527 | SOC_DAPM_SINGLE("LOMIX Left ADC Bypass Switch", WM8400_OUTPUT_MIXER1, | ||
528 | WM8400_LLBLO_SHIFT, 1, 0), | ||
529 | SOC_DAPM_SINGLE("LOMIX RIN3 Bypass Switch", WM8400_OUTPUT_MIXER1, | ||
530 | WM8400_LRI3LO_SHIFT, 1, 0), | ||
531 | SOC_DAPM_SINGLE("LOMIX LIN3 Bypass Switch", WM8400_OUTPUT_MIXER1, | ||
532 | WM8400_LLI3LO_SHIFT, 1, 0), | ||
533 | SOC_DAPM_SINGLE("LOMIX RIN12 PGA Bypass Switch", WM8400_OUTPUT_MIXER1, | ||
534 | WM8400_LR12LO_SHIFT, 1, 0), | ||
535 | SOC_DAPM_SINGLE("LOMIX LIN12 PGA Bypass Switch", WM8400_OUTPUT_MIXER1, | ||
536 | WM8400_LL12LO_SHIFT, 1, 0), | ||
537 | SOC_DAPM_SINGLE("LOMIX Left DAC Switch", WM8400_OUTPUT_MIXER1, | ||
538 | WM8400_LDLO_SHIFT, 1, 0), | ||
539 | }; | ||
540 | |||
541 | /* ROMIX */ | ||
542 | static const struct snd_kcontrol_new wm8400_dapm_romix_controls[] = { | ||
543 | SOC_DAPM_SINGLE("ROMIX Left ADC Bypass Switch", WM8400_OUTPUT_MIXER2, | ||
544 | WM8400_RLBRO_SHIFT, 1, 0), | ||
545 | SOC_DAPM_SINGLE("ROMIX Right ADC Bypass Switch", WM8400_OUTPUT_MIXER2, | ||
546 | WM8400_RRBRO_SHIFT, 1, 0), | ||
547 | SOC_DAPM_SINGLE("ROMIX LIN3 Bypass Switch", WM8400_OUTPUT_MIXER2, | ||
548 | WM8400_RLI3RO_SHIFT, 1, 0), | ||
549 | SOC_DAPM_SINGLE("ROMIX RIN3 Bypass Switch", WM8400_OUTPUT_MIXER2, | ||
550 | WM8400_RRI3RO_SHIFT, 1, 0), | ||
551 | SOC_DAPM_SINGLE("ROMIX LIN12 PGA Bypass Switch", WM8400_OUTPUT_MIXER2, | ||
552 | WM8400_RL12RO_SHIFT, 1, 0), | ||
553 | SOC_DAPM_SINGLE("ROMIX RIN12 PGA Bypass Switch", WM8400_OUTPUT_MIXER2, | ||
554 | WM8400_RR12RO_SHIFT, 1, 0), | ||
555 | SOC_DAPM_SINGLE("ROMIX Right DAC Switch", WM8400_OUTPUT_MIXER2, | ||
556 | WM8400_RDRO_SHIFT, 1, 0), | ||
557 | }; | ||
558 | |||
559 | /* LONMIX */ | ||
560 | static const struct snd_kcontrol_new wm8400_dapm_lonmix_controls[] = { | ||
561 | SOC_DAPM_SINGLE("LONMIX Left Mixer PGA Switch", WM8400_LINE_MIXER1, | ||
562 | WM8400_LLOPGALON_SHIFT, 1, 0), | ||
563 | SOC_DAPM_SINGLE("LONMIX Right Mixer PGA Switch", WM8400_LINE_MIXER1, | ||
564 | WM8400_LROPGALON_SHIFT, 1, 0), | ||
565 | SOC_DAPM_SINGLE("LONMIX Inverted LOP Switch", WM8400_LINE_MIXER1, | ||
566 | WM8400_LOPLON_SHIFT, 1, 0), | ||
567 | }; | ||
568 | |||
569 | /* LOPMIX */ | ||
570 | static const struct snd_kcontrol_new wm8400_dapm_lopmix_controls[] = { | ||
571 | SOC_DAPM_SINGLE("LOPMIX Right Mic Bypass Switch", WM8400_LINE_MIXER1, | ||
572 | WM8400_LR12LOP_SHIFT, 1, 0), | ||
573 | SOC_DAPM_SINGLE("LOPMIX Left Mic Bypass Switch", WM8400_LINE_MIXER1, | ||
574 | WM8400_LL12LOP_SHIFT, 1, 0), | ||
575 | SOC_DAPM_SINGLE("LOPMIX Left Mixer PGA Switch", WM8400_LINE_MIXER1, | ||
576 | WM8400_LLOPGALOP_SHIFT, 1, 0), | ||
577 | }; | ||
578 | |||
579 | /* RONMIX */ | ||
580 | static const struct snd_kcontrol_new wm8400_dapm_ronmix_controls[] = { | ||
581 | SOC_DAPM_SINGLE("RONMIX Right Mixer PGA Switch", WM8400_LINE_MIXER2, | ||
582 | WM8400_RROPGARON_SHIFT, 1, 0), | ||
583 | SOC_DAPM_SINGLE("RONMIX Left Mixer PGA Switch", WM8400_LINE_MIXER2, | ||
584 | WM8400_RLOPGARON_SHIFT, 1, 0), | ||
585 | SOC_DAPM_SINGLE("RONMIX Inverted ROP Switch", WM8400_LINE_MIXER2, | ||
586 | WM8400_ROPRON_SHIFT, 1, 0), | ||
587 | }; | ||
588 | |||
589 | /* ROPMIX */ | ||
590 | static const struct snd_kcontrol_new wm8400_dapm_ropmix_controls[] = { | ||
591 | SOC_DAPM_SINGLE("ROPMIX Left Mic Bypass Switch", WM8400_LINE_MIXER2, | ||
592 | WM8400_RL12ROP_SHIFT, 1, 0), | ||
593 | SOC_DAPM_SINGLE("ROPMIX Right Mic Bypass Switch", WM8400_LINE_MIXER2, | ||
594 | WM8400_RR12ROP_SHIFT, 1, 0), | ||
595 | SOC_DAPM_SINGLE("ROPMIX Right Mixer PGA Switch", WM8400_LINE_MIXER2, | ||
596 | WM8400_RROPGAROP_SHIFT, 1, 0), | ||
597 | }; | ||
598 | |||
599 | /* OUT3MIX */ | ||
600 | static const struct snd_kcontrol_new wm8400_dapm_out3mix_controls[] = { | ||
601 | SOC_DAPM_SINGLE("OUT3MIX LIN4/RXP Bypass Switch", WM8400_OUT3_4_MIXER, | ||
602 | WM8400_LI4O3_SHIFT, 1, 0), | ||
603 | SOC_DAPM_SINGLE("OUT3MIX Left Out PGA Switch", WM8400_OUT3_4_MIXER, | ||
604 | WM8400_LPGAO3_SHIFT, 1, 0), | ||
605 | }; | ||
606 | |||
607 | /* OUT4MIX */ | ||
608 | static const struct snd_kcontrol_new wm8400_dapm_out4mix_controls[] = { | ||
609 | SOC_DAPM_SINGLE("OUT4MIX Right Out PGA Switch", WM8400_OUT3_4_MIXER, | ||
610 | WM8400_RPGAO4_SHIFT, 1, 0), | ||
611 | SOC_DAPM_SINGLE("OUT4MIX RIN4/RXP Bypass Switch", WM8400_OUT3_4_MIXER, | ||
612 | WM8400_RI4O4_SHIFT, 1, 0), | ||
613 | }; | ||
614 | |||
615 | /* SPKMIX */ | ||
616 | static const struct snd_kcontrol_new wm8400_dapm_spkmix_controls[] = { | ||
617 | SOC_DAPM_SINGLE("SPKMIX LIN2 Bypass Switch", WM8400_SPEAKER_MIXER, | ||
618 | WM8400_LI2SPK_SHIFT, 1, 0), | ||
619 | SOC_DAPM_SINGLE("SPKMIX LADC Bypass Switch", WM8400_SPEAKER_MIXER, | ||
620 | WM8400_LB2SPK_SHIFT, 1, 0), | ||
621 | SOC_DAPM_SINGLE("SPKMIX Left Mixer PGA Switch", WM8400_SPEAKER_MIXER, | ||
622 | WM8400_LOPGASPK_SHIFT, 1, 0), | ||
623 | SOC_DAPM_SINGLE("SPKMIX Left DAC Switch", WM8400_SPEAKER_MIXER, | ||
624 | WM8400_LDSPK_SHIFT, 1, 0), | ||
625 | SOC_DAPM_SINGLE("SPKMIX Right DAC Switch", WM8400_SPEAKER_MIXER, | ||
626 | WM8400_RDSPK_SHIFT, 1, 0), | ||
627 | SOC_DAPM_SINGLE("SPKMIX Right Mixer PGA Switch", WM8400_SPEAKER_MIXER, | ||
628 | WM8400_ROPGASPK_SHIFT, 1, 0), | ||
629 | SOC_DAPM_SINGLE("SPKMIX RADC Bypass Switch", WM8400_SPEAKER_MIXER, | ||
630 | WM8400_RL12ROP_SHIFT, 1, 0), | ||
631 | SOC_DAPM_SINGLE("SPKMIX RIN2 Bypass Switch", WM8400_SPEAKER_MIXER, | ||
632 | WM8400_RI2SPK_SHIFT, 1, 0), | ||
633 | }; | ||
634 | |||
635 | static const struct snd_soc_dapm_widget wm8400_dapm_widgets[] = { | ||
636 | /* Input Side */ | ||
637 | /* Input Lines */ | ||
638 | SND_SOC_DAPM_INPUT("LIN1"), | ||
639 | SND_SOC_DAPM_INPUT("LIN2"), | ||
640 | SND_SOC_DAPM_INPUT("LIN3"), | ||
641 | SND_SOC_DAPM_INPUT("LIN4/RXN"), | ||
642 | SND_SOC_DAPM_INPUT("RIN3"), | ||
643 | SND_SOC_DAPM_INPUT("RIN4/RXP"), | ||
644 | SND_SOC_DAPM_INPUT("RIN1"), | ||
645 | SND_SOC_DAPM_INPUT("RIN2"), | ||
646 | SND_SOC_DAPM_INPUT("Internal ADC Source"), | ||
647 | |||
648 | /* DACs */ | ||
649 | SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8400_POWER_MANAGEMENT_2, | ||
650 | WM8400_ADCL_ENA_SHIFT, 0), | ||
651 | SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8400_POWER_MANAGEMENT_2, | ||
652 | WM8400_ADCR_ENA_SHIFT, 0), | ||
653 | |||
654 | /* Input PGAs */ | ||
655 | SND_SOC_DAPM_MIXER("LIN12 PGA", WM8400_POWER_MANAGEMENT_2, | ||
656 | WM8400_LIN12_ENA_SHIFT, | ||
657 | 0, &wm8400_dapm_lin12_pga_controls[0], | ||
658 | ARRAY_SIZE(wm8400_dapm_lin12_pga_controls)), | ||
659 | SND_SOC_DAPM_MIXER("LIN34 PGA", WM8400_POWER_MANAGEMENT_2, | ||
660 | WM8400_LIN34_ENA_SHIFT, | ||
661 | 0, &wm8400_dapm_lin34_pga_controls[0], | ||
662 | ARRAY_SIZE(wm8400_dapm_lin34_pga_controls)), | ||
663 | SND_SOC_DAPM_MIXER("RIN12 PGA", WM8400_POWER_MANAGEMENT_2, | ||
664 | WM8400_RIN12_ENA_SHIFT, | ||
665 | 0, &wm8400_dapm_rin12_pga_controls[0], | ||
666 | ARRAY_SIZE(wm8400_dapm_rin12_pga_controls)), | ||
667 | SND_SOC_DAPM_MIXER("RIN34 PGA", WM8400_POWER_MANAGEMENT_2, | ||
668 | WM8400_RIN34_ENA_SHIFT, | ||
669 | 0, &wm8400_dapm_rin34_pga_controls[0], | ||
670 | ARRAY_SIZE(wm8400_dapm_rin34_pga_controls)), | ||
671 | |||
672 | /* INMIXL */ | ||
673 | SND_SOC_DAPM_MIXER_E("INMIXL", WM8400_INTDRIVBITS, WM8400_INMIXL_PWR, 0, | ||
674 | &wm8400_dapm_inmixl_controls[0], | ||
675 | ARRAY_SIZE(wm8400_dapm_inmixl_controls), | ||
676 | inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | ||
677 | |||
678 | /* AINLMUX */ | ||
679 | SND_SOC_DAPM_MUX_E("AILNMUX", WM8400_INTDRIVBITS, WM8400_AINLMUX_PWR, 0, | ||
680 | &wm8400_dapm_ainlmux_controls, inmixer_event, | ||
681 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | ||
682 | |||
683 | /* INMIXR */ | ||
684 | SND_SOC_DAPM_MIXER_E("INMIXR", WM8400_INTDRIVBITS, WM8400_INMIXR_PWR, 0, | ||
685 | &wm8400_dapm_inmixr_controls[0], | ||
686 | ARRAY_SIZE(wm8400_dapm_inmixr_controls), | ||
687 | inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | ||
688 | |||
689 | /* AINRMUX */ | ||
690 | SND_SOC_DAPM_MUX_E("AIRNMUX", WM8400_INTDRIVBITS, WM8400_AINRMUX_PWR, 0, | ||
691 | &wm8400_dapm_ainrmux_controls, inmixer_event, | ||
692 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | ||
693 | |||
694 | /* Output Side */ | ||
695 | /* DACs */ | ||
696 | SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8400_POWER_MANAGEMENT_3, | ||
697 | WM8400_DACL_ENA_SHIFT, 0), | ||
698 | SND_SOC_DAPM_DAC("Right DAC", "Right Playback", WM8400_POWER_MANAGEMENT_3, | ||
699 | WM8400_DACR_ENA_SHIFT, 0), | ||
700 | |||
701 | /* LOMIX */ | ||
702 | SND_SOC_DAPM_MIXER_E("LOMIX", WM8400_POWER_MANAGEMENT_3, | ||
703 | WM8400_LOMIX_ENA_SHIFT, | ||
704 | 0, &wm8400_dapm_lomix_controls[0], | ||
705 | ARRAY_SIZE(wm8400_dapm_lomix_controls), | ||
706 | outmixer_event, SND_SOC_DAPM_PRE_REG), | ||
707 | |||
708 | /* LONMIX */ | ||
709 | SND_SOC_DAPM_MIXER("LONMIX", WM8400_POWER_MANAGEMENT_3, WM8400_LON_ENA_SHIFT, | ||
710 | 0, &wm8400_dapm_lonmix_controls[0], | ||
711 | ARRAY_SIZE(wm8400_dapm_lonmix_controls)), | ||
712 | |||
713 | /* LOPMIX */ | ||
714 | SND_SOC_DAPM_MIXER("LOPMIX", WM8400_POWER_MANAGEMENT_3, WM8400_LOP_ENA_SHIFT, | ||
715 | 0, &wm8400_dapm_lopmix_controls[0], | ||
716 | ARRAY_SIZE(wm8400_dapm_lopmix_controls)), | ||
717 | |||
718 | /* OUT3MIX */ | ||
719 | SND_SOC_DAPM_MIXER("OUT3MIX", WM8400_POWER_MANAGEMENT_1, WM8400_OUT3_ENA_SHIFT, | ||
720 | 0, &wm8400_dapm_out3mix_controls[0], | ||
721 | ARRAY_SIZE(wm8400_dapm_out3mix_controls)), | ||
722 | |||
723 | /* SPKMIX */ | ||
724 | SND_SOC_DAPM_MIXER_E("SPKMIX", WM8400_POWER_MANAGEMENT_1, WM8400_SPK_ENA_SHIFT, | ||
725 | 0, &wm8400_dapm_spkmix_controls[0], | ||
726 | ARRAY_SIZE(wm8400_dapm_spkmix_controls), outmixer_event, | ||
727 | SND_SOC_DAPM_PRE_REG), | ||
728 | |||
729 | /* OUT4MIX */ | ||
730 | SND_SOC_DAPM_MIXER("OUT4MIX", WM8400_POWER_MANAGEMENT_1, WM8400_OUT4_ENA_SHIFT, | ||
731 | 0, &wm8400_dapm_out4mix_controls[0], | ||
732 | ARRAY_SIZE(wm8400_dapm_out4mix_controls)), | ||
733 | |||
734 | /* ROPMIX */ | ||
735 | SND_SOC_DAPM_MIXER("ROPMIX", WM8400_POWER_MANAGEMENT_3, WM8400_ROP_ENA_SHIFT, | ||
736 | 0, &wm8400_dapm_ropmix_controls[0], | ||
737 | ARRAY_SIZE(wm8400_dapm_ropmix_controls)), | ||
738 | |||
739 | /* RONMIX */ | ||
740 | SND_SOC_DAPM_MIXER("RONMIX", WM8400_POWER_MANAGEMENT_3, WM8400_RON_ENA_SHIFT, | ||
741 | 0, &wm8400_dapm_ronmix_controls[0], | ||
742 | ARRAY_SIZE(wm8400_dapm_ronmix_controls)), | ||
743 | |||
744 | /* ROMIX */ | ||
745 | SND_SOC_DAPM_MIXER_E("ROMIX", WM8400_POWER_MANAGEMENT_3, | ||
746 | WM8400_ROMIX_ENA_SHIFT, | ||
747 | 0, &wm8400_dapm_romix_controls[0], | ||
748 | ARRAY_SIZE(wm8400_dapm_romix_controls), | ||
749 | outmixer_event, SND_SOC_DAPM_PRE_REG), | ||
750 | |||
751 | /* LOUT PGA */ | ||
752 | SND_SOC_DAPM_PGA("LOUT PGA", WM8400_POWER_MANAGEMENT_1, WM8400_LOUT_ENA_SHIFT, | ||
753 | 0, NULL, 0), | ||
754 | |||
755 | /* ROUT PGA */ | ||
756 | SND_SOC_DAPM_PGA("ROUT PGA", WM8400_POWER_MANAGEMENT_1, WM8400_ROUT_ENA_SHIFT, | ||
757 | 0, NULL, 0), | ||
758 | |||
759 | /* LOPGA */ | ||
760 | SND_SOC_DAPM_PGA("LOPGA", WM8400_POWER_MANAGEMENT_3, WM8400_LOPGA_ENA_SHIFT, 0, | ||
761 | NULL, 0), | ||
762 | |||
763 | /* ROPGA */ | ||
764 | SND_SOC_DAPM_PGA("ROPGA", WM8400_POWER_MANAGEMENT_3, WM8400_ROPGA_ENA_SHIFT, 0, | ||
765 | NULL, 0), | ||
766 | |||
767 | /* MICBIAS */ | ||
768 | SND_SOC_DAPM_MICBIAS("MICBIAS", WM8400_POWER_MANAGEMENT_1, | ||
769 | WM8400_MIC1BIAS_ENA_SHIFT, 0), | ||
770 | |||
771 | SND_SOC_DAPM_OUTPUT("LON"), | ||
772 | SND_SOC_DAPM_OUTPUT("LOP"), | ||
773 | SND_SOC_DAPM_OUTPUT("OUT3"), | ||
774 | SND_SOC_DAPM_OUTPUT("LOUT"), | ||
775 | SND_SOC_DAPM_OUTPUT("SPKN"), | ||
776 | SND_SOC_DAPM_OUTPUT("SPKP"), | ||
777 | SND_SOC_DAPM_OUTPUT("ROUT"), | ||
778 | SND_SOC_DAPM_OUTPUT("OUT4"), | ||
779 | SND_SOC_DAPM_OUTPUT("ROP"), | ||
780 | SND_SOC_DAPM_OUTPUT("RON"), | ||
781 | |||
782 | SND_SOC_DAPM_OUTPUT("Internal DAC Sink"), | ||
783 | }; | ||
784 | |||
785 | static const struct snd_soc_dapm_route audio_map[] = { | ||
786 | /* Make DACs turn on when playing even if not mixed into any outputs */ | ||
787 | {"Internal DAC Sink", NULL, "Left DAC"}, | ||
788 | {"Internal DAC Sink", NULL, "Right DAC"}, | ||
789 | |||
790 | /* Make ADCs turn on when recording | ||
791 | * even if not mixed from any inputs */ | ||
792 | {"Left ADC", NULL, "Internal ADC Source"}, | ||
793 | {"Right ADC", NULL, "Internal ADC Source"}, | ||
794 | |||
795 | /* Input Side */ | ||
796 | /* LIN12 PGA */ | ||
797 | {"LIN12 PGA", "LIN1 Switch", "LIN1"}, | ||
798 | {"LIN12 PGA", "LIN2 Switch", "LIN2"}, | ||
799 | /* LIN34 PGA */ | ||
800 | {"LIN34 PGA", "LIN3 Switch", "LIN3"}, | ||
801 | {"LIN34 PGA", "LIN4 Switch", "LIN4/RXN"}, | ||
802 | /* INMIXL */ | ||
803 | {"INMIXL", "Record Left Volume", "LOMIX"}, | ||
804 | {"INMIXL", "LIN2 Volume", "LIN2"}, | ||
805 | {"INMIXL", "LINPGA12 Switch", "LIN12 PGA"}, | ||
806 | {"INMIXL", "LINPGA34 Switch", "LIN34 PGA"}, | ||
807 | /* AILNMUX */ | ||
808 | {"AILNMUX", "INMIXL Mix", "INMIXL"}, | ||
809 | {"AILNMUX", "DIFFINL Mix", "LIN12 PGA"}, | ||
810 | {"AILNMUX", "DIFFINL Mix", "LIN34 PGA"}, | ||
811 | {"AILNMUX", "RXVOICE Mix", "LIN4/RXN"}, | ||
812 | {"AILNMUX", "RXVOICE Mix", "RIN4/RXP"}, | ||
813 | /* ADC */ | ||
814 | {"Left ADC", NULL, "AILNMUX"}, | ||
815 | |||
816 | /* RIN12 PGA */ | ||
817 | {"RIN12 PGA", "RIN1 Switch", "RIN1"}, | ||
818 | {"RIN12 PGA", "RIN2 Switch", "RIN2"}, | ||
819 | /* RIN34 PGA */ | ||
820 | {"RIN34 PGA", "RIN3 Switch", "RIN3"}, | ||
821 | {"RIN34 PGA", "RIN4 Switch", "RIN4/RXP"}, | ||
822 | /* INMIXL */ | ||
823 | {"INMIXR", "Record Right Volume", "ROMIX"}, | ||
824 | {"INMIXR", "RIN2 Volume", "RIN2"}, | ||
825 | {"INMIXR", "RINPGA12 Switch", "RIN12 PGA"}, | ||
826 | {"INMIXR", "RINPGA34 Switch", "RIN34 PGA"}, | ||
827 | /* AIRNMUX */ | ||
828 | {"AIRNMUX", "INMIXR Mix", "INMIXR"}, | ||
829 | {"AIRNMUX", "DIFFINR Mix", "RIN12 PGA"}, | ||
830 | {"AIRNMUX", "DIFFINR Mix", "RIN34 PGA"}, | ||
831 | {"AIRNMUX", "RXVOICE Mix", "LIN4/RXN"}, | ||
832 | {"AIRNMUX", "RXVOICE Mix", "RIN4/RXP"}, | ||
833 | /* ADC */ | ||
834 | {"Right ADC", NULL, "AIRNMUX"}, | ||
835 | |||
836 | /* LOMIX */ | ||
837 | {"LOMIX", "LOMIX RIN3 Bypass Switch", "RIN3"}, | ||
838 | {"LOMIX", "LOMIX LIN3 Bypass Switch", "LIN3"}, | ||
839 | {"LOMIX", "LOMIX LIN12 PGA Bypass Switch", "LIN12 PGA"}, | ||
840 | {"LOMIX", "LOMIX RIN12 PGA Bypass Switch", "RIN12 PGA"}, | ||
841 | {"LOMIX", "LOMIX Right ADC Bypass Switch", "AIRNMUX"}, | ||
842 | {"LOMIX", "LOMIX Left ADC Bypass Switch", "AILNMUX"}, | ||
843 | {"LOMIX", "LOMIX Left DAC Switch", "Left DAC"}, | ||
844 | |||
845 | /* ROMIX */ | ||
846 | {"ROMIX", "ROMIX RIN3 Bypass Switch", "RIN3"}, | ||
847 | {"ROMIX", "ROMIX LIN3 Bypass Switch", "LIN3"}, | ||
848 | {"ROMIX", "ROMIX LIN12 PGA Bypass Switch", "LIN12 PGA"}, | ||
849 | {"ROMIX", "ROMIX RIN12 PGA Bypass Switch", "RIN12 PGA"}, | ||
850 | {"ROMIX", "ROMIX Right ADC Bypass Switch", "AIRNMUX"}, | ||
851 | {"ROMIX", "ROMIX Left ADC Bypass Switch", "AILNMUX"}, | ||
852 | {"ROMIX", "ROMIX Right DAC Switch", "Right DAC"}, | ||
853 | |||
854 | /* SPKMIX */ | ||
855 | {"SPKMIX", "SPKMIX LIN2 Bypass Switch", "LIN2"}, | ||
856 | {"SPKMIX", "SPKMIX RIN2 Bypass Switch", "RIN2"}, | ||
857 | {"SPKMIX", "SPKMIX LADC Bypass Switch", "AILNMUX"}, | ||
858 | {"SPKMIX", "SPKMIX RADC Bypass Switch", "AIRNMUX"}, | ||
859 | {"SPKMIX", "SPKMIX Left Mixer PGA Switch", "LOPGA"}, | ||
860 | {"SPKMIX", "SPKMIX Right Mixer PGA Switch", "ROPGA"}, | ||
861 | {"SPKMIX", "SPKMIX Right DAC Switch", "Right DAC"}, | ||
862 | {"SPKMIX", "SPKMIX Left DAC Switch", "Right DAC"}, | ||
863 | |||
864 | /* LONMIX */ | ||
865 | {"LONMIX", "LONMIX Left Mixer PGA Switch", "LOPGA"}, | ||
866 | {"LONMIX", "LONMIX Right Mixer PGA Switch", "ROPGA"}, | ||
867 | {"LONMIX", "LONMIX Inverted LOP Switch", "LOPMIX"}, | ||
868 | |||
869 | /* LOPMIX */ | ||
870 | {"LOPMIX", "LOPMIX Right Mic Bypass Switch", "RIN12 PGA"}, | ||
871 | {"LOPMIX", "LOPMIX Left Mic Bypass Switch", "LIN12 PGA"}, | ||
872 | {"LOPMIX", "LOPMIX Left Mixer PGA Switch", "LOPGA"}, | ||
873 | |||
874 | /* OUT3MIX */ | ||
875 | {"OUT3MIX", "OUT3MIX LIN4/RXP Bypass Switch", "LIN4/RXN"}, | ||
876 | {"OUT3MIX", "OUT3MIX Left Out PGA Switch", "LOPGA"}, | ||
877 | |||
878 | /* OUT4MIX */ | ||
879 | {"OUT4MIX", "OUT4MIX Right Out PGA Switch", "ROPGA"}, | ||
880 | {"OUT4MIX", "OUT4MIX RIN4/RXP Bypass Switch", "RIN4/RXP"}, | ||
881 | |||
882 | /* RONMIX */ | ||
883 | {"RONMIX", "RONMIX Right Mixer PGA Switch", "ROPGA"}, | ||
884 | {"RONMIX", "RONMIX Left Mixer PGA Switch", "LOPGA"}, | ||
885 | {"RONMIX", "RONMIX Inverted ROP Switch", "ROPMIX"}, | ||
886 | |||
887 | /* ROPMIX */ | ||
888 | {"ROPMIX", "ROPMIX Left Mic Bypass Switch", "LIN12 PGA"}, | ||
889 | {"ROPMIX", "ROPMIX Right Mic Bypass Switch", "RIN12 PGA"}, | ||
890 | {"ROPMIX", "ROPMIX Right Mixer PGA Switch", "ROPGA"}, | ||
891 | |||
892 | /* Out Mixer PGAs */ | ||
893 | {"LOPGA", NULL, "LOMIX"}, | ||
894 | {"ROPGA", NULL, "ROMIX"}, | ||
895 | |||
896 | {"LOUT PGA", NULL, "LOMIX"}, | ||
897 | {"ROUT PGA", NULL, "ROMIX"}, | ||
898 | |||
899 | /* Output Pins */ | ||
900 | {"LON", NULL, "LONMIX"}, | ||
901 | {"LOP", NULL, "LOPMIX"}, | ||
902 | {"OUT3", NULL, "OUT3MIX"}, | ||
903 | {"LOUT", NULL, "LOUT PGA"}, | ||
904 | {"SPKN", NULL, "SPKMIX"}, | ||
905 | {"ROUT", NULL, "ROUT PGA"}, | ||
906 | {"OUT4", NULL, "OUT4MIX"}, | ||
907 | {"ROP", NULL, "ROPMIX"}, | ||
908 | {"RON", NULL, "RONMIX"}, | ||
909 | }; | ||
910 | |||
911 | static int wm8400_add_widgets(struct snd_soc_codec *codec) | ||
912 | { | ||
913 | snd_soc_dapm_new_controls(codec, wm8400_dapm_widgets, | ||
914 | ARRAY_SIZE(wm8400_dapm_widgets)); | ||
915 | |||
916 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | ||
917 | |||
918 | snd_soc_dapm_new_widgets(codec); | ||
919 | return 0; | ||
920 | } | ||
921 | |||
922 | /* | ||
923 | * Clock after FLL and dividers | ||
924 | */ | ||
925 | static int wm8400_set_dai_sysclk(struct snd_soc_dai *codec_dai, | ||
926 | int clk_id, unsigned int freq, int dir) | ||
927 | { | ||
928 | struct snd_soc_codec *codec = codec_dai->codec; | ||
929 | struct wm8400_priv *wm8400 = codec->private_data; | ||
930 | |||
931 | wm8400->sysclk = freq; | ||
932 | return 0; | ||
933 | } | ||
934 | |||
935 | struct fll_factors { | ||
936 | u16 n; | ||
937 | u16 k; | ||
938 | u16 outdiv; | ||
939 | u16 fratio; | ||
940 | u16 freq_ref; | ||
941 | }; | ||
942 | |||
943 | #define FIXED_FLL_SIZE ((1 << 16) * 10) | ||
944 | |||
945 | static int fll_factors(struct wm8400_priv *wm8400, struct fll_factors *factors, | ||
946 | unsigned int Fref, unsigned int Fout) | ||
947 | { | ||
948 | u64 Kpart; | ||
949 | unsigned int K, Nmod, target; | ||
950 | |||
951 | factors->outdiv = 2; | ||
952 | while (Fout * factors->outdiv < 90000000 || | ||
953 | Fout * factors->outdiv > 100000000) { | ||
954 | factors->outdiv *= 2; | ||
955 | if (factors->outdiv > 32) { | ||
956 | dev_err(wm8400->wm8400->dev, | ||
957 | "Unsupported FLL output frequency %dHz\n", | ||
958 | Fout); | ||
959 | return -EINVAL; | ||
960 | } | ||
961 | } | ||
962 | target = Fout * factors->outdiv; | ||
963 | factors->outdiv = factors->outdiv >> 2; | ||
964 | |||
965 | if (Fref < 48000) | ||
966 | factors->freq_ref = 1; | ||
967 | else | ||
968 | factors->freq_ref = 0; | ||
969 | |||
970 | if (Fref < 1000000) | ||
971 | factors->fratio = 9; | ||
972 | else | ||
973 | factors->fratio = 0; | ||
974 | |||
975 | /* Ensure we have a fractional part */ | ||
976 | do { | ||
977 | if (Fref < 1000000) | ||
978 | factors->fratio--; | ||
979 | else | ||
980 | factors->fratio++; | ||
981 | |||
982 | if (factors->fratio < 1 || factors->fratio > 8) { | ||
983 | dev_err(wm8400->wm8400->dev, | ||
984 | "Unable to calculate FRATIO\n"); | ||
985 | return -EINVAL; | ||
986 | } | ||
987 | |||
988 | factors->n = target / (Fref * factors->fratio); | ||
989 | Nmod = target % (Fref * factors->fratio); | ||
990 | } while (Nmod == 0); | ||
991 | |||
992 | /* Calculate fractional part - scale up so we can round. */ | ||
993 | Kpart = FIXED_FLL_SIZE * (long long)Nmod; | ||
994 | |||
995 | do_div(Kpart, (Fref * factors->fratio)); | ||
996 | |||
997 | K = Kpart & 0xFFFFFFFF; | ||
998 | |||
999 | if ((K % 10) >= 5) | ||
1000 | K += 5; | ||
1001 | |||
1002 | /* Move down to proper range now rounding is done */ | ||
1003 | factors->k = K / 10; | ||
1004 | |||
1005 | dev_dbg(wm8400->wm8400->dev, | ||
1006 | "FLL: Fref=%d Fout=%d N=%x K=%x, FRATIO=%x OUTDIV=%x\n", | ||
1007 | Fref, Fout, | ||
1008 | factors->n, factors->k, factors->fratio, factors->outdiv); | ||
1009 | |||
1010 | return 0; | ||
1011 | } | ||
1012 | |||
1013 | static int wm8400_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, | ||
1014 | unsigned int freq_in, unsigned int freq_out) | ||
1015 | { | ||
1016 | struct snd_soc_codec *codec = codec_dai->codec; | ||
1017 | struct wm8400_priv *wm8400 = codec->private_data; | ||
1018 | struct fll_factors factors; | ||
1019 | int ret; | ||
1020 | u16 reg; | ||
1021 | |||
1022 | if (freq_in == wm8400->fll_in && freq_out == wm8400->fll_out) | ||
1023 | return 0; | ||
1024 | |||
1025 | if (freq_out != 0) { | ||
1026 | ret = fll_factors(wm8400, &factors, freq_in, freq_out); | ||
1027 | if (ret != 0) | ||
1028 | return ret; | ||
1029 | } | ||
1030 | |||
1031 | wm8400->fll_out = freq_out; | ||
1032 | wm8400->fll_in = freq_in; | ||
1033 | |||
1034 | /* We *must* disable the FLL before any changes */ | ||
1035 | reg = wm8400_read(codec, WM8400_POWER_MANAGEMENT_2); | ||
1036 | reg &= ~WM8400_FLL_ENA; | ||
1037 | wm8400_write(codec, WM8400_POWER_MANAGEMENT_2, reg); | ||
1038 | |||
1039 | reg = wm8400_read(codec, WM8400_FLL_CONTROL_1); | ||
1040 | reg &= ~WM8400_FLL_OSC_ENA; | ||
1041 | wm8400_write(codec, WM8400_FLL_CONTROL_1, reg); | ||
1042 | |||
1043 | if (freq_out == 0) | ||
1044 | return 0; | ||
1045 | |||
1046 | reg &= ~(WM8400_FLL_REF_FREQ | WM8400_FLL_FRATIO_MASK); | ||
1047 | reg |= WM8400_FLL_FRAC | factors.fratio; | ||
1048 | reg |= factors.freq_ref << WM8400_FLL_REF_FREQ_SHIFT; | ||
1049 | wm8400_write(codec, WM8400_FLL_CONTROL_1, reg); | ||
1050 | |||
1051 | wm8400_write(codec, WM8400_FLL_CONTROL_2, factors.k); | ||
1052 | wm8400_write(codec, WM8400_FLL_CONTROL_3, factors.n); | ||
1053 | |||
1054 | reg = wm8400_read(codec, WM8400_FLL_CONTROL_4); | ||
1055 | reg &= WM8400_FLL_OUTDIV_MASK; | ||
1056 | reg |= factors.outdiv; | ||
1057 | wm8400_write(codec, WM8400_FLL_CONTROL_4, reg); | ||
1058 | |||
1059 | return 0; | ||
1060 | } | ||
1061 | |||
1062 | /* | ||
1063 | * Sets ADC and Voice DAC format. | ||
1064 | */ | ||
1065 | static int wm8400_set_dai_fmt(struct snd_soc_dai *codec_dai, | ||
1066 | unsigned int fmt) | ||
1067 | { | ||
1068 | struct snd_soc_codec *codec = codec_dai->codec; | ||
1069 | u16 audio1, audio3; | ||
1070 | |||
1071 | audio1 = wm8400_read(codec, WM8400_AUDIO_INTERFACE_1); | ||
1072 | audio3 = wm8400_read(codec, WM8400_AUDIO_INTERFACE_3); | ||
1073 | |||
1074 | /* set master/slave audio interface */ | ||
1075 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
1076 | case SND_SOC_DAIFMT_CBS_CFS: | ||
1077 | audio3 &= ~WM8400_AIF_MSTR1; | ||
1078 | break; | ||
1079 | case SND_SOC_DAIFMT_CBM_CFM: | ||
1080 | audio3 |= WM8400_AIF_MSTR1; | ||
1081 | break; | ||
1082 | default: | ||
1083 | return -EINVAL; | ||
1084 | } | ||
1085 | |||
1086 | audio1 &= ~WM8400_AIF_FMT_MASK; | ||
1087 | |||
1088 | /* interface format */ | ||
1089 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
1090 | case SND_SOC_DAIFMT_I2S: | ||
1091 | audio1 |= WM8400_AIF_FMT_I2S; | ||
1092 | audio1 &= ~WM8400_AIF_LRCLK_INV; | ||
1093 | break; | ||
1094 | case SND_SOC_DAIFMT_RIGHT_J: | ||
1095 | audio1 |= WM8400_AIF_FMT_RIGHTJ; | ||
1096 | audio1 &= ~WM8400_AIF_LRCLK_INV; | ||
1097 | break; | ||
1098 | case SND_SOC_DAIFMT_LEFT_J: | ||
1099 | audio1 |= WM8400_AIF_FMT_LEFTJ; | ||
1100 | audio1 &= ~WM8400_AIF_LRCLK_INV; | ||
1101 | break; | ||
1102 | case SND_SOC_DAIFMT_DSP_A: | ||
1103 | audio1 |= WM8400_AIF_FMT_DSP; | ||
1104 | audio1 &= ~WM8400_AIF_LRCLK_INV; | ||
1105 | break; | ||
1106 | case SND_SOC_DAIFMT_DSP_B: | ||
1107 | audio1 |= WM8400_AIF_FMT_DSP | WM8400_AIF_LRCLK_INV; | ||
1108 | break; | ||
1109 | default: | ||
1110 | return -EINVAL; | ||
1111 | } | ||
1112 | |||
1113 | wm8400_write(codec, WM8400_AUDIO_INTERFACE_1, audio1); | ||
1114 | wm8400_write(codec, WM8400_AUDIO_INTERFACE_3, audio3); | ||
1115 | return 0; | ||
1116 | } | ||
1117 | |||
1118 | static int wm8400_set_dai_clkdiv(struct snd_soc_dai *codec_dai, | ||
1119 | int div_id, int div) | ||
1120 | { | ||
1121 | struct snd_soc_codec *codec = codec_dai->codec; | ||
1122 | u16 reg; | ||
1123 | |||
1124 | switch (div_id) { | ||
1125 | case WM8400_MCLK_DIV: | ||
1126 | reg = wm8400_read(codec, WM8400_CLOCKING_2) & | ||
1127 | ~WM8400_MCLK_DIV_MASK; | ||
1128 | wm8400_write(codec, WM8400_CLOCKING_2, reg | div); | ||
1129 | break; | ||
1130 | case WM8400_DACCLK_DIV: | ||
1131 | reg = wm8400_read(codec, WM8400_CLOCKING_2) & | ||
1132 | ~WM8400_DAC_CLKDIV_MASK; | ||
1133 | wm8400_write(codec, WM8400_CLOCKING_2, reg | div); | ||
1134 | break; | ||
1135 | case WM8400_ADCCLK_DIV: | ||
1136 | reg = wm8400_read(codec, WM8400_CLOCKING_2) & | ||
1137 | ~WM8400_ADC_CLKDIV_MASK; | ||
1138 | wm8400_write(codec, WM8400_CLOCKING_2, reg | div); | ||
1139 | break; | ||
1140 | case WM8400_BCLK_DIV: | ||
1141 | reg = wm8400_read(codec, WM8400_CLOCKING_1) & | ||
1142 | ~WM8400_BCLK_DIV_MASK; | ||
1143 | wm8400_write(codec, WM8400_CLOCKING_1, reg | div); | ||
1144 | break; | ||
1145 | default: | ||
1146 | return -EINVAL; | ||
1147 | } | ||
1148 | |||
1149 | return 0; | ||
1150 | } | ||
1151 | |||
1152 | /* | ||
1153 | * Set PCM DAI bit size and sample rate. | ||
1154 | */ | ||
1155 | static int wm8400_hw_params(struct snd_pcm_substream *substream, | ||
1156 | struct snd_pcm_hw_params *params, | ||
1157 | struct snd_soc_dai *dai) | ||
1158 | { | ||
1159 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
1160 | struct snd_soc_device *socdev = rtd->socdev; | ||
1161 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1162 | u16 audio1 = wm8400_read(codec, WM8400_AUDIO_INTERFACE_1); | ||
1163 | |||
1164 | audio1 &= ~WM8400_AIF_WL_MASK; | ||
1165 | /* bit size */ | ||
1166 | switch (params_format(params)) { | ||
1167 | case SNDRV_PCM_FORMAT_S16_LE: | ||
1168 | break; | ||
1169 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
1170 | audio1 |= WM8400_AIF_WL_20BITS; | ||
1171 | break; | ||
1172 | case SNDRV_PCM_FORMAT_S24_LE: | ||
1173 | audio1 |= WM8400_AIF_WL_24BITS; | ||
1174 | break; | ||
1175 | case SNDRV_PCM_FORMAT_S32_LE: | ||
1176 | audio1 |= WM8400_AIF_WL_32BITS; | ||
1177 | break; | ||
1178 | } | ||
1179 | |||
1180 | wm8400_write(codec, WM8400_AUDIO_INTERFACE_1, audio1); | ||
1181 | return 0; | ||
1182 | } | ||
1183 | |||
1184 | static int wm8400_mute(struct snd_soc_dai *dai, int mute) | ||
1185 | { | ||
1186 | struct snd_soc_codec *codec = dai->codec; | ||
1187 | u16 val = wm8400_read(codec, WM8400_DAC_CTRL) & ~WM8400_DAC_MUTE; | ||
1188 | |||
1189 | if (mute) | ||
1190 | wm8400_write(codec, WM8400_DAC_CTRL, val | WM8400_DAC_MUTE); | ||
1191 | else | ||
1192 | wm8400_write(codec, WM8400_DAC_CTRL, val); | ||
1193 | |||
1194 | return 0; | ||
1195 | } | ||
1196 | |||
1197 | /* TODO: set bias for best performance at standby */ | ||
1198 | static int wm8400_set_bias_level(struct snd_soc_codec *codec, | ||
1199 | enum snd_soc_bias_level level) | ||
1200 | { | ||
1201 | struct wm8400_priv *wm8400 = codec->private_data; | ||
1202 | u16 val; | ||
1203 | int ret; | ||
1204 | |||
1205 | switch (level) { | ||
1206 | case SND_SOC_BIAS_ON: | ||
1207 | break; | ||
1208 | |||
1209 | case SND_SOC_BIAS_PREPARE: | ||
1210 | /* VMID=2*50k */ | ||
1211 | val = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1) & | ||
1212 | ~WM8400_VMID_MODE_MASK; | ||
1213 | wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val | 0x2); | ||
1214 | break; | ||
1215 | |||
1216 | case SND_SOC_BIAS_STANDBY: | ||
1217 | if (codec->bias_level == SND_SOC_BIAS_OFF) { | ||
1218 | ret = regulator_bulk_enable(ARRAY_SIZE(power), | ||
1219 | &power[0]); | ||
1220 | if (ret != 0) { | ||
1221 | dev_err(wm8400->wm8400->dev, | ||
1222 | "Failed to enable regulators: %d\n", | ||
1223 | ret); | ||
1224 | return ret; | ||
1225 | } | ||
1226 | |||
1227 | wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, | ||
1228 | WM8400_CODEC_ENA | WM8400_SYSCLK_ENA); | ||
1229 | |||
1230 | /* Enable POBCTRL, SOFT_ST, VMIDTOG and BUFDCOPEN */ | ||
1231 | wm8400_write(codec, WM8400_ANTIPOP2, WM8400_SOFTST | | ||
1232 | WM8400_BUFDCOPEN | WM8400_POBCTRL); | ||
1233 | |||
1234 | msleep(50); | ||
1235 | |||
1236 | /* Enable VREF & VMID at 2x50k */ | ||
1237 | val = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1); | ||
1238 | val |= 0x2 | WM8400_VREF_ENA; | ||
1239 | wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val); | ||
1240 | |||
1241 | /* Enable BUFIOEN */ | ||
1242 | wm8400_write(codec, WM8400_ANTIPOP2, WM8400_SOFTST | | ||
1243 | WM8400_BUFDCOPEN | WM8400_POBCTRL | | ||
1244 | WM8400_BUFIOEN); | ||
1245 | |||
1246 | /* disable POBCTRL, SOFT_ST and BUFDCOPEN */ | ||
1247 | wm8400_write(codec, WM8400_ANTIPOP2, WM8400_BUFIOEN); | ||
1248 | } | ||
1249 | |||
1250 | /* VMID=2*300k */ | ||
1251 | val = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1) & | ||
1252 | ~WM8400_VMID_MODE_MASK; | ||
1253 | wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val | 0x4); | ||
1254 | break; | ||
1255 | |||
1256 | case SND_SOC_BIAS_OFF: | ||
1257 | /* Enable POBCTRL and SOFT_ST */ | ||
1258 | wm8400_write(codec, WM8400_ANTIPOP2, WM8400_SOFTST | | ||
1259 | WM8400_POBCTRL | WM8400_BUFIOEN); | ||
1260 | |||
1261 | /* Enable POBCTRL, SOFT_ST and BUFDCOPEN */ | ||
1262 | wm8400_write(codec, WM8400_ANTIPOP2, WM8400_SOFTST | | ||
1263 | WM8400_BUFDCOPEN | WM8400_POBCTRL | | ||
1264 | WM8400_BUFIOEN); | ||
1265 | |||
1266 | /* mute DAC */ | ||
1267 | val = wm8400_read(codec, WM8400_DAC_CTRL); | ||
1268 | wm8400_write(codec, WM8400_DAC_CTRL, val | WM8400_DAC_MUTE); | ||
1269 | |||
1270 | /* Enable any disabled outputs */ | ||
1271 | val = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1); | ||
1272 | val |= WM8400_SPK_ENA | WM8400_OUT3_ENA | | ||
1273 | WM8400_OUT4_ENA | WM8400_LOUT_ENA | | ||
1274 | WM8400_ROUT_ENA; | ||
1275 | wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val); | ||
1276 | |||
1277 | /* Disable VMID */ | ||
1278 | val &= ~WM8400_VMID_MODE_MASK; | ||
1279 | wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val); | ||
1280 | |||
1281 | msleep(300); | ||
1282 | |||
1283 | /* Enable all output discharge bits */ | ||
1284 | wm8400_write(codec, WM8400_ANTIPOP1, WM8400_DIS_LLINE | | ||
1285 | WM8400_DIS_RLINE | WM8400_DIS_OUT3 | | ||
1286 | WM8400_DIS_OUT4 | WM8400_DIS_LOUT | | ||
1287 | WM8400_DIS_ROUT); | ||
1288 | |||
1289 | /* Disable VREF */ | ||
1290 | val &= ~WM8400_VREF_ENA; | ||
1291 | wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val); | ||
1292 | |||
1293 | /* disable POBCTRL, SOFT_ST and BUFDCOPEN */ | ||
1294 | wm8400_write(codec, WM8400_ANTIPOP2, 0x0); | ||
1295 | |||
1296 | ret = regulator_bulk_disable(ARRAY_SIZE(power), | ||
1297 | &power[0]); | ||
1298 | if (ret != 0) | ||
1299 | return ret; | ||
1300 | |||
1301 | break; | ||
1302 | } | ||
1303 | |||
1304 | codec->bias_level = level; | ||
1305 | return 0; | ||
1306 | } | ||
1307 | |||
1308 | #define WM8400_RATES SNDRV_PCM_RATE_8000_96000 | ||
1309 | |||
1310 | #define WM8400_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | ||
1311 | SNDRV_PCM_FMTBIT_S24_LE) | ||
1312 | |||
1313 | static struct snd_soc_dai_ops wm8400_dai_ops = { | ||
1314 | .hw_params = wm8400_hw_params, | ||
1315 | .digital_mute = wm8400_mute, | ||
1316 | .set_fmt = wm8400_set_dai_fmt, | ||
1317 | .set_clkdiv = wm8400_set_dai_clkdiv, | ||
1318 | .set_sysclk = wm8400_set_dai_sysclk, | ||
1319 | .set_pll = wm8400_set_dai_pll, | ||
1320 | }; | ||
1321 | |||
1322 | /* | ||
1323 | * The WM8400 supports 2 different and mutually exclusive DAI | ||
1324 | * configurations. | ||
1325 | * | ||
1326 | * 1. ADC/DAC on Primary Interface | ||
1327 | * 2. ADC on Primary Interface/DAC on secondary | ||
1328 | */ | ||
1329 | struct snd_soc_dai wm8400_dai = { | ||
1330 | /* ADC/DAC on primary */ | ||
1331 | .name = "WM8400 ADC/DAC Primary", | ||
1332 | .id = 1, | ||
1333 | .playback = { | ||
1334 | .stream_name = "Playback", | ||
1335 | .channels_min = 1, | ||
1336 | .channels_max = 2, | ||
1337 | .rates = WM8400_RATES, | ||
1338 | .formats = WM8400_FORMATS, | ||
1339 | }, | ||
1340 | .capture = { | ||
1341 | .stream_name = "Capture", | ||
1342 | .channels_min = 1, | ||
1343 | .channels_max = 2, | ||
1344 | .rates = WM8400_RATES, | ||
1345 | .formats = WM8400_FORMATS, | ||
1346 | }, | ||
1347 | .ops = &wm8400_dai_ops, | ||
1348 | }; | ||
1349 | EXPORT_SYMBOL_GPL(wm8400_dai); | ||
1350 | |||
1351 | static int wm8400_suspend(struct platform_device *pdev, pm_message_t state) | ||
1352 | { | ||
1353 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1354 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1355 | |||
1356 | wm8400_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1357 | |||
1358 | return 0; | ||
1359 | } | ||
1360 | |||
1361 | static int wm8400_resume(struct platform_device *pdev) | ||
1362 | { | ||
1363 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1364 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1365 | |||
1366 | wm8400_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1367 | |||
1368 | return 0; | ||
1369 | } | ||
1370 | |||
1371 | static struct snd_soc_codec *wm8400_codec; | ||
1372 | |||
1373 | static int wm8400_probe(struct platform_device *pdev) | ||
1374 | { | ||
1375 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1376 | struct snd_soc_codec *codec; | ||
1377 | int ret; | ||
1378 | |||
1379 | if (!wm8400_codec) { | ||
1380 | dev_err(&pdev->dev, "wm8400 not yet discovered\n"); | ||
1381 | return -ENODEV; | ||
1382 | } | ||
1383 | codec = wm8400_codec; | ||
1384 | |||
1385 | socdev->card->codec = codec; | ||
1386 | |||
1387 | /* register pcms */ | ||
1388 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
1389 | if (ret < 0) { | ||
1390 | dev_err(&pdev->dev, "failed to create pcms\n"); | ||
1391 | goto pcm_err; | ||
1392 | } | ||
1393 | |||
1394 | wm8400_add_controls(codec); | ||
1395 | wm8400_add_widgets(codec); | ||
1396 | |||
1397 | ret = snd_soc_init_card(socdev); | ||
1398 | if (ret < 0) { | ||
1399 | dev_err(&pdev->dev, "failed to register card\n"); | ||
1400 | goto card_err; | ||
1401 | } | ||
1402 | |||
1403 | return ret; | ||
1404 | |||
1405 | card_err: | ||
1406 | snd_soc_free_pcms(socdev); | ||
1407 | snd_soc_dapm_free(socdev); | ||
1408 | pcm_err: | ||
1409 | return ret; | ||
1410 | } | ||
1411 | |||
1412 | /* power down chip */ | ||
1413 | static int wm8400_remove(struct platform_device *pdev) | ||
1414 | { | ||
1415 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1416 | |||
1417 | snd_soc_free_pcms(socdev); | ||
1418 | snd_soc_dapm_free(socdev); | ||
1419 | |||
1420 | return 0; | ||
1421 | } | ||
1422 | |||
1423 | struct snd_soc_codec_device soc_codec_dev_wm8400 = { | ||
1424 | .probe = wm8400_probe, | ||
1425 | .remove = wm8400_remove, | ||
1426 | .suspend = wm8400_suspend, | ||
1427 | .resume = wm8400_resume, | ||
1428 | }; | ||
1429 | |||
1430 | static void wm8400_probe_deferred(struct work_struct *work) | ||
1431 | { | ||
1432 | struct wm8400_priv *priv = container_of(work, struct wm8400_priv, | ||
1433 | work); | ||
1434 | struct snd_soc_codec *codec = &priv->codec; | ||
1435 | int ret; | ||
1436 | |||
1437 | /* charge output caps */ | ||
1438 | wm8400_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1439 | |||
1440 | /* We're done, tell the subsystem. */ | ||
1441 | ret = snd_soc_register_codec(codec); | ||
1442 | if (ret != 0) { | ||
1443 | dev_err(priv->wm8400->dev, | ||
1444 | "Failed to register codec: %d\n", ret); | ||
1445 | goto err; | ||
1446 | } | ||
1447 | |||
1448 | ret = snd_soc_register_dai(&wm8400_dai); | ||
1449 | if (ret != 0) { | ||
1450 | dev_err(priv->wm8400->dev, | ||
1451 | "Failed to register DAI: %d\n", ret); | ||
1452 | goto err_codec; | ||
1453 | } | ||
1454 | |||
1455 | return; | ||
1456 | |||
1457 | err_codec: | ||
1458 | snd_soc_unregister_codec(codec); | ||
1459 | err: | ||
1460 | wm8400_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1461 | } | ||
1462 | |||
1463 | static int wm8400_codec_probe(struct platform_device *dev) | ||
1464 | { | ||
1465 | struct wm8400_priv *priv; | ||
1466 | int ret; | ||
1467 | u16 reg; | ||
1468 | struct snd_soc_codec *codec; | ||
1469 | |||
1470 | priv = kzalloc(sizeof(struct wm8400_priv), GFP_KERNEL); | ||
1471 | if (priv == NULL) | ||
1472 | return -ENOMEM; | ||
1473 | |||
1474 | codec = &priv->codec; | ||
1475 | codec->private_data = priv; | ||
1476 | codec->control_data = dev->dev.driver_data; | ||
1477 | priv->wm8400 = dev->dev.driver_data; | ||
1478 | |||
1479 | ret = regulator_bulk_get(priv->wm8400->dev, | ||
1480 | ARRAY_SIZE(power), &power[0]); | ||
1481 | if (ret != 0) { | ||
1482 | dev_err(&dev->dev, "Failed to get regulators: %d\n", ret); | ||
1483 | goto err; | ||
1484 | } | ||
1485 | |||
1486 | codec->dev = &dev->dev; | ||
1487 | wm8400_dai.dev = &dev->dev; | ||
1488 | |||
1489 | codec->name = "WM8400"; | ||
1490 | codec->owner = THIS_MODULE; | ||
1491 | codec->read = wm8400_read; | ||
1492 | codec->write = wm8400_write; | ||
1493 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
1494 | codec->set_bias_level = wm8400_set_bias_level; | ||
1495 | codec->dai = &wm8400_dai; | ||
1496 | codec->num_dai = 1; | ||
1497 | codec->reg_cache_size = WM8400_REGISTER_COUNT; | ||
1498 | mutex_init(&codec->mutex); | ||
1499 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1500 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1501 | INIT_WORK(&priv->work, wm8400_probe_deferred); | ||
1502 | |||
1503 | wm8400_codec_reset(codec); | ||
1504 | |||
1505 | reg = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1); | ||
1506 | wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, reg | WM8400_CODEC_ENA); | ||
1507 | |||
1508 | /* Latch volume update bits */ | ||
1509 | reg = wm8400_read(codec, WM8400_LEFT_LINE_INPUT_1_2_VOLUME); | ||
1510 | wm8400_write(codec, WM8400_LEFT_LINE_INPUT_1_2_VOLUME, | ||
1511 | reg & WM8400_IPVU); | ||
1512 | reg = wm8400_read(codec, WM8400_RIGHT_LINE_INPUT_1_2_VOLUME); | ||
1513 | wm8400_write(codec, WM8400_RIGHT_LINE_INPUT_1_2_VOLUME, | ||
1514 | reg & WM8400_IPVU); | ||
1515 | |||
1516 | wm8400_write(codec, WM8400_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8)); | ||
1517 | wm8400_write(codec, WM8400_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8)); | ||
1518 | |||
1519 | wm8400_codec = codec; | ||
1520 | |||
1521 | if (!schedule_work(&priv->work)) { | ||
1522 | ret = -EINVAL; | ||
1523 | goto err_regulator; | ||
1524 | } | ||
1525 | |||
1526 | return 0; | ||
1527 | |||
1528 | err_regulator: | ||
1529 | wm8400_codec = NULL; | ||
1530 | regulator_bulk_free(ARRAY_SIZE(power), power); | ||
1531 | err: | ||
1532 | kfree(priv); | ||
1533 | return ret; | ||
1534 | } | ||
1535 | |||
1536 | static int __exit wm8400_codec_remove(struct platform_device *dev) | ||
1537 | { | ||
1538 | struct wm8400_priv *priv = wm8400_codec->private_data; | ||
1539 | u16 reg; | ||
1540 | |||
1541 | snd_soc_unregister_dai(&wm8400_dai); | ||
1542 | snd_soc_unregister_codec(wm8400_codec); | ||
1543 | |||
1544 | reg = wm8400_read(wm8400_codec, WM8400_POWER_MANAGEMENT_1); | ||
1545 | wm8400_write(wm8400_codec, WM8400_POWER_MANAGEMENT_1, | ||
1546 | reg & (~WM8400_CODEC_ENA)); | ||
1547 | |||
1548 | regulator_bulk_free(ARRAY_SIZE(power), power); | ||
1549 | kfree(priv); | ||
1550 | |||
1551 | wm8400_codec = NULL; | ||
1552 | |||
1553 | return 0; | ||
1554 | } | ||
1555 | |||
1556 | static struct platform_driver wm8400_codec_driver = { | ||
1557 | .driver = { | ||
1558 | .name = "wm8400-codec", | ||
1559 | .owner = THIS_MODULE, | ||
1560 | }, | ||
1561 | .probe = wm8400_codec_probe, | ||
1562 | .remove = __exit_p(wm8400_codec_remove), | ||
1563 | }; | ||
1564 | |||
1565 | static int __init wm8400_codec_init(void) | ||
1566 | { | ||
1567 | return platform_driver_register(&wm8400_codec_driver); | ||
1568 | } | ||
1569 | module_init(wm8400_codec_init); | ||
1570 | |||
1571 | static void __exit wm8400_codec_exit(void) | ||
1572 | { | ||
1573 | platform_driver_unregister(&wm8400_codec_driver); | ||
1574 | } | ||
1575 | module_exit(wm8400_codec_exit); | ||
1576 | |||
1577 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8400); | ||
1578 | |||
1579 | MODULE_DESCRIPTION("ASoC WM8400 driver"); | ||
1580 | MODULE_AUTHOR("Mark Brown"); | ||
1581 | MODULE_LICENSE("GPL"); | ||
1582 | MODULE_ALIAS("platform:wm8400-codec"); | ||
diff --git a/sound/soc/codecs/wm8400.h b/sound/soc/codecs/wm8400.h new file mode 100644 index 000000000000..79c5934d4776 --- /dev/null +++ b/sound/soc/codecs/wm8400.h | |||
@@ -0,0 +1,62 @@ | |||
1 | /* | ||
2 | * wm8400.h -- audio driver for WM8400 | ||
3 | * | ||
4 | * Copyright 2008 Wolfson Microelectronics PLC. | ||
5 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #ifndef _WM8400_CODEC_H | ||
15 | #define _WM8400_CODEC_H | ||
16 | |||
17 | #define WM8400_MCLK_DIV 0 | ||
18 | #define WM8400_DACCLK_DIV 1 | ||
19 | #define WM8400_ADCCLK_DIV 2 | ||
20 | #define WM8400_BCLK_DIV 3 | ||
21 | |||
22 | #define WM8400_MCLK_DIV_1 0x400 | ||
23 | #define WM8400_MCLK_DIV_2 0x800 | ||
24 | |||
25 | #define WM8400_DAC_CLKDIV_1 0x00 | ||
26 | #define WM8400_DAC_CLKDIV_1_5 0x04 | ||
27 | #define WM8400_DAC_CLKDIV_2 0x08 | ||
28 | #define WM8400_DAC_CLKDIV_3 0x0c | ||
29 | #define WM8400_DAC_CLKDIV_4 0x10 | ||
30 | #define WM8400_DAC_CLKDIV_5_5 0x14 | ||
31 | #define WM8400_DAC_CLKDIV_6 0x18 | ||
32 | |||
33 | #define WM8400_ADC_CLKDIV_1 0x00 | ||
34 | #define WM8400_ADC_CLKDIV_1_5 0x20 | ||
35 | #define WM8400_ADC_CLKDIV_2 0x40 | ||
36 | #define WM8400_ADC_CLKDIV_3 0x60 | ||
37 | #define WM8400_ADC_CLKDIV_4 0x80 | ||
38 | #define WM8400_ADC_CLKDIV_5_5 0xa0 | ||
39 | #define WM8400_ADC_CLKDIV_6 0xc0 | ||
40 | |||
41 | |||
42 | #define WM8400_BCLK_DIV_1 (0x0 << 1) | ||
43 | #define WM8400_BCLK_DIV_1_5 (0x1 << 1) | ||
44 | #define WM8400_BCLK_DIV_2 (0x2 << 1) | ||
45 | #define WM8400_BCLK_DIV_3 (0x3 << 1) | ||
46 | #define WM8400_BCLK_DIV_4 (0x4 << 1) | ||
47 | #define WM8400_BCLK_DIV_5_5 (0x5 << 1) | ||
48 | #define WM8400_BCLK_DIV_6 (0x6 << 1) | ||
49 | #define WM8400_BCLK_DIV_8 (0x7 << 1) | ||
50 | #define WM8400_BCLK_DIV_11 (0x8 << 1) | ||
51 | #define WM8400_BCLK_DIV_12 (0x9 << 1) | ||
52 | #define WM8400_BCLK_DIV_16 (0xA << 1) | ||
53 | #define WM8400_BCLK_DIV_22 (0xB << 1) | ||
54 | #define WM8400_BCLK_DIV_24 (0xC << 1) | ||
55 | #define WM8400_BCLK_DIV_32 (0xD << 1) | ||
56 | #define WM8400_BCLK_DIV_44 (0xE << 1) | ||
57 | #define WM8400_BCLK_DIV_48 (0xF << 1) | ||
58 | |||
59 | extern struct snd_soc_dai wm8400_dai; | ||
60 | extern struct snd_soc_codec_device soc_codec_dev_wm8400; | ||
61 | |||
62 | #endif | ||
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index 40f8238df717..6a4cea09c45d 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c | |||
@@ -171,22 +171,6 @@ SOC_SINGLE("Capture Boost(+20dB)", WM8510_ADCBOOST, 8, 1, 0), | |||
171 | SOC_SINGLE("Mono Playback Switch", WM8510_MONOMIX, 6, 1, 1), | 171 | SOC_SINGLE("Mono Playback Switch", WM8510_MONOMIX, 6, 1, 1), |
172 | }; | 172 | }; |
173 | 173 | ||
174 | /* add non dapm controls */ | ||
175 | static int wm8510_add_controls(struct snd_soc_codec *codec) | ||
176 | { | ||
177 | int err, i; | ||
178 | |||
179 | for (i = 0; i < ARRAY_SIZE(wm8510_snd_controls); i++) { | ||
180 | err = snd_ctl_add(codec->card, | ||
181 | snd_soc_cnew(&wm8510_snd_controls[i], codec, | ||
182 | NULL)); | ||
183 | if (err < 0) | ||
184 | return err; | ||
185 | } | ||
186 | |||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | /* Speaker Output Mixer */ | 174 | /* Speaker Output Mixer */ |
191 | static const struct snd_kcontrol_new wm8510_speaker_mixer_controls[] = { | 175 | static const struct snd_kcontrol_new wm8510_speaker_mixer_controls[] = { |
192 | SOC_DAPM_SINGLE("Line Bypass Switch", WM8510_SPKMIX, 1, 1, 0), | 176 | SOC_DAPM_SINGLE("Line Bypass Switch", WM8510_SPKMIX, 1, 1, 0), |
@@ -352,7 +336,7 @@ static int wm8510_set_dai_pll(struct snd_soc_dai *codec_dai, | |||
352 | return 0; | 336 | return 0; |
353 | } | 337 | } |
354 | 338 | ||
355 | pll_factors(freq_out*8, freq_in); | 339 | pll_factors(freq_out*4, freq_in); |
356 | 340 | ||
357 | wm8510_write(codec, WM8510_PLLN, (pll_div.pre_div << 4) | pll_div.n); | 341 | wm8510_write(codec, WM8510_PLLN, (pll_div.pre_div << 4) | pll_div.n); |
358 | wm8510_write(codec, WM8510_PLLK1, pll_div.k >> 18); | 342 | wm8510_write(codec, WM8510_PLLK1, pll_div.k >> 18); |
@@ -383,7 +367,7 @@ static int wm8510_set_dai_clkdiv(struct snd_soc_dai *codec_dai, | |||
383 | wm8510_write(codec, WM8510_GPIO, reg | div); | 367 | wm8510_write(codec, WM8510_GPIO, reg | div); |
384 | break; | 368 | break; |
385 | case WM8510_MCLKDIV: | 369 | case WM8510_MCLKDIV: |
386 | reg = wm8510_read_reg_cache(codec, WM8510_CLOCK) & 0x1f; | 370 | reg = wm8510_read_reg_cache(codec, WM8510_CLOCK) & 0x11f; |
387 | wm8510_write(codec, WM8510_CLOCK, reg | div); | 371 | wm8510_write(codec, WM8510_CLOCK, reg | div); |
388 | break; | 372 | break; |
389 | case WM8510_ADCCLK: | 373 | case WM8510_ADCCLK: |
@@ -468,7 +452,7 @@ static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream, | |||
468 | { | 452 | { |
469 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 453 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
470 | struct snd_soc_device *socdev = rtd->socdev; | 454 | struct snd_soc_device *socdev = rtd->socdev; |
471 | struct snd_soc_codec *codec = socdev->codec; | 455 | struct snd_soc_codec *codec = socdev->card->codec; |
472 | u16 iface = wm8510_read_reg_cache(codec, WM8510_IFACE) & 0x19f; | 456 | u16 iface = wm8510_read_reg_cache(codec, WM8510_IFACE) & 0x19f; |
473 | u16 adn = wm8510_read_reg_cache(codec, WM8510_ADD) & 0x1f1; | 457 | u16 adn = wm8510_read_reg_cache(codec, WM8510_ADD) & 0x1f1; |
474 | 458 | ||
@@ -570,6 +554,14 @@ static int wm8510_set_bias_level(struct snd_soc_codec *codec, | |||
570 | #define WM8510_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | 554 | #define WM8510_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ |
571 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) | 555 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) |
572 | 556 | ||
557 | static struct snd_soc_dai_ops wm8510_dai_ops = { | ||
558 | .hw_params = wm8510_pcm_hw_params, | ||
559 | .digital_mute = wm8510_mute, | ||
560 | .set_fmt = wm8510_set_dai_fmt, | ||
561 | .set_clkdiv = wm8510_set_dai_clkdiv, | ||
562 | .set_pll = wm8510_set_dai_pll, | ||
563 | }; | ||
564 | |||
573 | struct snd_soc_dai wm8510_dai = { | 565 | struct snd_soc_dai wm8510_dai = { |
574 | .name = "WM8510 HiFi", | 566 | .name = "WM8510 HiFi", |
575 | .playback = { | 567 | .playback = { |
@@ -584,20 +576,14 @@ struct snd_soc_dai wm8510_dai = { | |||
584 | .channels_max = 2, | 576 | .channels_max = 2, |
585 | .rates = WM8510_RATES, | 577 | .rates = WM8510_RATES, |
586 | .formats = WM8510_FORMATS,}, | 578 | .formats = WM8510_FORMATS,}, |
587 | .ops = { | 579 | .ops = &wm8510_dai_ops, |
588 | .hw_params = wm8510_pcm_hw_params, | ||
589 | .digital_mute = wm8510_mute, | ||
590 | .set_fmt = wm8510_set_dai_fmt, | ||
591 | .set_clkdiv = wm8510_set_dai_clkdiv, | ||
592 | .set_pll = wm8510_set_dai_pll, | ||
593 | }, | ||
594 | }; | 580 | }; |
595 | EXPORT_SYMBOL_GPL(wm8510_dai); | 581 | EXPORT_SYMBOL_GPL(wm8510_dai); |
596 | 582 | ||
597 | static int wm8510_suspend(struct platform_device *pdev, pm_message_t state) | 583 | static int wm8510_suspend(struct platform_device *pdev, pm_message_t state) |
598 | { | 584 | { |
599 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 585 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
600 | struct snd_soc_codec *codec = socdev->codec; | 586 | struct snd_soc_codec *codec = socdev->card->codec; |
601 | 587 | ||
602 | wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF); | 588 | wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF); |
603 | return 0; | 589 | return 0; |
@@ -606,7 +592,7 @@ static int wm8510_suspend(struct platform_device *pdev, pm_message_t state) | |||
606 | static int wm8510_resume(struct platform_device *pdev) | 592 | static int wm8510_resume(struct platform_device *pdev) |
607 | { | 593 | { |
608 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 594 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
609 | struct snd_soc_codec *codec = socdev->codec; | 595 | struct snd_soc_codec *codec = socdev->card->codec; |
610 | int i; | 596 | int i; |
611 | u8 data[2]; | 597 | u8 data[2]; |
612 | u16 *cache = codec->reg_cache; | 598 | u16 *cache = codec->reg_cache; |
@@ -628,7 +614,7 @@ static int wm8510_resume(struct platform_device *pdev) | |||
628 | */ | 614 | */ |
629 | static int wm8510_init(struct snd_soc_device *socdev) | 615 | static int wm8510_init(struct snd_soc_device *socdev) |
630 | { | 616 | { |
631 | struct snd_soc_codec *codec = socdev->codec; | 617 | struct snd_soc_codec *codec = socdev->card->codec; |
632 | int ret = 0; | 618 | int ret = 0; |
633 | 619 | ||
634 | codec->name = "WM8510"; | 620 | codec->name = "WM8510"; |
@@ -656,7 +642,8 @@ static int wm8510_init(struct snd_soc_device *socdev) | |||
656 | /* power on device */ | 642 | /* power on device */ |
657 | codec->bias_level = SND_SOC_BIAS_OFF; | 643 | codec->bias_level = SND_SOC_BIAS_OFF; |
658 | wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 644 | wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
659 | wm8510_add_controls(codec); | 645 | snd_soc_add_controls(codec, wm8510_snd_controls, |
646 | ARRAY_SIZE(wm8510_snd_controls)); | ||
660 | wm8510_add_widgets(codec); | 647 | wm8510_add_widgets(codec); |
661 | ret = snd_soc_init_card(socdev); | 648 | ret = snd_soc_init_card(socdev); |
662 | if (ret < 0) { | 649 | if (ret < 0) { |
@@ -685,7 +672,7 @@ static int wm8510_i2c_probe(struct i2c_client *i2c, | |||
685 | const struct i2c_device_id *id) | 672 | const struct i2c_device_id *id) |
686 | { | 673 | { |
687 | struct snd_soc_device *socdev = wm8510_socdev; | 674 | struct snd_soc_device *socdev = wm8510_socdev; |
688 | struct snd_soc_codec *codec = socdev->codec; | 675 | struct snd_soc_codec *codec = socdev->card->codec; |
689 | int ret; | 676 | int ret; |
690 | 677 | ||
691 | i2c_set_clientdata(i2c, codec); | 678 | i2c_set_clientdata(i2c, codec); |
@@ -766,7 +753,7 @@ err_driver: | |||
766 | static int __devinit wm8510_spi_probe(struct spi_device *spi) | 753 | static int __devinit wm8510_spi_probe(struct spi_device *spi) |
767 | { | 754 | { |
768 | struct snd_soc_device *socdev = wm8510_socdev; | 755 | struct snd_soc_device *socdev = wm8510_socdev; |
769 | struct snd_soc_codec *codec = socdev->codec; | 756 | struct snd_soc_codec *codec = socdev->card->codec; |
770 | int ret; | 757 | int ret; |
771 | 758 | ||
772 | codec->control_data = spi; | 759 | codec->control_data = spi; |
@@ -832,7 +819,7 @@ static int wm8510_probe(struct platform_device *pdev) | |||
832 | if (codec == NULL) | 819 | if (codec == NULL) |
833 | return -ENOMEM; | 820 | return -ENOMEM; |
834 | 821 | ||
835 | socdev->codec = codec; | 822 | socdev->card->codec = codec; |
836 | mutex_init(&codec->mutex); | 823 | mutex_init(&codec->mutex); |
837 | INIT_LIST_HEAD(&codec->dapm_widgets); | 824 | INIT_LIST_HEAD(&codec->dapm_widgets); |
838 | INIT_LIST_HEAD(&codec->dapm_paths); | 825 | INIT_LIST_HEAD(&codec->dapm_paths); |
@@ -862,7 +849,7 @@ static int wm8510_probe(struct platform_device *pdev) | |||
862 | static int wm8510_remove(struct platform_device *pdev) | 849 | static int wm8510_remove(struct platform_device *pdev) |
863 | { | 850 | { |
864 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 851 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
865 | struct snd_soc_codec *codec = socdev->codec; | 852 | struct snd_soc_codec *codec = socdev->card->codec; |
866 | 853 | ||
867 | if (codec->control_data) | 854 | if (codec->control_data) |
868 | wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF); | 855 | wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF); |
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index d004e5845298..442ea6f160fc 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * wm8580.c -- WM8580 ALSA Soc Audio driver | 2 | * wm8580.c -- WM8580 ALSA Soc Audio driver |
3 | * | 3 | * |
4 | * Copyright 2008 Wolfson Microelectronics PLC. | 4 | * Copyright 2008, 2009 Wolfson Microelectronics PLC. |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms of the GNU General Public License as published by the | 7 | * under the terms of the GNU General Public License as published by the |
@@ -35,19 +35,6 @@ | |||
35 | 35 | ||
36 | #include "wm8580.h" | 36 | #include "wm8580.h" |
37 | 37 | ||
38 | #define WM8580_VERSION "0.1" | ||
39 | |||
40 | struct pll_state { | ||
41 | unsigned int in; | ||
42 | unsigned int out; | ||
43 | }; | ||
44 | |||
45 | /* codec private data */ | ||
46 | struct wm8580_priv { | ||
47 | struct pll_state a; | ||
48 | struct pll_state b; | ||
49 | }; | ||
50 | |||
51 | /* WM8580 register space */ | 38 | /* WM8580 register space */ |
52 | #define WM8580_PLLA1 0x00 | 39 | #define WM8580_PLLA1 0x00 |
53 | #define WM8580_PLLA2 0x01 | 40 | #define WM8580_PLLA2 0x01 |
@@ -102,6 +89,8 @@ struct wm8580_priv { | |||
102 | #define WM8580_READBACK 0x34 | 89 | #define WM8580_READBACK 0x34 |
103 | #define WM8580_RESET 0x35 | 90 | #define WM8580_RESET 0x35 |
104 | 91 | ||
92 | #define WM8580_MAX_REGISTER 0x35 | ||
93 | |||
105 | /* PLLB4 (register 7h) */ | 94 | /* PLLB4 (register 7h) */ |
106 | #define WM8580_PLLB4_MCLKOUTSRC_MASK 0x60 | 95 | #define WM8580_PLLB4_MCLKOUTSRC_MASK 0x60 |
107 | #define WM8580_PLLB4_MCLKOUTSRC_PLLA 0x20 | 96 | #define WM8580_PLLB4_MCLKOUTSRC_PLLA 0x20 |
@@ -193,6 +182,20 @@ static const u16 wm8580_reg[] = { | |||
193 | 0x0000, 0x0000 /*R53*/ | 182 | 0x0000, 0x0000 /*R53*/ |
194 | }; | 183 | }; |
195 | 184 | ||
185 | struct pll_state { | ||
186 | unsigned int in; | ||
187 | unsigned int out; | ||
188 | }; | ||
189 | |||
190 | /* codec private data */ | ||
191 | struct wm8580_priv { | ||
192 | struct snd_soc_codec codec; | ||
193 | u16 reg_cache[WM8580_MAX_REGISTER + 1]; | ||
194 | struct pll_state a; | ||
195 | struct pll_state b; | ||
196 | }; | ||
197 | |||
198 | |||
196 | /* | 199 | /* |
197 | * read wm8580 register cache | 200 | * read wm8580 register cache |
198 | */ | 201 | */ |
@@ -200,7 +203,7 @@ static inline unsigned int wm8580_read_reg_cache(struct snd_soc_codec *codec, | |||
200 | unsigned int reg) | 203 | unsigned int reg) |
201 | { | 204 | { |
202 | u16 *cache = codec->reg_cache; | 205 | u16 *cache = codec->reg_cache; |
203 | BUG_ON(reg > ARRAY_SIZE(wm8580_reg)); | 206 | BUG_ON(reg >= ARRAY_SIZE(wm8580_reg)); |
204 | return cache[reg]; | 207 | return cache[reg]; |
205 | } | 208 | } |
206 | 209 | ||
@@ -223,7 +226,7 @@ static int wm8580_write(struct snd_soc_codec *codec, unsigned int reg, | |||
223 | { | 226 | { |
224 | u8 data[2]; | 227 | u8 data[2]; |
225 | 228 | ||
226 | BUG_ON(reg > ARRAY_SIZE(wm8580_reg)); | 229 | BUG_ON(reg >= ARRAY_SIZE(wm8580_reg)); |
227 | 230 | ||
228 | /* Registers are 9 bits wide */ | 231 | /* Registers are 9 bits wide */ |
229 | value &= 0x1ff; | 232 | value &= 0x1ff; |
@@ -330,20 +333,6 @@ SOC_DOUBLE("ADC Mute Switch", WM8580_ADC_CONTROL1, 0, 1, 1, 0), | |||
330 | SOC_SINGLE("ADC High-Pass Filter Switch", WM8580_ADC_CONTROL1, 4, 1, 0), | 333 | SOC_SINGLE("ADC High-Pass Filter Switch", WM8580_ADC_CONTROL1, 4, 1, 0), |
331 | }; | 334 | }; |
332 | 335 | ||
333 | /* Add non-DAPM controls */ | ||
334 | static int wm8580_add_controls(struct snd_soc_codec *codec) | ||
335 | { | ||
336 | int err, i; | ||
337 | |||
338 | for (i = 0; i < ARRAY_SIZE(wm8580_snd_controls); i++) { | ||
339 | err = snd_ctl_add(codec->card, | ||
340 | snd_soc_cnew(&wm8580_snd_controls[i], | ||
341 | codec, NULL)); | ||
342 | if (err < 0) | ||
343 | return err; | ||
344 | } | ||
345 | return 0; | ||
346 | } | ||
347 | static const struct snd_soc_dapm_widget wm8580_dapm_widgets[] = { | 336 | static const struct snd_soc_dapm_widget wm8580_dapm_widgets[] = { |
348 | SND_SOC_DAPM_DAC("DAC1", "Playback", WM8580_PWRDN1, 2, 1), | 337 | SND_SOC_DAPM_DAC("DAC1", "Playback", WM8580_PWRDN1, 2, 1), |
349 | SND_SOC_DAPM_DAC("DAC2", "Playback", WM8580_PWRDN1, 3, 1), | 338 | SND_SOC_DAPM_DAC("DAC2", "Playback", WM8580_PWRDN1, 3, 1), |
@@ -553,7 +542,7 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream, | |||
553 | { | 542 | { |
554 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 543 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
555 | struct snd_soc_device *socdev = rtd->socdev; | 544 | struct snd_soc_device *socdev = rtd->socdev; |
556 | struct snd_soc_codec *codec = socdev->codec; | 545 | struct snd_soc_codec *codec = socdev->card->codec; |
557 | u16 paifb = wm8580_read(codec, WM8580_PAIF3 + dai->id); | 546 | u16 paifb = wm8580_read(codec, WM8580_PAIF3 + dai->id); |
558 | 547 | ||
559 | paifb &= ~WM8580_AIF_LENGTH_MASK; | 548 | paifb &= ~WM8580_AIF_LENGTH_MASK; |
@@ -771,8 +760,22 @@ static int wm8580_set_bias_level(struct snd_soc_codec *codec, | |||
771 | switch (level) { | 760 | switch (level) { |
772 | case SND_SOC_BIAS_ON: | 761 | case SND_SOC_BIAS_ON: |
773 | case SND_SOC_BIAS_PREPARE: | 762 | case SND_SOC_BIAS_PREPARE: |
763 | break; | ||
764 | |||
774 | case SND_SOC_BIAS_STANDBY: | 765 | case SND_SOC_BIAS_STANDBY: |
766 | if (codec->bias_level == SND_SOC_BIAS_OFF) { | ||
767 | /* Power up and get individual control of the DACs */ | ||
768 | reg = wm8580_read(codec, WM8580_PWRDN1); | ||
769 | reg &= ~(WM8580_PWRDN1_PWDN | WM8580_PWRDN1_ALLDACPD); | ||
770 | wm8580_write(codec, WM8580_PWRDN1, reg); | ||
771 | |||
772 | /* Make VMID high impedence */ | ||
773 | reg = wm8580_read(codec, WM8580_ADC_CONTROL1); | ||
774 | reg &= ~0x100; | ||
775 | wm8580_write(codec, WM8580_ADC_CONTROL1, reg); | ||
776 | } | ||
775 | break; | 777 | break; |
778 | |||
776 | case SND_SOC_BIAS_OFF: | 779 | case SND_SOC_BIAS_OFF: |
777 | reg = wm8580_read(codec, WM8580_PWRDN1); | 780 | reg = wm8580_read(codec, WM8580_PWRDN1); |
778 | wm8580_write(codec, WM8580_PWRDN1, reg | WM8580_PWRDN1_PWDN); | 781 | wm8580_write(codec, WM8580_PWRDN1, reg | WM8580_PWRDN1_PWDN); |
@@ -785,6 +788,21 @@ static int wm8580_set_bias_level(struct snd_soc_codec *codec, | |||
785 | #define WM8580_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | 788 | #define WM8580_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ |
786 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) | 789 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) |
787 | 790 | ||
791 | static struct snd_soc_dai_ops wm8580_dai_ops_playback = { | ||
792 | .hw_params = wm8580_paif_hw_params, | ||
793 | .set_fmt = wm8580_set_paif_dai_fmt, | ||
794 | .set_clkdiv = wm8580_set_dai_clkdiv, | ||
795 | .set_pll = wm8580_set_dai_pll, | ||
796 | .digital_mute = wm8580_digital_mute, | ||
797 | }; | ||
798 | |||
799 | static struct snd_soc_dai_ops wm8580_dai_ops_capture = { | ||
800 | .hw_params = wm8580_paif_hw_params, | ||
801 | .set_fmt = wm8580_set_paif_dai_fmt, | ||
802 | .set_clkdiv = wm8580_set_dai_clkdiv, | ||
803 | .set_pll = wm8580_set_dai_pll, | ||
804 | }; | ||
805 | |||
788 | struct snd_soc_dai wm8580_dai[] = { | 806 | struct snd_soc_dai wm8580_dai[] = { |
789 | { | 807 | { |
790 | .name = "WM8580 PAIFRX", | 808 | .name = "WM8580 PAIFRX", |
@@ -796,13 +814,7 @@ struct snd_soc_dai wm8580_dai[] = { | |||
796 | .rates = SNDRV_PCM_RATE_8000_192000, | 814 | .rates = SNDRV_PCM_RATE_8000_192000, |
797 | .formats = WM8580_FORMATS, | 815 | .formats = WM8580_FORMATS, |
798 | }, | 816 | }, |
799 | .ops = { | 817 | .ops = &wm8580_dai_ops_playback, |
800 | .hw_params = wm8580_paif_hw_params, | ||
801 | .set_fmt = wm8580_set_paif_dai_fmt, | ||
802 | .set_clkdiv = wm8580_set_dai_clkdiv, | ||
803 | .set_pll = wm8580_set_dai_pll, | ||
804 | .digital_mute = wm8580_digital_mute, | ||
805 | }, | ||
806 | }, | 818 | }, |
807 | { | 819 | { |
808 | .name = "WM8580 PAIFTX", | 820 | .name = "WM8580 PAIFTX", |
@@ -814,109 +826,168 @@ struct snd_soc_dai wm8580_dai[] = { | |||
814 | .rates = SNDRV_PCM_RATE_8000_192000, | 826 | .rates = SNDRV_PCM_RATE_8000_192000, |
815 | .formats = WM8580_FORMATS, | 827 | .formats = WM8580_FORMATS, |
816 | }, | 828 | }, |
817 | .ops = { | 829 | .ops = &wm8580_dai_ops_capture, |
818 | .hw_params = wm8580_paif_hw_params, | ||
819 | .set_fmt = wm8580_set_paif_dai_fmt, | ||
820 | .set_clkdiv = wm8580_set_dai_clkdiv, | ||
821 | .set_pll = wm8580_set_dai_pll, | ||
822 | }, | ||
823 | }, | 830 | }, |
824 | }; | 831 | }; |
825 | EXPORT_SYMBOL_GPL(wm8580_dai); | 832 | EXPORT_SYMBOL_GPL(wm8580_dai); |
826 | 833 | ||
827 | /* | 834 | static struct snd_soc_codec *wm8580_codec; |
828 | * initialise the WM8580 driver | 835 | |
829 | * register the mixer and dsp interfaces with the kernel | 836 | static int wm8580_probe(struct platform_device *pdev) |
830 | */ | ||
831 | static int wm8580_init(struct snd_soc_device *socdev) | ||
832 | { | 837 | { |
833 | struct snd_soc_codec *codec = socdev->codec; | 838 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
839 | struct snd_soc_codec *codec; | ||
834 | int ret = 0; | 840 | int ret = 0; |
835 | 841 | ||
836 | codec->name = "WM8580"; | 842 | if (wm8580_codec == NULL) { |
837 | codec->owner = THIS_MODULE; | 843 | dev_err(&pdev->dev, "Codec device not registered\n"); |
838 | codec->read = wm8580_read_reg_cache; | 844 | return -ENODEV; |
839 | codec->write = wm8580_write; | 845 | } |
840 | codec->set_bias_level = wm8580_set_bias_level; | ||
841 | codec->dai = wm8580_dai; | ||
842 | codec->num_dai = ARRAY_SIZE(wm8580_dai); | ||
843 | codec->reg_cache_size = ARRAY_SIZE(wm8580_reg); | ||
844 | codec->reg_cache = kmemdup(wm8580_reg, sizeof(wm8580_reg), | ||
845 | GFP_KERNEL); | ||
846 | |||
847 | if (codec->reg_cache == NULL) | ||
848 | return -ENOMEM; | ||
849 | |||
850 | /* Get the codec into a known state */ | ||
851 | wm8580_write(codec, WM8580_RESET, 0); | ||
852 | |||
853 | /* Power up and get individual control of the DACs */ | ||
854 | wm8580_write(codec, WM8580_PWRDN1, wm8580_read(codec, WM8580_PWRDN1) & | ||
855 | ~(WM8580_PWRDN1_PWDN | WM8580_PWRDN1_ALLDACPD)); | ||
856 | 846 | ||
857 | /* Make VMID high impedence */ | 847 | socdev->card->codec = wm8580_codec; |
858 | wm8580_write(codec, WM8580_ADC_CONTROL1, | 848 | codec = wm8580_codec; |
859 | wm8580_read(codec, WM8580_ADC_CONTROL1) & ~0x100); | ||
860 | 849 | ||
861 | /* register pcms */ | 850 | /* register pcms */ |
862 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, | 851 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); |
863 | SNDRV_DEFAULT_STR1); | ||
864 | if (ret < 0) { | 852 | if (ret < 0) { |
865 | printk(KERN_ERR "wm8580: failed to create pcms\n"); | 853 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); |
866 | goto pcm_err; | 854 | goto pcm_err; |
867 | } | 855 | } |
868 | 856 | ||
869 | wm8580_add_controls(codec); | 857 | snd_soc_add_controls(codec, wm8580_snd_controls, |
858 | ARRAY_SIZE(wm8580_snd_controls)); | ||
870 | wm8580_add_widgets(codec); | 859 | wm8580_add_widgets(codec); |
871 | |||
872 | ret = snd_soc_init_card(socdev); | 860 | ret = snd_soc_init_card(socdev); |
873 | if (ret < 0) { | 861 | if (ret < 0) { |
874 | printk(KERN_ERR "wm8580: failed to register card\n"); | 862 | dev_err(codec->dev, "failed to register card: %d\n", ret); |
875 | goto card_err; | 863 | goto card_err; |
876 | } | 864 | } |
865 | |||
877 | return ret; | 866 | return ret; |
878 | 867 | ||
879 | card_err: | 868 | card_err: |
880 | snd_soc_free_pcms(socdev); | 869 | snd_soc_free_pcms(socdev); |
881 | snd_soc_dapm_free(socdev); | 870 | snd_soc_dapm_free(socdev); |
882 | pcm_err: | 871 | pcm_err: |
883 | kfree(codec->reg_cache); | ||
884 | return ret; | 872 | return ret; |
885 | } | 873 | } |
886 | 874 | ||
887 | /* If the i2c layer weren't so broken, we could pass this kind of data | 875 | /* power down chip */ |
888 | around */ | 876 | static int wm8580_remove(struct platform_device *pdev) |
889 | static struct snd_soc_device *wm8580_socdev; | 877 | { |
878 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
879 | |||
880 | snd_soc_free_pcms(socdev); | ||
881 | snd_soc_dapm_free(socdev); | ||
890 | 882 | ||
891 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 883 | return 0; |
884 | } | ||
892 | 885 | ||
893 | /* | 886 | struct snd_soc_codec_device soc_codec_dev_wm8580 = { |
894 | * WM8580 2 wire address is determined by GPIO5 | 887 | .probe = wm8580_probe, |
895 | * state during powerup. | 888 | .remove = wm8580_remove, |
896 | * low = 0x1a | 889 | }; |
897 | * high = 0x1b | 890 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8580); |
898 | */ | 891 | |
892 | static int wm8580_register(struct wm8580_priv *wm8580) | ||
893 | { | ||
894 | int ret, i; | ||
895 | struct snd_soc_codec *codec = &wm8580->codec; | ||
896 | |||
897 | if (wm8580_codec) { | ||
898 | dev_err(codec->dev, "Another WM8580 is registered\n"); | ||
899 | ret = -EINVAL; | ||
900 | goto err; | ||
901 | } | ||
902 | |||
903 | mutex_init(&codec->mutex); | ||
904 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
905 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
899 | 906 | ||
907 | codec->private_data = wm8580; | ||
908 | codec->name = "WM8580"; | ||
909 | codec->owner = THIS_MODULE; | ||
910 | codec->read = wm8580_read_reg_cache; | ||
911 | codec->write = wm8580_write; | ||
912 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
913 | codec->set_bias_level = wm8580_set_bias_level; | ||
914 | codec->dai = wm8580_dai; | ||
915 | codec->num_dai = ARRAY_SIZE(wm8580_dai); | ||
916 | codec->reg_cache_size = ARRAY_SIZE(wm8580->reg_cache); | ||
917 | codec->reg_cache = &wm8580->reg_cache; | ||
918 | |||
919 | memcpy(codec->reg_cache, wm8580_reg, sizeof(wm8580_reg)); | ||
920 | |||
921 | /* Get the codec into a known state */ | ||
922 | ret = wm8580_write(codec, WM8580_RESET, 0); | ||
923 | if (ret != 0) { | ||
924 | dev_err(codec->dev, "Failed to reset codec: %d\n", ret); | ||
925 | goto err; | ||
926 | } | ||
927 | |||
928 | for (i = 0; i < ARRAY_SIZE(wm8580_dai); i++) | ||
929 | wm8580_dai[i].dev = codec->dev; | ||
930 | |||
931 | wm8580_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
932 | |||
933 | wm8580_codec = codec; | ||
934 | |||
935 | ret = snd_soc_register_codec(codec); | ||
936 | if (ret != 0) { | ||
937 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
938 | goto err; | ||
939 | } | ||
940 | |||
941 | ret = snd_soc_register_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai)); | ||
942 | if (ret != 0) { | ||
943 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
944 | goto err_codec; | ||
945 | } | ||
946 | |||
947 | return 0; | ||
948 | |||
949 | err_codec: | ||
950 | snd_soc_unregister_codec(codec); | ||
951 | err: | ||
952 | kfree(wm8580); | ||
953 | return ret; | ||
954 | } | ||
955 | |||
956 | static void wm8580_unregister(struct wm8580_priv *wm8580) | ||
957 | { | ||
958 | wm8580_set_bias_level(&wm8580->codec, SND_SOC_BIAS_OFF); | ||
959 | snd_soc_unregister_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai)); | ||
960 | snd_soc_unregister_codec(&wm8580->codec); | ||
961 | kfree(wm8580); | ||
962 | wm8580_codec = NULL; | ||
963 | } | ||
964 | |||
965 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
900 | static int wm8580_i2c_probe(struct i2c_client *i2c, | 966 | static int wm8580_i2c_probe(struct i2c_client *i2c, |
901 | const struct i2c_device_id *id) | 967 | const struct i2c_device_id *id) |
902 | { | 968 | { |
903 | struct snd_soc_device *socdev = wm8580_socdev; | 969 | struct wm8580_priv *wm8580; |
904 | struct snd_soc_codec *codec = socdev->codec; | 970 | struct snd_soc_codec *codec; |
905 | int ret; | ||
906 | 971 | ||
907 | i2c_set_clientdata(i2c, codec); | 972 | wm8580 = kzalloc(sizeof(struct wm8580_priv), GFP_KERNEL); |
973 | if (wm8580 == NULL) | ||
974 | return -ENOMEM; | ||
975 | |||
976 | codec = &wm8580->codec; | ||
977 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
978 | |||
979 | i2c_set_clientdata(i2c, wm8580); | ||
908 | codec->control_data = i2c; | 980 | codec->control_data = i2c; |
909 | 981 | ||
910 | ret = wm8580_init(socdev); | 982 | codec->dev = &i2c->dev; |
911 | if (ret < 0) | 983 | |
912 | dev_err(&i2c->dev, "failed to initialise WM8580\n"); | 984 | return wm8580_register(wm8580); |
913 | return ret; | ||
914 | } | 985 | } |
915 | 986 | ||
916 | static int wm8580_i2c_remove(struct i2c_client *client) | 987 | static int wm8580_i2c_remove(struct i2c_client *client) |
917 | { | 988 | { |
918 | struct snd_soc_codec *codec = i2c_get_clientdata(client); | 989 | struct wm8580_priv *wm8580 = i2c_get_clientdata(client); |
919 | kfree(codec->reg_cache); | 990 | wm8580_unregister(wm8580); |
920 | return 0; | 991 | return 0; |
921 | } | 992 | } |
922 | 993 | ||
@@ -928,129 +999,35 @@ MODULE_DEVICE_TABLE(i2c, wm8580_i2c_id); | |||
928 | 999 | ||
929 | static struct i2c_driver wm8580_i2c_driver = { | 1000 | static struct i2c_driver wm8580_i2c_driver = { |
930 | .driver = { | 1001 | .driver = { |
931 | .name = "WM8580 I2C Codec", | 1002 | .name = "wm8580", |
932 | .owner = THIS_MODULE, | 1003 | .owner = THIS_MODULE, |
933 | }, | 1004 | }, |
934 | .probe = wm8580_i2c_probe, | 1005 | .probe = wm8580_i2c_probe, |
935 | .remove = wm8580_i2c_remove, | 1006 | .remove = wm8580_i2c_remove, |
936 | .id_table = wm8580_i2c_id, | 1007 | .id_table = wm8580_i2c_id, |
937 | }; | 1008 | }; |
1009 | #endif | ||
938 | 1010 | ||
939 | static int wm8580_add_i2c_device(struct platform_device *pdev, | 1011 | static int __init wm8580_modinit(void) |
940 | const struct wm8580_setup_data *setup) | ||
941 | { | 1012 | { |
942 | struct i2c_board_info info; | ||
943 | struct i2c_adapter *adapter; | ||
944 | struct i2c_client *client; | ||
945 | int ret; | 1013 | int ret; |
946 | 1014 | ||
1015 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
947 | ret = i2c_add_driver(&wm8580_i2c_driver); | 1016 | ret = i2c_add_driver(&wm8580_i2c_driver); |
948 | if (ret != 0) { | 1017 | if (ret != 0) { |
949 | dev_err(&pdev->dev, "can't add i2c driver\n"); | 1018 | pr_err("Failed to register WM8580 I2C driver: %d\n", ret); |
950 | return ret; | ||
951 | } | ||
952 | |||
953 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
954 | info.addr = setup->i2c_address; | ||
955 | strlcpy(info.type, "wm8580", I2C_NAME_SIZE); | ||
956 | |||
957 | adapter = i2c_get_adapter(setup->i2c_bus); | ||
958 | if (!adapter) { | ||
959 | dev_err(&pdev->dev, "can't get i2c adapter %d\n", | ||
960 | setup->i2c_bus); | ||
961 | goto err_driver; | ||
962 | } | ||
963 | |||
964 | client = i2c_new_device(adapter, &info); | ||
965 | i2c_put_adapter(adapter); | ||
966 | if (!client) { | ||
967 | dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", | ||
968 | (unsigned int)info.addr); | ||
969 | goto err_driver; | ||
970 | } | 1019 | } |
971 | |||
972 | return 0; | ||
973 | |||
974 | err_driver: | ||
975 | i2c_del_driver(&wm8580_i2c_driver); | ||
976 | return -ENODEV; | ||
977 | } | ||
978 | #endif | 1020 | #endif |
979 | 1021 | ||
980 | static int wm8580_probe(struct platform_device *pdev) | ||
981 | { | ||
982 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
983 | struct wm8580_setup_data *setup; | ||
984 | struct snd_soc_codec *codec; | ||
985 | struct wm8580_priv *wm8580; | ||
986 | int ret = 0; | ||
987 | |||
988 | pr_info("WM8580 Audio Codec %s\n", WM8580_VERSION); | ||
989 | |||
990 | setup = socdev->codec_data; | ||
991 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
992 | if (codec == NULL) | ||
993 | return -ENOMEM; | ||
994 | |||
995 | wm8580 = kzalloc(sizeof(struct wm8580_priv), GFP_KERNEL); | ||
996 | if (wm8580 == NULL) { | ||
997 | kfree(codec); | ||
998 | return -ENOMEM; | ||
999 | } | ||
1000 | |||
1001 | codec->private_data = wm8580; | ||
1002 | socdev->codec = codec; | ||
1003 | mutex_init(&codec->mutex); | ||
1004 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1005 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1006 | wm8580_socdev = socdev; | ||
1007 | |||
1008 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1009 | if (setup->i2c_address) { | ||
1010 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
1011 | ret = wm8580_add_i2c_device(pdev, setup); | ||
1012 | } | ||
1013 | #else | ||
1014 | /* Add other interfaces here */ | ||
1015 | #endif | ||
1016 | return ret; | ||
1017 | } | ||
1018 | |||
1019 | /* power down chip */ | ||
1020 | static int wm8580_remove(struct platform_device *pdev) | ||
1021 | { | ||
1022 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1023 | struct snd_soc_codec *codec = socdev->codec; | ||
1024 | |||
1025 | if (codec->control_data) | ||
1026 | wm8580_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1027 | snd_soc_free_pcms(socdev); | ||
1028 | snd_soc_dapm_free(socdev); | ||
1029 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1030 | i2c_unregister_device(codec->control_data); | ||
1031 | i2c_del_driver(&wm8580_i2c_driver); | ||
1032 | #endif | ||
1033 | kfree(codec->private_data); | ||
1034 | kfree(codec); | ||
1035 | |||
1036 | return 0; | 1022 | return 0; |
1037 | } | 1023 | } |
1038 | |||
1039 | struct snd_soc_codec_device soc_codec_dev_wm8580 = { | ||
1040 | .probe = wm8580_probe, | ||
1041 | .remove = wm8580_remove, | ||
1042 | }; | ||
1043 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8580); | ||
1044 | |||
1045 | static int __init wm8580_modinit(void) | ||
1046 | { | ||
1047 | return snd_soc_register_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai)); | ||
1048 | } | ||
1049 | module_init(wm8580_modinit); | 1024 | module_init(wm8580_modinit); |
1050 | 1025 | ||
1051 | static void __exit wm8580_exit(void) | 1026 | static void __exit wm8580_exit(void) |
1052 | { | 1027 | { |
1053 | snd_soc_unregister_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai)); | 1028 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
1029 | i2c_del_driver(&wm8580_i2c_driver); | ||
1030 | #endif | ||
1054 | } | 1031 | } |
1055 | module_exit(wm8580_exit); | 1032 | module_exit(wm8580_exit); |
1056 | 1033 | ||
diff --git a/sound/soc/codecs/wm8580.h b/sound/soc/codecs/wm8580.h index 09e4422f6f2f..0dfb5ddde6a2 100644 --- a/sound/soc/codecs/wm8580.h +++ b/sound/soc/codecs/wm8580.h | |||
@@ -28,11 +28,6 @@ | |||
28 | #define WM8580_CLKSRC_OSC 4 | 28 | #define WM8580_CLKSRC_OSC 4 |
29 | #define WM8580_CLKSRC_NONE 5 | 29 | #define WM8580_CLKSRC_NONE 5 |
30 | 30 | ||
31 | struct wm8580_setup_data { | ||
32 | int i2c_bus; | ||
33 | unsigned short i2c_address; | ||
34 | }; | ||
35 | |||
36 | #define WM8580_DAI_PAIFRX 0 | 31 | #define WM8580_DAI_PAIFRX 0 |
37 | #define WM8580_DAI_PAIFTX 1 | 32 | #define WM8580_DAI_PAIFTX 1 |
38 | 33 | ||
diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c index 80b11983e137..e7ff2121ede9 100644 --- a/sound/soc/codecs/wm8728.c +++ b/sound/soc/codecs/wm8728.c | |||
@@ -47,7 +47,7 @@ static inline unsigned int wm8728_read_reg_cache(struct snd_soc_codec *codec, | |||
47 | unsigned int reg) | 47 | unsigned int reg) |
48 | { | 48 | { |
49 | u16 *cache = codec->reg_cache; | 49 | u16 *cache = codec->reg_cache; |
50 | BUG_ON(reg > ARRAY_SIZE(wm8728_reg_defaults)); | 50 | BUG_ON(reg >= ARRAY_SIZE(wm8728_reg_defaults)); |
51 | return cache[reg]; | 51 | return cache[reg]; |
52 | } | 52 | } |
53 | 53 | ||
@@ -55,7 +55,7 @@ static inline void wm8728_write_reg_cache(struct snd_soc_codec *codec, | |||
55 | u16 reg, unsigned int value) | 55 | u16 reg, unsigned int value) |
56 | { | 56 | { |
57 | u16 *cache = codec->reg_cache; | 57 | u16 *cache = codec->reg_cache; |
58 | BUG_ON(reg > ARRAY_SIZE(wm8728_reg_defaults)); | 58 | BUG_ON(reg >= ARRAY_SIZE(wm8728_reg_defaults)); |
59 | cache[reg] = value; | 59 | cache[reg] = value; |
60 | } | 60 | } |
61 | 61 | ||
@@ -92,21 +92,6 @@ SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8728_DACLVOL, WM8728_DACRVOL, | |||
92 | SOC_SINGLE("Deemphasis", WM8728_DACCTL, 1, 1, 0), | 92 | SOC_SINGLE("Deemphasis", WM8728_DACCTL, 1, 1, 0), |
93 | }; | 93 | }; |
94 | 94 | ||
95 | static int wm8728_add_controls(struct snd_soc_codec *codec) | ||
96 | { | ||
97 | int err, i; | ||
98 | |||
99 | for (i = 0; i < ARRAY_SIZE(wm8728_snd_controls); i++) { | ||
100 | err = snd_ctl_add(codec->card, | ||
101 | snd_soc_cnew(&wm8728_snd_controls[i], | ||
102 | codec, NULL)); | ||
103 | if (err < 0) | ||
104 | return err; | ||
105 | } | ||
106 | |||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | /* | 95 | /* |
111 | * DAPM controls. | 96 | * DAPM controls. |
112 | */ | 97 | */ |
@@ -152,7 +137,7 @@ static int wm8728_hw_params(struct snd_pcm_substream *substream, | |||
152 | { | 137 | { |
153 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 138 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
154 | struct snd_soc_device *socdev = rtd->socdev; | 139 | struct snd_soc_device *socdev = rtd->socdev; |
155 | struct snd_soc_codec *codec = socdev->codec; | 140 | struct snd_soc_codec *codec = socdev->card->codec; |
156 | u16 dac = wm8728_read_reg_cache(codec, WM8728_DACCTL); | 141 | u16 dac = wm8728_read_reg_cache(codec, WM8728_DACCTL); |
157 | 142 | ||
158 | dac &= ~0x18; | 143 | dac &= ~0x18; |
@@ -259,6 +244,12 @@ static int wm8728_set_bias_level(struct snd_soc_codec *codec, | |||
259 | #define WM8728_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | 244 | #define WM8728_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ |
260 | SNDRV_PCM_FMTBIT_S24_LE) | 245 | SNDRV_PCM_FMTBIT_S24_LE) |
261 | 246 | ||
247 | static struct snd_soc_dai_ops wm8728_dai_ops = { | ||
248 | .hw_params = wm8728_hw_params, | ||
249 | .digital_mute = wm8728_mute, | ||
250 | .set_fmt = wm8728_set_dai_fmt, | ||
251 | }; | ||
252 | |||
262 | struct snd_soc_dai wm8728_dai = { | 253 | struct snd_soc_dai wm8728_dai = { |
263 | .name = "WM8728", | 254 | .name = "WM8728", |
264 | .playback = { | 255 | .playback = { |
@@ -268,18 +259,14 @@ struct snd_soc_dai wm8728_dai = { | |||
268 | .rates = WM8728_RATES, | 259 | .rates = WM8728_RATES, |
269 | .formats = WM8728_FORMATS, | 260 | .formats = WM8728_FORMATS, |
270 | }, | 261 | }, |
271 | .ops = { | 262 | .ops = &wm8728_dai_ops, |
272 | .hw_params = wm8728_hw_params, | ||
273 | .digital_mute = wm8728_mute, | ||
274 | .set_fmt = wm8728_set_dai_fmt, | ||
275 | } | ||
276 | }; | 263 | }; |
277 | EXPORT_SYMBOL_GPL(wm8728_dai); | 264 | EXPORT_SYMBOL_GPL(wm8728_dai); |
278 | 265 | ||
279 | static int wm8728_suspend(struct platform_device *pdev, pm_message_t state) | 266 | static int wm8728_suspend(struct platform_device *pdev, pm_message_t state) |
280 | { | 267 | { |
281 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 268 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
282 | struct snd_soc_codec *codec = socdev->codec; | 269 | struct snd_soc_codec *codec = socdev->card->codec; |
283 | 270 | ||
284 | wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF); | 271 | wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF); |
285 | 272 | ||
@@ -289,7 +276,7 @@ static int wm8728_suspend(struct platform_device *pdev, pm_message_t state) | |||
289 | static int wm8728_resume(struct platform_device *pdev) | 276 | static int wm8728_resume(struct platform_device *pdev) |
290 | { | 277 | { |
291 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 278 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
292 | struct snd_soc_codec *codec = socdev->codec; | 279 | struct snd_soc_codec *codec = socdev->card->codec; |
293 | 280 | ||
294 | wm8728_set_bias_level(codec, codec->suspend_bias_level); | 281 | wm8728_set_bias_level(codec, codec->suspend_bias_level); |
295 | 282 | ||
@@ -302,7 +289,7 @@ static int wm8728_resume(struct platform_device *pdev) | |||
302 | */ | 289 | */ |
303 | static int wm8728_init(struct snd_soc_device *socdev) | 290 | static int wm8728_init(struct snd_soc_device *socdev) |
304 | { | 291 | { |
305 | struct snd_soc_codec *codec = socdev->codec; | 292 | struct snd_soc_codec *codec = socdev->card->codec; |
306 | int ret = 0; | 293 | int ret = 0; |
307 | 294 | ||
308 | codec->name = "WM8728"; | 295 | codec->name = "WM8728"; |
@@ -330,7 +317,8 @@ static int wm8728_init(struct snd_soc_device *socdev) | |||
330 | /* power on device */ | 317 | /* power on device */ |
331 | wm8728_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 318 | wm8728_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
332 | 319 | ||
333 | wm8728_add_controls(codec); | 320 | snd_soc_add_controls(codec, wm8728_snd_controls, |
321 | ARRAY_SIZE(wm8728_snd_controls)); | ||
334 | wm8728_add_widgets(codec); | 322 | wm8728_add_widgets(codec); |
335 | ret = snd_soc_init_card(socdev); | 323 | ret = snd_soc_init_card(socdev); |
336 | if (ret < 0) { | 324 | if (ret < 0) { |
@@ -363,7 +351,7 @@ static int wm8728_i2c_probe(struct i2c_client *i2c, | |||
363 | const struct i2c_device_id *id) | 351 | const struct i2c_device_id *id) |
364 | { | 352 | { |
365 | struct snd_soc_device *socdev = wm8728_socdev; | 353 | struct snd_soc_device *socdev = wm8728_socdev; |
366 | struct snd_soc_codec *codec = socdev->codec; | 354 | struct snd_soc_codec *codec = socdev->card->codec; |
367 | int ret; | 355 | int ret; |
368 | 356 | ||
369 | i2c_set_clientdata(i2c, codec); | 357 | i2c_set_clientdata(i2c, codec); |
@@ -444,7 +432,7 @@ err_driver: | |||
444 | static int __devinit wm8728_spi_probe(struct spi_device *spi) | 432 | static int __devinit wm8728_spi_probe(struct spi_device *spi) |
445 | { | 433 | { |
446 | struct snd_soc_device *socdev = wm8728_socdev; | 434 | struct snd_soc_device *socdev = wm8728_socdev; |
447 | struct snd_soc_codec *codec = socdev->codec; | 435 | struct snd_soc_codec *codec = socdev->card->codec; |
448 | int ret; | 436 | int ret; |
449 | 437 | ||
450 | codec->control_data = spi; | 438 | codec->control_data = spi; |
@@ -508,7 +496,7 @@ static int wm8728_probe(struct platform_device *pdev) | |||
508 | if (codec == NULL) | 496 | if (codec == NULL) |
509 | return -ENOMEM; | 497 | return -ENOMEM; |
510 | 498 | ||
511 | socdev->codec = codec; | 499 | socdev->card->codec = codec; |
512 | mutex_init(&codec->mutex); | 500 | mutex_init(&codec->mutex); |
513 | INIT_LIST_HEAD(&codec->dapm_widgets); | 501 | INIT_LIST_HEAD(&codec->dapm_widgets); |
514 | INIT_LIST_HEAD(&codec->dapm_paths); | 502 | INIT_LIST_HEAD(&codec->dapm_paths); |
@@ -541,7 +529,7 @@ static int wm8728_probe(struct platform_device *pdev) | |||
541 | static int wm8728_remove(struct platform_device *pdev) | 529 | static int wm8728_remove(struct platform_device *pdev) |
542 | { | 530 | { |
543 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 531 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
544 | struct snd_soc_codec *codec = socdev->codec; | 532 | struct snd_soc_codec *codec = socdev->card->codec; |
545 | 533 | ||
546 | if (codec->control_data) | 534 | if (codec->control_data) |
547 | wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF); | 535 | wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF); |
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index c444b9f2701e..e043e3f60008 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c | |||
@@ -29,15 +29,20 @@ | |||
29 | 29 | ||
30 | #include "wm8731.h" | 30 | #include "wm8731.h" |
31 | 31 | ||
32 | #define WM8731_VERSION "0.13" | 32 | static struct snd_soc_codec *wm8731_codec; |
33 | |||
34 | struct snd_soc_codec_device soc_codec_dev_wm8731; | 33 | struct snd_soc_codec_device soc_codec_dev_wm8731; |
35 | 34 | ||
36 | /* codec private data */ | 35 | /* codec private data */ |
37 | struct wm8731_priv { | 36 | struct wm8731_priv { |
37 | struct snd_soc_codec codec; | ||
38 | u16 reg_cache[WM8731_CACHEREGNUM]; | ||
38 | unsigned int sysclk; | 39 | unsigned int sysclk; |
39 | }; | 40 | }; |
40 | 41 | ||
42 | #ifdef CONFIG_SPI_MASTER | ||
43 | static int wm8731_spi_write(struct spi_device *spi, const char *data, int len); | ||
44 | #endif | ||
45 | |||
41 | /* | 46 | /* |
42 | * wm8731 register cache | 47 | * wm8731 register cache |
43 | * We can't read the WM8731 register space when we are | 48 | * We can't read the WM8731 register space when we are |
@@ -129,22 +134,6 @@ SOC_SINGLE("Store DC Offset Switch", WM8731_APDIGI, 4, 1, 0), | |||
129 | SOC_ENUM("Playback De-emphasis", wm8731_enum[1]), | 134 | SOC_ENUM("Playback De-emphasis", wm8731_enum[1]), |
130 | }; | 135 | }; |
131 | 136 | ||
132 | /* add non dapm controls */ | ||
133 | static int wm8731_add_controls(struct snd_soc_codec *codec) | ||
134 | { | ||
135 | int err, i; | ||
136 | |||
137 | for (i = 0; i < ARRAY_SIZE(wm8731_snd_controls); i++) { | ||
138 | err = snd_ctl_add(codec->card, | ||
139 | snd_soc_cnew(&wm8731_snd_controls[i], | ||
140 | codec, NULL)); | ||
141 | if (err < 0) | ||
142 | return err; | ||
143 | } | ||
144 | |||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | /* Output Mixer */ | 137 | /* Output Mixer */ |
149 | static const struct snd_kcontrol_new wm8731_output_mixer_controls[] = { | 138 | static const struct snd_kcontrol_new wm8731_output_mixer_controls[] = { |
150 | SOC_DAPM_SINGLE("Line Bypass Switch", WM8731_APANA, 3, 1, 0), | 139 | SOC_DAPM_SINGLE("Line Bypass Switch", WM8731_APANA, 3, 1, 0), |
@@ -269,7 +258,7 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream, | |||
269 | { | 258 | { |
270 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 259 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
271 | struct snd_soc_device *socdev = rtd->socdev; | 260 | struct snd_soc_device *socdev = rtd->socdev; |
272 | struct snd_soc_codec *codec = socdev->codec; | 261 | struct snd_soc_codec *codec = socdev->card->codec; |
273 | struct wm8731_priv *wm8731 = codec->private_data; | 262 | struct wm8731_priv *wm8731 = codec->private_data; |
274 | u16 iface = wm8731_read_reg_cache(codec, WM8731_IFACE) & 0xfff3; | 263 | u16 iface = wm8731_read_reg_cache(codec, WM8731_IFACE) & 0xfff3; |
275 | int i = get_coeff(wm8731->sysclk, params_rate(params)); | 264 | int i = get_coeff(wm8731->sysclk, params_rate(params)); |
@@ -299,7 +288,7 @@ static int wm8731_pcm_prepare(struct snd_pcm_substream *substream, | |||
299 | { | 288 | { |
300 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 289 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
301 | struct snd_soc_device *socdev = rtd->socdev; | 290 | struct snd_soc_device *socdev = rtd->socdev; |
302 | struct snd_soc_codec *codec = socdev->codec; | 291 | struct snd_soc_codec *codec = socdev->card->codec; |
303 | 292 | ||
304 | /* set active */ | 293 | /* set active */ |
305 | wm8731_write(codec, WM8731_ACTIVE, 0x0001); | 294 | wm8731_write(codec, WM8731_ACTIVE, 0x0001); |
@@ -312,7 +301,7 @@ static void wm8731_shutdown(struct snd_pcm_substream *substream, | |||
312 | { | 301 | { |
313 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 302 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
314 | struct snd_soc_device *socdev = rtd->socdev; | 303 | struct snd_soc_device *socdev = rtd->socdev; |
315 | struct snd_soc_codec *codec = socdev->codec; | 304 | struct snd_soc_codec *codec = socdev->card->codec; |
316 | 305 | ||
317 | /* deactivate */ | 306 | /* deactivate */ |
318 | if (!codec->active) { | 307 | if (!codec->active) { |
@@ -414,21 +403,19 @@ static int wm8731_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
414 | static int wm8731_set_bias_level(struct snd_soc_codec *codec, | 403 | static int wm8731_set_bias_level(struct snd_soc_codec *codec, |
415 | enum snd_soc_bias_level level) | 404 | enum snd_soc_bias_level level) |
416 | { | 405 | { |
417 | u16 reg = wm8731_read_reg_cache(codec, WM8731_PWR) & 0xff7f; | 406 | u16 reg; |
418 | 407 | ||
419 | switch (level) { | 408 | switch (level) { |
420 | case SND_SOC_BIAS_ON: | 409 | case SND_SOC_BIAS_ON: |
421 | /* vref/mid, osc on, dac unmute */ | ||
422 | wm8731_write(codec, WM8731_PWR, reg); | ||
423 | break; | 410 | break; |
424 | case SND_SOC_BIAS_PREPARE: | 411 | case SND_SOC_BIAS_PREPARE: |
425 | break; | 412 | break; |
426 | case SND_SOC_BIAS_STANDBY: | 413 | case SND_SOC_BIAS_STANDBY: |
427 | /* everything off except vref/vmid, */ | 414 | /* Clear PWROFF, gate CLKOUT, everything else as-is */ |
415 | reg = wm8731_read_reg_cache(codec, WM8731_PWR) & 0xff7f; | ||
428 | wm8731_write(codec, WM8731_PWR, reg | 0x0040); | 416 | wm8731_write(codec, WM8731_PWR, reg | 0x0040); |
429 | break; | 417 | break; |
430 | case SND_SOC_BIAS_OFF: | 418 | case SND_SOC_BIAS_OFF: |
431 | /* everything off, dac mute, inactive */ | ||
432 | wm8731_write(codec, WM8731_ACTIVE, 0x0); | 419 | wm8731_write(codec, WM8731_ACTIVE, 0x0); |
433 | wm8731_write(codec, WM8731_PWR, 0xffff); | 420 | wm8731_write(codec, WM8731_PWR, 0xffff); |
434 | break; | 421 | break; |
@@ -446,6 +433,15 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec, | |||
446 | #define WM8731_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | 433 | #define WM8731_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ |
447 | SNDRV_PCM_FMTBIT_S24_LE) | 434 | SNDRV_PCM_FMTBIT_S24_LE) |
448 | 435 | ||
436 | static struct snd_soc_dai_ops wm8731_dai_ops = { | ||
437 | .prepare = wm8731_pcm_prepare, | ||
438 | .hw_params = wm8731_hw_params, | ||
439 | .shutdown = wm8731_shutdown, | ||
440 | .digital_mute = wm8731_mute, | ||
441 | .set_sysclk = wm8731_set_dai_sysclk, | ||
442 | .set_fmt = wm8731_set_dai_fmt, | ||
443 | }; | ||
444 | |||
449 | struct snd_soc_dai wm8731_dai = { | 445 | struct snd_soc_dai wm8731_dai = { |
450 | .name = "WM8731", | 446 | .name = "WM8731", |
451 | .playback = { | 447 | .playback = { |
@@ -460,21 +456,14 @@ struct snd_soc_dai wm8731_dai = { | |||
460 | .channels_max = 2, | 456 | .channels_max = 2, |
461 | .rates = WM8731_RATES, | 457 | .rates = WM8731_RATES, |
462 | .formats = WM8731_FORMATS,}, | 458 | .formats = WM8731_FORMATS,}, |
463 | .ops = { | 459 | .ops = &wm8731_dai_ops, |
464 | .prepare = wm8731_pcm_prepare, | ||
465 | .hw_params = wm8731_hw_params, | ||
466 | .shutdown = wm8731_shutdown, | ||
467 | .digital_mute = wm8731_mute, | ||
468 | .set_sysclk = wm8731_set_dai_sysclk, | ||
469 | .set_fmt = wm8731_set_dai_fmt, | ||
470 | } | ||
471 | }; | 460 | }; |
472 | EXPORT_SYMBOL_GPL(wm8731_dai); | 461 | EXPORT_SYMBOL_GPL(wm8731_dai); |
473 | 462 | ||
474 | static int wm8731_suspend(struct platform_device *pdev, pm_message_t state) | 463 | static int wm8731_suspend(struct platform_device *pdev, pm_message_t state) |
475 | { | 464 | { |
476 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 465 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
477 | struct snd_soc_codec *codec = socdev->codec; | 466 | struct snd_soc_codec *codec = socdev->card->codec; |
478 | 467 | ||
479 | wm8731_write(codec, WM8731_ACTIVE, 0x0); | 468 | wm8731_write(codec, WM8731_ACTIVE, 0x0); |
480 | wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); | 469 | wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); |
@@ -484,7 +473,7 @@ static int wm8731_suspend(struct platform_device *pdev, pm_message_t state) | |||
484 | static int wm8731_resume(struct platform_device *pdev) | 473 | static int wm8731_resume(struct platform_device *pdev) |
485 | { | 474 | { |
486 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 475 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
487 | struct snd_soc_codec *codec = socdev->codec; | 476 | struct snd_soc_codec *codec = socdev->card->codec; |
488 | int i; | 477 | int i; |
489 | u8 data[2]; | 478 | u8 data[2]; |
490 | u16 *cache = codec->reg_cache; | 479 | u16 *cache = codec->reg_cache; |
@@ -500,54 +489,33 @@ static int wm8731_resume(struct platform_device *pdev) | |||
500 | return 0; | 489 | return 0; |
501 | } | 490 | } |
502 | 491 | ||
503 | /* | 492 | static int wm8731_probe(struct platform_device *pdev) |
504 | * initialise the WM8731 driver | ||
505 | * register the mixer and dsp interfaces with the kernel | ||
506 | */ | ||
507 | static int wm8731_init(struct snd_soc_device *socdev) | ||
508 | { | 493 | { |
509 | struct snd_soc_codec *codec = socdev->codec; | 494 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
510 | int reg, ret = 0; | 495 | struct snd_soc_codec *codec; |
496 | int ret = 0; | ||
511 | 497 | ||
512 | codec->name = "WM8731"; | 498 | if (wm8731_codec == NULL) { |
513 | codec->owner = THIS_MODULE; | 499 | dev_err(&pdev->dev, "Codec device not registered\n"); |
514 | codec->read = wm8731_read_reg_cache; | 500 | return -ENODEV; |
515 | codec->write = wm8731_write; | 501 | } |
516 | codec->set_bias_level = wm8731_set_bias_level; | ||
517 | codec->dai = &wm8731_dai; | ||
518 | codec->num_dai = 1; | ||
519 | codec->reg_cache_size = ARRAY_SIZE(wm8731_reg); | ||
520 | codec->reg_cache = kmemdup(wm8731_reg, sizeof(wm8731_reg), GFP_KERNEL); | ||
521 | if (codec->reg_cache == NULL) | ||
522 | return -ENOMEM; | ||
523 | 502 | ||
524 | wm8731_reset(codec); | 503 | socdev->card->codec = wm8731_codec; |
504 | codec = wm8731_codec; | ||
525 | 505 | ||
526 | /* register pcms */ | 506 | /* register pcms */ |
527 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | 507 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); |
528 | if (ret < 0) { | 508 | if (ret < 0) { |
529 | printk(KERN_ERR "wm8731: failed to create pcms\n"); | 509 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); |
530 | goto pcm_err; | 510 | goto pcm_err; |
531 | } | 511 | } |
532 | 512 | ||
533 | /* power on device */ | 513 | snd_soc_add_controls(codec, wm8731_snd_controls, |
534 | wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 514 | ARRAY_SIZE(wm8731_snd_controls)); |
535 | |||
536 | /* set the update bits */ | ||
537 | reg = wm8731_read_reg_cache(codec, WM8731_LOUT1V); | ||
538 | wm8731_write(codec, WM8731_LOUT1V, reg & ~0x0100); | ||
539 | reg = wm8731_read_reg_cache(codec, WM8731_ROUT1V); | ||
540 | wm8731_write(codec, WM8731_ROUT1V, reg & ~0x0100); | ||
541 | reg = wm8731_read_reg_cache(codec, WM8731_LINVOL); | ||
542 | wm8731_write(codec, WM8731_LINVOL, reg & ~0x0100); | ||
543 | reg = wm8731_read_reg_cache(codec, WM8731_RINVOL); | ||
544 | wm8731_write(codec, WM8731_RINVOL, reg & ~0x0100); | ||
545 | |||
546 | wm8731_add_controls(codec); | ||
547 | wm8731_add_widgets(codec); | 515 | wm8731_add_widgets(codec); |
548 | ret = snd_soc_init_card(socdev); | 516 | ret = snd_soc_init_card(socdev); |
549 | if (ret < 0) { | 517 | if (ret < 0) { |
550 | printk(KERN_ERR "wm8731: failed to register card\n"); | 518 | dev_err(codec->dev, "failed to register card: %d\n", ret); |
551 | goto card_err; | 519 | goto card_err; |
552 | } | 520 | } |
553 | 521 | ||
@@ -557,133 +525,109 @@ card_err: | |||
557 | snd_soc_free_pcms(socdev); | 525 | snd_soc_free_pcms(socdev); |
558 | snd_soc_dapm_free(socdev); | 526 | snd_soc_dapm_free(socdev); |
559 | pcm_err: | 527 | pcm_err: |
560 | kfree(codec->reg_cache); | ||
561 | return ret; | 528 | return ret; |
562 | } | 529 | } |
563 | 530 | ||
564 | static struct snd_soc_device *wm8731_socdev; | 531 | /* power down chip */ |
565 | 532 | static int wm8731_remove(struct platform_device *pdev) | |
566 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
567 | |||
568 | /* | ||
569 | * WM8731 2 wire address is determined by GPIO5 | ||
570 | * state during powerup. | ||
571 | * low = 0x1a | ||
572 | * high = 0x1b | ||
573 | */ | ||
574 | |||
575 | static int wm8731_i2c_probe(struct i2c_client *i2c, | ||
576 | const struct i2c_device_id *id) | ||
577 | { | 533 | { |
578 | struct snd_soc_device *socdev = wm8731_socdev; | 534 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
579 | struct snd_soc_codec *codec = socdev->codec; | ||
580 | int ret; | ||
581 | |||
582 | i2c_set_clientdata(i2c, codec); | ||
583 | codec->control_data = i2c; | ||
584 | |||
585 | ret = wm8731_init(socdev); | ||
586 | if (ret < 0) | ||
587 | pr_err("failed to initialise WM8731\n"); | ||
588 | 535 | ||
589 | return ret; | 536 | snd_soc_free_pcms(socdev); |
590 | } | 537 | snd_soc_dapm_free(socdev); |
591 | 538 | ||
592 | static int wm8731_i2c_remove(struct i2c_client *client) | ||
593 | { | ||
594 | struct snd_soc_codec *codec = i2c_get_clientdata(client); | ||
595 | kfree(codec->reg_cache); | ||
596 | return 0; | 539 | return 0; |
597 | } | 540 | } |
598 | 541 | ||
599 | static const struct i2c_device_id wm8731_i2c_id[] = { | 542 | struct snd_soc_codec_device soc_codec_dev_wm8731 = { |
600 | { "wm8731", 0 }, | 543 | .probe = wm8731_probe, |
601 | { } | 544 | .remove = wm8731_remove, |
602 | }; | 545 | .suspend = wm8731_suspend, |
603 | MODULE_DEVICE_TABLE(i2c, wm8731_i2c_id); | 546 | .resume = wm8731_resume, |
604 | |||
605 | static struct i2c_driver wm8731_i2c_driver = { | ||
606 | .driver = { | ||
607 | .name = "WM8731 I2C Codec", | ||
608 | .owner = THIS_MODULE, | ||
609 | }, | ||
610 | .probe = wm8731_i2c_probe, | ||
611 | .remove = wm8731_i2c_remove, | ||
612 | .id_table = wm8731_i2c_id, | ||
613 | }; | 547 | }; |
548 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731); | ||
614 | 549 | ||
615 | static int wm8731_add_i2c_device(struct platform_device *pdev, | 550 | static int wm8731_register(struct wm8731_priv *wm8731) |
616 | const struct wm8731_setup_data *setup) | ||
617 | { | 551 | { |
618 | struct i2c_board_info info; | ||
619 | struct i2c_adapter *adapter; | ||
620 | struct i2c_client *client; | ||
621 | int ret; | 552 | int ret; |
553 | struct snd_soc_codec *codec = &wm8731->codec; | ||
554 | u16 reg; | ||
622 | 555 | ||
623 | ret = i2c_add_driver(&wm8731_i2c_driver); | 556 | if (wm8731_codec) { |
624 | if (ret != 0) { | 557 | dev_err(codec->dev, "Another WM8731 is registered\n"); |
625 | dev_err(&pdev->dev, "can't add i2c driver\n"); | 558 | return -EINVAL; |
626 | return ret; | ||
627 | } | 559 | } |
628 | 560 | ||
629 | memset(&info, 0, sizeof(struct i2c_board_info)); | 561 | mutex_init(&codec->mutex); |
630 | info.addr = setup->i2c_address; | 562 | INIT_LIST_HEAD(&codec->dapm_widgets); |
631 | strlcpy(info.type, "wm8731", I2C_NAME_SIZE); | 563 | INIT_LIST_HEAD(&codec->dapm_paths); |
632 | 564 | ||
633 | adapter = i2c_get_adapter(setup->i2c_bus); | 565 | codec->private_data = wm8731; |
634 | if (!adapter) { | 566 | codec->name = "WM8731"; |
635 | dev_err(&pdev->dev, "can't get i2c adapter %d\n", | 567 | codec->owner = THIS_MODULE; |
636 | setup->i2c_bus); | 568 | codec->read = wm8731_read_reg_cache; |
637 | goto err_driver; | 569 | codec->write = wm8731_write; |
638 | } | 570 | codec->bias_level = SND_SOC_BIAS_OFF; |
571 | codec->set_bias_level = wm8731_set_bias_level; | ||
572 | codec->dai = &wm8731_dai; | ||
573 | codec->num_dai = 1; | ||
574 | codec->reg_cache_size = WM8731_CACHEREGNUM; | ||
575 | codec->reg_cache = &wm8731->reg_cache; | ||
639 | 576 | ||
640 | client = i2c_new_device(adapter, &info); | 577 | memcpy(codec->reg_cache, wm8731_reg, sizeof(wm8731_reg)); |
641 | i2c_put_adapter(adapter); | 578 | |
642 | if (!client) { | 579 | ret = wm8731_reset(codec); |
643 | dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", | 580 | if (ret < 0) { |
644 | (unsigned int)info.addr); | 581 | dev_err(codec->dev, "Failed to issue reset\n"); |
645 | goto err_driver; | 582 | return ret; |
646 | } | 583 | } |
647 | 584 | ||
648 | return 0; | 585 | wm8731_dai.dev = codec->dev; |
649 | 586 | ||
650 | err_driver: | 587 | wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
651 | i2c_del_driver(&wm8731_i2c_driver); | ||
652 | return -ENODEV; | ||
653 | } | ||
654 | #endif | ||
655 | 588 | ||
656 | #if defined(CONFIG_SPI_MASTER) | 589 | /* Latch the update bits */ |
657 | static int __devinit wm8731_spi_probe(struct spi_device *spi) | 590 | reg = wm8731_read_reg_cache(codec, WM8731_LOUT1V); |
658 | { | 591 | wm8731_write(codec, WM8731_LOUT1V, reg & ~0x0100); |
659 | struct snd_soc_device *socdev = wm8731_socdev; | 592 | reg = wm8731_read_reg_cache(codec, WM8731_ROUT1V); |
660 | struct snd_soc_codec *codec = socdev->codec; | 593 | wm8731_write(codec, WM8731_ROUT1V, reg & ~0x0100); |
661 | int ret; | 594 | reg = wm8731_read_reg_cache(codec, WM8731_LINVOL); |
595 | wm8731_write(codec, WM8731_LINVOL, reg & ~0x0100); | ||
596 | reg = wm8731_read_reg_cache(codec, WM8731_RINVOL); | ||
597 | wm8731_write(codec, WM8731_RINVOL, reg & ~0x0100); | ||
662 | 598 | ||
663 | codec->control_data = spi; | 599 | /* Disable bypass path by default */ |
600 | reg = wm8731_read_reg_cache(codec, WM8731_APANA); | ||
601 | wm8731_write(codec, WM8731_APANA, reg & ~0x4); | ||
664 | 602 | ||
665 | ret = wm8731_init(socdev); | 603 | wm8731_codec = codec; |
666 | if (ret < 0) | ||
667 | dev_err(&spi->dev, "failed to initialise WM8731\n"); | ||
668 | 604 | ||
669 | return ret; | 605 | ret = snd_soc_register_codec(codec); |
670 | } | 606 | if (ret != 0) { |
607 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
608 | return ret; | ||
609 | } | ||
610 | |||
611 | ret = snd_soc_register_dai(&wm8731_dai); | ||
612 | if (ret != 0) { | ||
613 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
614 | snd_soc_unregister_codec(codec); | ||
615 | return ret; | ||
616 | } | ||
671 | 617 | ||
672 | static int __devexit wm8731_spi_remove(struct spi_device *spi) | ||
673 | { | ||
674 | return 0; | 618 | return 0; |
675 | } | 619 | } |
676 | 620 | ||
677 | static struct spi_driver wm8731_spi_driver = { | 621 | static void wm8731_unregister(struct wm8731_priv *wm8731) |
678 | .driver = { | 622 | { |
679 | .name = "wm8731", | 623 | wm8731_set_bias_level(&wm8731->codec, SND_SOC_BIAS_OFF); |
680 | .bus = &spi_bus_type, | 624 | snd_soc_unregister_dai(&wm8731_dai); |
681 | .owner = THIS_MODULE, | 625 | snd_soc_unregister_codec(&wm8731->codec); |
682 | }, | 626 | kfree(wm8731); |
683 | .probe = wm8731_spi_probe, | 627 | wm8731_codec = NULL; |
684 | .remove = __devexit_p(wm8731_spi_remove), | 628 | } |
685 | }; | ||
686 | 629 | ||
630 | #if defined(CONFIG_SPI_MASTER) | ||
687 | static int wm8731_spi_write(struct spi_device *spi, const char *data, int len) | 631 | static int wm8731_spi_write(struct spi_device *spi, const char *data, int len) |
688 | { | 632 | { |
689 | struct spi_transfer t; | 633 | struct spi_transfer t; |
@@ -707,101 +651,121 @@ static int wm8731_spi_write(struct spi_device *spi, const char *data, int len) | |||
707 | 651 | ||
708 | return len; | 652 | return len; |
709 | } | 653 | } |
710 | #endif /* CONFIG_SPI_MASTER */ | ||
711 | 654 | ||
712 | static int wm8731_probe(struct platform_device *pdev) | 655 | static int __devinit wm8731_spi_probe(struct spi_device *spi) |
713 | { | 656 | { |
714 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
715 | struct wm8731_setup_data *setup; | ||
716 | struct snd_soc_codec *codec; | 657 | struct snd_soc_codec *codec; |
717 | struct wm8731_priv *wm8731; | 658 | struct wm8731_priv *wm8731; |
718 | int ret = 0; | ||
719 | |||
720 | pr_info("WM8731 Audio Codec %s", WM8731_VERSION); | ||
721 | |||
722 | setup = socdev->codec_data; | ||
723 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
724 | if (codec == NULL) | ||
725 | return -ENOMEM; | ||
726 | 659 | ||
727 | wm8731 = kzalloc(sizeof(struct wm8731_priv), GFP_KERNEL); | 660 | wm8731 = kzalloc(sizeof(struct wm8731_priv), GFP_KERNEL); |
728 | if (wm8731 == NULL) { | 661 | if (wm8731 == NULL) |
729 | kfree(codec); | ||
730 | return -ENOMEM; | 662 | return -ENOMEM; |
731 | } | ||
732 | 663 | ||
733 | codec->private_data = wm8731; | 664 | codec = &wm8731->codec; |
734 | socdev->codec = codec; | 665 | codec->control_data = spi; |
735 | mutex_init(&codec->mutex); | 666 | codec->hw_write = (hw_write_t)wm8731_spi_write; |
736 | INIT_LIST_HEAD(&codec->dapm_widgets); | 667 | codec->dev = &spi->dev; |
737 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
738 | 668 | ||
739 | wm8731_socdev = socdev; | 669 | spi->dev.driver_data = wm8731; |
740 | ret = -ENODEV; | ||
741 | 670 | ||
742 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 671 | return wm8731_register(wm8731); |
743 | if (setup->i2c_address) { | ||
744 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
745 | ret = wm8731_add_i2c_device(pdev, setup); | ||
746 | } | ||
747 | #endif | ||
748 | #if defined(CONFIG_SPI_MASTER) | ||
749 | if (setup->spi) { | ||
750 | codec->hw_write = (hw_write_t)wm8731_spi_write; | ||
751 | ret = spi_register_driver(&wm8731_spi_driver); | ||
752 | if (ret != 0) | ||
753 | printk(KERN_ERR "can't add spi driver"); | ||
754 | } | ||
755 | #endif | ||
756 | |||
757 | if (ret != 0) { | ||
758 | kfree(codec->private_data); | ||
759 | kfree(codec); | ||
760 | } | ||
761 | return ret; | ||
762 | } | 672 | } |
763 | 673 | ||
764 | /* power down chip */ | 674 | static int __devexit wm8731_spi_remove(struct spi_device *spi) |
765 | static int wm8731_remove(struct platform_device *pdev) | ||
766 | { | 675 | { |
767 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 676 | struct wm8731_priv *wm8731 = spi->dev.driver_data; |
768 | struct snd_soc_codec *codec = socdev->codec; | ||
769 | 677 | ||
770 | if (codec->control_data) | 678 | wm8731_unregister(wm8731); |
771 | wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); | 679 | |
680 | return 0; | ||
681 | } | ||
682 | |||
683 | static struct spi_driver wm8731_spi_driver = { | ||
684 | .driver = { | ||
685 | .name = "wm8731", | ||
686 | .bus = &spi_bus_type, | ||
687 | .owner = THIS_MODULE, | ||
688 | }, | ||
689 | .probe = wm8731_spi_probe, | ||
690 | .remove = __devexit_p(wm8731_spi_remove), | ||
691 | }; | ||
692 | #endif /* CONFIG_SPI_MASTER */ | ||
772 | 693 | ||
773 | snd_soc_free_pcms(socdev); | ||
774 | snd_soc_dapm_free(socdev); | ||
775 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 694 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
776 | i2c_unregister_device(codec->control_data); | 695 | static __devinit int wm8731_i2c_probe(struct i2c_client *i2c, |
777 | i2c_del_driver(&wm8731_i2c_driver); | 696 | const struct i2c_device_id *id) |
778 | #endif | 697 | { |
779 | #if defined(CONFIG_SPI_MASTER) | 698 | struct wm8731_priv *wm8731; |
780 | spi_unregister_driver(&wm8731_spi_driver); | 699 | struct snd_soc_codec *codec; |
781 | #endif | 700 | |
782 | kfree(codec->private_data); | 701 | wm8731 = kzalloc(sizeof(struct wm8731_priv), GFP_KERNEL); |
783 | kfree(codec); | 702 | if (wm8731 == NULL) |
703 | return -ENOMEM; | ||
704 | |||
705 | codec = &wm8731->codec; | ||
706 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
784 | 707 | ||
708 | i2c_set_clientdata(i2c, wm8731); | ||
709 | codec->control_data = i2c; | ||
710 | |||
711 | codec->dev = &i2c->dev; | ||
712 | |||
713 | return wm8731_register(wm8731); | ||
714 | } | ||
715 | |||
716 | static __devexit int wm8731_i2c_remove(struct i2c_client *client) | ||
717 | { | ||
718 | struct wm8731_priv *wm8731 = i2c_get_clientdata(client); | ||
719 | wm8731_unregister(wm8731); | ||
785 | return 0; | 720 | return 0; |
786 | } | 721 | } |
787 | 722 | ||
788 | struct snd_soc_codec_device soc_codec_dev_wm8731 = { | 723 | static const struct i2c_device_id wm8731_i2c_id[] = { |
789 | .probe = wm8731_probe, | 724 | { "wm8731", 0 }, |
790 | .remove = wm8731_remove, | 725 | { } |
791 | .suspend = wm8731_suspend, | ||
792 | .resume = wm8731_resume, | ||
793 | }; | 726 | }; |
794 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731); | 727 | MODULE_DEVICE_TABLE(i2c, wm8731_i2c_id); |
728 | |||
729 | static struct i2c_driver wm8731_i2c_driver = { | ||
730 | .driver = { | ||
731 | .name = "WM8731 I2C Codec", | ||
732 | .owner = THIS_MODULE, | ||
733 | }, | ||
734 | .probe = wm8731_i2c_probe, | ||
735 | .remove = __devexit_p(wm8731_i2c_remove), | ||
736 | .id_table = wm8731_i2c_id, | ||
737 | }; | ||
738 | #endif | ||
795 | 739 | ||
796 | static int __init wm8731_modinit(void) | 740 | static int __init wm8731_modinit(void) |
797 | { | 741 | { |
798 | return snd_soc_register_dai(&wm8731_dai); | 742 | int ret; |
743 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
744 | ret = i2c_add_driver(&wm8731_i2c_driver); | ||
745 | if (ret != 0) { | ||
746 | printk(KERN_ERR "Failed to register WM8731 I2C driver: %d\n", | ||
747 | ret); | ||
748 | } | ||
749 | #endif | ||
750 | #if defined(CONFIG_SPI_MASTER) | ||
751 | ret = spi_register_driver(&wm8731_spi_driver); | ||
752 | if (ret != 0) { | ||
753 | printk(KERN_ERR "Failed to register WM8731 SPI driver: %d\n", | ||
754 | ret); | ||
755 | } | ||
756 | #endif | ||
757 | return 0; | ||
799 | } | 758 | } |
800 | module_init(wm8731_modinit); | 759 | module_init(wm8731_modinit); |
801 | 760 | ||
802 | static void __exit wm8731_exit(void) | 761 | static void __exit wm8731_exit(void) |
803 | { | 762 | { |
804 | snd_soc_unregister_dai(&wm8731_dai); | 763 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
764 | i2c_del_driver(&wm8731_i2c_driver); | ||
765 | #endif | ||
766 | #if defined(CONFIG_SPI_MASTER) | ||
767 | spi_unregister_driver(&wm8731_spi_driver); | ||
768 | #endif | ||
805 | } | 769 | } |
806 | module_exit(wm8731_exit); | 770 | module_exit(wm8731_exit); |
807 | 771 | ||
diff --git a/sound/soc/codecs/wm8731.h b/sound/soc/codecs/wm8731.h index 95190e9c0c14..cd7b806e8ad0 100644 --- a/sound/soc/codecs/wm8731.h +++ b/sound/soc/codecs/wm8731.h | |||
@@ -34,12 +34,6 @@ | |||
34 | #define WM8731_SYSCLK 0 | 34 | #define WM8731_SYSCLK 0 |
35 | #define WM8731_DAI 0 | 35 | #define WM8731_DAI 0 |
36 | 36 | ||
37 | struct wm8731_setup_data { | ||
38 | int spi; | ||
39 | int i2c_bus; | ||
40 | unsigned short i2c_address; | ||
41 | }; | ||
42 | |||
43 | extern struct snd_soc_dai wm8731_dai; | 37 | extern struct snd_soc_dai wm8731_dai; |
44 | extern struct snd_soc_codec_device soc_codec_dev_wm8731; | 38 | extern struct snd_soc_codec_device soc_codec_dev_wm8731; |
45 | 39 | ||
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index 5997fa68e0d5..b64509b01a49 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c | |||
@@ -231,21 +231,6 @@ SOC_SINGLE("Mono Playback Volume", WM8750_MOUTV, 0, 127, 0), | |||
231 | 231 | ||
232 | }; | 232 | }; |
233 | 233 | ||
234 | /* add non dapm controls */ | ||
235 | static int wm8750_add_controls(struct snd_soc_codec *codec) | ||
236 | { | ||
237 | int err, i; | ||
238 | |||
239 | for (i = 0; i < ARRAY_SIZE(wm8750_snd_controls); i++) { | ||
240 | err = snd_ctl_add(codec->card, | ||
241 | snd_soc_cnew(&wm8750_snd_controls[i], | ||
242 | codec, NULL)); | ||
243 | if (err < 0) | ||
244 | return err; | ||
245 | } | ||
246 | return 0; | ||
247 | } | ||
248 | |||
249 | /* | 234 | /* |
250 | * DAPM Controls | 235 | * DAPM Controls |
251 | */ | 236 | */ |
@@ -619,7 +604,7 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream, | |||
619 | { | 604 | { |
620 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 605 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
621 | struct snd_soc_device *socdev = rtd->socdev; | 606 | struct snd_soc_device *socdev = rtd->socdev; |
622 | struct snd_soc_codec *codec = socdev->codec; | 607 | struct snd_soc_codec *codec = socdev->card->codec; |
623 | struct wm8750_priv *wm8750 = codec->private_data; | 608 | struct wm8750_priv *wm8750 = codec->private_data; |
624 | u16 iface = wm8750_read_reg_cache(codec, WM8750_IFACE) & 0x1f3; | 609 | u16 iface = wm8750_read_reg_cache(codec, WM8750_IFACE) & 0x1f3; |
625 | u16 srate = wm8750_read_reg_cache(codec, WM8750_SRATE) & 0x1c0; | 610 | u16 srate = wm8750_read_reg_cache(codec, WM8750_SRATE) & 0x1c0; |
@@ -694,6 +679,13 @@ static int wm8750_set_bias_level(struct snd_soc_codec *codec, | |||
694 | #define WM8750_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | 679 | #define WM8750_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ |
695 | SNDRV_PCM_FMTBIT_S24_LE) | 680 | SNDRV_PCM_FMTBIT_S24_LE) |
696 | 681 | ||
682 | static struct snd_soc_dai_ops wm8750_dai_ops = { | ||
683 | .hw_params = wm8750_pcm_hw_params, | ||
684 | .digital_mute = wm8750_mute, | ||
685 | .set_fmt = wm8750_set_dai_fmt, | ||
686 | .set_sysclk = wm8750_set_dai_sysclk, | ||
687 | }; | ||
688 | |||
697 | struct snd_soc_dai wm8750_dai = { | 689 | struct snd_soc_dai wm8750_dai = { |
698 | .name = "WM8750", | 690 | .name = "WM8750", |
699 | .playback = { | 691 | .playback = { |
@@ -708,12 +700,7 @@ struct snd_soc_dai wm8750_dai = { | |||
708 | .channels_max = 2, | 700 | .channels_max = 2, |
709 | .rates = WM8750_RATES, | 701 | .rates = WM8750_RATES, |
710 | .formats = WM8750_FORMATS,}, | 702 | .formats = WM8750_FORMATS,}, |
711 | .ops = { | 703 | .ops = &wm8750_dai_ops, |
712 | .hw_params = wm8750_pcm_hw_params, | ||
713 | .digital_mute = wm8750_mute, | ||
714 | .set_fmt = wm8750_set_dai_fmt, | ||
715 | .set_sysclk = wm8750_set_dai_sysclk, | ||
716 | }, | ||
717 | }; | 704 | }; |
718 | EXPORT_SYMBOL_GPL(wm8750_dai); | 705 | EXPORT_SYMBOL_GPL(wm8750_dai); |
719 | 706 | ||
@@ -727,7 +714,7 @@ static void wm8750_work(struct work_struct *work) | |||
727 | static int wm8750_suspend(struct platform_device *pdev, pm_message_t state) | 714 | static int wm8750_suspend(struct platform_device *pdev, pm_message_t state) |
728 | { | 715 | { |
729 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 716 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
730 | struct snd_soc_codec *codec = socdev->codec; | 717 | struct snd_soc_codec *codec = socdev->card->codec; |
731 | 718 | ||
732 | wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF); | 719 | wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF); |
733 | return 0; | 720 | return 0; |
@@ -736,7 +723,7 @@ static int wm8750_suspend(struct platform_device *pdev, pm_message_t state) | |||
736 | static int wm8750_resume(struct platform_device *pdev) | 723 | static int wm8750_resume(struct platform_device *pdev) |
737 | { | 724 | { |
738 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 725 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
739 | struct snd_soc_codec *codec = socdev->codec; | 726 | struct snd_soc_codec *codec = socdev->card->codec; |
740 | int i; | 727 | int i; |
741 | u8 data[2]; | 728 | u8 data[2]; |
742 | u16 *cache = codec->reg_cache; | 729 | u16 *cache = codec->reg_cache; |
@@ -769,7 +756,7 @@ static int wm8750_resume(struct platform_device *pdev) | |||
769 | */ | 756 | */ |
770 | static int wm8750_init(struct snd_soc_device *socdev) | 757 | static int wm8750_init(struct snd_soc_device *socdev) |
771 | { | 758 | { |
772 | struct snd_soc_codec *codec = socdev->codec; | 759 | struct snd_soc_codec *codec = socdev->card->codec; |
773 | int reg, ret = 0; | 760 | int reg, ret = 0; |
774 | 761 | ||
775 | codec->name = "WM8750"; | 762 | codec->name = "WM8750"; |
@@ -816,7 +803,8 @@ static int wm8750_init(struct snd_soc_device *socdev) | |||
816 | reg = wm8750_read_reg_cache(codec, WM8750_RINVOL); | 803 | reg = wm8750_read_reg_cache(codec, WM8750_RINVOL); |
817 | wm8750_write(codec, WM8750_RINVOL, reg | 0x0100); | 804 | wm8750_write(codec, WM8750_RINVOL, reg | 0x0100); |
818 | 805 | ||
819 | wm8750_add_controls(codec); | 806 | snd_soc_add_controls(codec, wm8750_snd_controls, |
807 | ARRAY_SIZE(wm8750_snd_controls)); | ||
820 | wm8750_add_widgets(codec); | 808 | wm8750_add_widgets(codec); |
821 | ret = snd_soc_init_card(socdev); | 809 | ret = snd_soc_init_card(socdev); |
822 | if (ret < 0) { | 810 | if (ret < 0) { |
@@ -850,7 +838,7 @@ static int wm8750_i2c_probe(struct i2c_client *i2c, | |||
850 | const struct i2c_device_id *id) | 838 | const struct i2c_device_id *id) |
851 | { | 839 | { |
852 | struct snd_soc_device *socdev = wm8750_socdev; | 840 | struct snd_soc_device *socdev = wm8750_socdev; |
853 | struct snd_soc_codec *codec = socdev->codec; | 841 | struct snd_soc_codec *codec = socdev->card->codec; |
854 | int ret; | 842 | int ret; |
855 | 843 | ||
856 | i2c_set_clientdata(i2c, codec); | 844 | i2c_set_clientdata(i2c, codec); |
@@ -931,7 +919,7 @@ err_driver: | |||
931 | static int __devinit wm8750_spi_probe(struct spi_device *spi) | 919 | static int __devinit wm8750_spi_probe(struct spi_device *spi) |
932 | { | 920 | { |
933 | struct snd_soc_device *socdev = wm8750_socdev; | 921 | struct snd_soc_device *socdev = wm8750_socdev; |
934 | struct snd_soc_codec *codec = socdev->codec; | 922 | struct snd_soc_codec *codec = socdev->card->codec; |
935 | int ret; | 923 | int ret; |
936 | 924 | ||
937 | codec->control_data = spi; | 925 | codec->control_data = spi; |
@@ -1003,7 +991,7 @@ static int wm8750_probe(struct platform_device *pdev) | |||
1003 | } | 991 | } |
1004 | 992 | ||
1005 | codec->private_data = wm8750; | 993 | codec->private_data = wm8750; |
1006 | socdev->codec = codec; | 994 | socdev->card->codec = codec; |
1007 | mutex_init(&codec->mutex); | 995 | mutex_init(&codec->mutex); |
1008 | INIT_LIST_HEAD(&codec->dapm_widgets); | 996 | INIT_LIST_HEAD(&codec->dapm_widgets); |
1009 | INIT_LIST_HEAD(&codec->dapm_paths); | 997 | INIT_LIST_HEAD(&codec->dapm_paths); |
@@ -1057,7 +1045,7 @@ static int run_delayed_work(struct delayed_work *dwork) | |||
1057 | static int wm8750_remove(struct platform_device *pdev) | 1045 | static int wm8750_remove(struct platform_device *pdev) |
1058 | { | 1046 | { |
1059 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1047 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
1060 | struct snd_soc_codec *codec = socdev->codec; | 1048 | struct snd_soc_codec *codec = socdev->card->codec; |
1061 | 1049 | ||
1062 | if (codec->control_data) | 1050 | if (codec->control_data) |
1063 | wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1051 | wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF); |
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index 77620ab98756..a6e8f3f7f052 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c | |||
@@ -51,8 +51,6 @@ | |||
51 | 51 | ||
52 | #include "wm8753.h" | 52 | #include "wm8753.h" |
53 | 53 | ||
54 | #define WM8753_VERSION "0.16" | ||
55 | |||
56 | static int caps_charge = 2000; | 54 | static int caps_charge = 2000; |
57 | module_param(caps_charge, int, 0); | 55 | module_param(caps_charge, int, 0); |
58 | MODULE_PARM_DESC(caps_charge, "WM8753 cap charge time (msecs)"); | 56 | MODULE_PARM_DESC(caps_charge, "WM8753 cap charge time (msecs)"); |
@@ -60,12 +58,6 @@ MODULE_PARM_DESC(caps_charge, "WM8753 cap charge time (msecs)"); | |||
60 | static void wm8753_set_dai_mode(struct snd_soc_codec *codec, | 58 | static void wm8753_set_dai_mode(struct snd_soc_codec *codec, |
61 | unsigned int mode); | 59 | unsigned int mode); |
62 | 60 | ||
63 | /* codec private data */ | ||
64 | struct wm8753_priv { | ||
65 | unsigned int sysclk; | ||
66 | unsigned int pcmclk; | ||
67 | }; | ||
68 | |||
69 | /* | 61 | /* |
70 | * wm8753 register cache | 62 | * wm8753 register cache |
71 | * We can't read the WM8753 register space when we | 63 | * We can't read the WM8753 register space when we |
@@ -90,6 +82,14 @@ static const u16 wm8753_reg[] = { | |||
90 | 0x0000, 0x0000 | 82 | 0x0000, 0x0000 |
91 | }; | 83 | }; |
92 | 84 | ||
85 | /* codec private data */ | ||
86 | struct wm8753_priv { | ||
87 | unsigned int sysclk; | ||
88 | unsigned int pcmclk; | ||
89 | struct snd_soc_codec codec; | ||
90 | u16 reg_cache[ARRAY_SIZE(wm8753_reg)]; | ||
91 | }; | ||
92 | |||
93 | /* | 93 | /* |
94 | * read wm8753 register cache | 94 | * read wm8753 register cache |
95 | */ | 95 | */ |
@@ -97,7 +97,7 @@ static inline unsigned int wm8753_read_reg_cache(struct snd_soc_codec *codec, | |||
97 | unsigned int reg) | 97 | unsigned int reg) |
98 | { | 98 | { |
99 | u16 *cache = codec->reg_cache; | 99 | u16 *cache = codec->reg_cache; |
100 | if (reg < 1 || reg > (ARRAY_SIZE(wm8753_reg) + 1)) | 100 | if (reg < 1 || reg >= (ARRAY_SIZE(wm8753_reg) + 1)) |
101 | return -1; | 101 | return -1; |
102 | return cache[reg - 1]; | 102 | return cache[reg - 1]; |
103 | } | 103 | } |
@@ -109,7 +109,7 @@ static inline void wm8753_write_reg_cache(struct snd_soc_codec *codec, | |||
109 | unsigned int reg, unsigned int value) | 109 | unsigned int reg, unsigned int value) |
110 | { | 110 | { |
111 | u16 *cache = codec->reg_cache; | 111 | u16 *cache = codec->reg_cache; |
112 | if (reg < 1 || reg > 0x3f) | 112 | if (reg < 1 || reg >= (ARRAY_SIZE(wm8753_reg) + 1)) |
113 | return; | 113 | return; |
114 | cache[reg - 1] = value; | 114 | cache[reg - 1] = value; |
115 | } | 115 | } |
@@ -339,21 +339,6 @@ SOC_ENUM("ADC Data Select", wm8753_enum[27]), | |||
339 | SOC_ENUM("ROUT2 Phase", wm8753_enum[28]), | 339 | SOC_ENUM("ROUT2 Phase", wm8753_enum[28]), |
340 | }; | 340 | }; |
341 | 341 | ||
342 | /* add non dapm controls */ | ||
343 | static int wm8753_add_controls(struct snd_soc_codec *codec) | ||
344 | { | ||
345 | int err, i; | ||
346 | |||
347 | for (i = 0; i < ARRAY_SIZE(wm8753_snd_controls); i++) { | ||
348 | err = snd_ctl_add(codec->card, | ||
349 | snd_soc_cnew(&wm8753_snd_controls[i], | ||
350 | codec, NULL)); | ||
351 | if (err < 0) | ||
352 | return err; | ||
353 | } | ||
354 | return 0; | ||
355 | } | ||
356 | |||
357 | /* | 342 | /* |
358 | * _DAPM_ Controls | 343 | * _DAPM_ Controls |
359 | */ | 344 | */ |
@@ -927,7 +912,7 @@ static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream, | |||
927 | { | 912 | { |
928 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 913 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
929 | struct snd_soc_device *socdev = rtd->socdev; | 914 | struct snd_soc_device *socdev = rtd->socdev; |
930 | struct snd_soc_codec *codec = socdev->codec; | 915 | struct snd_soc_codec *codec = socdev->card->codec; |
931 | struct wm8753_priv *wm8753 = codec->private_data; | 916 | struct wm8753_priv *wm8753 = codec->private_data; |
932 | u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01f3; | 917 | u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01f3; |
933 | u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x017f; | 918 | u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x017f; |
@@ -1161,7 +1146,7 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream, | |||
1161 | { | 1146 | { |
1162 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1147 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1163 | struct snd_soc_device *socdev = rtd->socdev; | 1148 | struct snd_soc_device *socdev = rtd->socdev; |
1164 | struct snd_soc_codec *codec = socdev->codec; | 1149 | struct snd_soc_codec *codec = socdev->card->codec; |
1165 | struct wm8753_priv *wm8753 = codec->private_data; | 1150 | struct wm8753_priv *wm8753 = codec->private_data; |
1166 | u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x01c0; | 1151 | u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x01c0; |
1167 | u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01f3; | 1152 | u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01f3; |
@@ -1316,6 +1301,51 @@ static int wm8753_set_bias_level(struct snd_soc_codec *codec, | |||
1316 | * 3. Voice disabled - HIFI over HIFI | 1301 | * 3. Voice disabled - HIFI over HIFI |
1317 | * 4. Voice disabled - HIFI over HIFI, uses voice DAI LRC for capture | 1302 | * 4. Voice disabled - HIFI over HIFI, uses voice DAI LRC for capture |
1318 | */ | 1303 | */ |
1304 | static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode1 = { | ||
1305 | .hw_params = wm8753_i2s_hw_params, | ||
1306 | .digital_mute = wm8753_mute, | ||
1307 | .set_fmt = wm8753_mode1h_set_dai_fmt, | ||
1308 | .set_clkdiv = wm8753_set_dai_clkdiv, | ||
1309 | .set_pll = wm8753_set_dai_pll, | ||
1310 | .set_sysclk = wm8753_set_dai_sysclk, | ||
1311 | }; | ||
1312 | |||
1313 | static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode1 = { | ||
1314 | .hw_params = wm8753_pcm_hw_params, | ||
1315 | .digital_mute = wm8753_mute, | ||
1316 | .set_fmt = wm8753_mode1v_set_dai_fmt, | ||
1317 | .set_clkdiv = wm8753_set_dai_clkdiv, | ||
1318 | .set_pll = wm8753_set_dai_pll, | ||
1319 | .set_sysclk = wm8753_set_dai_sysclk, | ||
1320 | }; | ||
1321 | |||
1322 | static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode2 = { | ||
1323 | .hw_params = wm8753_pcm_hw_params, | ||
1324 | .digital_mute = wm8753_mute, | ||
1325 | .set_fmt = wm8753_mode2_set_dai_fmt, | ||
1326 | .set_clkdiv = wm8753_set_dai_clkdiv, | ||
1327 | .set_pll = wm8753_set_dai_pll, | ||
1328 | .set_sysclk = wm8753_set_dai_sysclk, | ||
1329 | }; | ||
1330 | |||
1331 | static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode3 = { | ||
1332 | .hw_params = wm8753_i2s_hw_params, | ||
1333 | .digital_mute = wm8753_mute, | ||
1334 | .set_fmt = wm8753_mode3_4_set_dai_fmt, | ||
1335 | .set_clkdiv = wm8753_set_dai_clkdiv, | ||
1336 | .set_pll = wm8753_set_dai_pll, | ||
1337 | .set_sysclk = wm8753_set_dai_sysclk, | ||
1338 | }; | ||
1339 | |||
1340 | static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode4 = { | ||
1341 | .hw_params = wm8753_i2s_hw_params, | ||
1342 | .digital_mute = wm8753_mute, | ||
1343 | .set_fmt = wm8753_mode3_4_set_dai_fmt, | ||
1344 | .set_clkdiv = wm8753_set_dai_clkdiv, | ||
1345 | .set_pll = wm8753_set_dai_pll, | ||
1346 | .set_sysclk = wm8753_set_dai_sysclk, | ||
1347 | }; | ||
1348 | |||
1319 | static const struct snd_soc_dai wm8753_all_dai[] = { | 1349 | static const struct snd_soc_dai wm8753_all_dai[] = { |
1320 | /* DAI HiFi mode 1 */ | 1350 | /* DAI HiFi mode 1 */ |
1321 | { .name = "WM8753 HiFi", | 1351 | { .name = "WM8753 HiFi", |
@@ -1332,14 +1362,7 @@ static const struct snd_soc_dai wm8753_all_dai[] = { | |||
1332 | .channels_max = 2, | 1362 | .channels_max = 2, |
1333 | .rates = WM8753_RATES, | 1363 | .rates = WM8753_RATES, |
1334 | .formats = WM8753_FORMATS}, | 1364 | .formats = WM8753_FORMATS}, |
1335 | .ops = { | 1365 | .ops = &wm8753_dai_ops_hifi_mode1, |
1336 | .hw_params = wm8753_i2s_hw_params, | ||
1337 | .digital_mute = wm8753_mute, | ||
1338 | .set_fmt = wm8753_mode1h_set_dai_fmt, | ||
1339 | .set_clkdiv = wm8753_set_dai_clkdiv, | ||
1340 | .set_pll = wm8753_set_dai_pll, | ||
1341 | .set_sysclk = wm8753_set_dai_sysclk, | ||
1342 | }, | ||
1343 | }, | 1366 | }, |
1344 | /* DAI Voice mode 1 */ | 1367 | /* DAI Voice mode 1 */ |
1345 | { .name = "WM8753 Voice", | 1368 | { .name = "WM8753 Voice", |
@@ -1356,14 +1379,7 @@ static const struct snd_soc_dai wm8753_all_dai[] = { | |||
1356 | .channels_max = 2, | 1379 | .channels_max = 2, |
1357 | .rates = WM8753_RATES, | 1380 | .rates = WM8753_RATES, |
1358 | .formats = WM8753_FORMATS,}, | 1381 | .formats = WM8753_FORMATS,}, |
1359 | .ops = { | 1382 | .ops = &wm8753_dai_ops_voice_mode1, |
1360 | .hw_params = wm8753_pcm_hw_params, | ||
1361 | .digital_mute = wm8753_mute, | ||
1362 | .set_fmt = wm8753_mode1v_set_dai_fmt, | ||
1363 | .set_clkdiv = wm8753_set_dai_clkdiv, | ||
1364 | .set_pll = wm8753_set_dai_pll, | ||
1365 | .set_sysclk = wm8753_set_dai_sysclk, | ||
1366 | }, | ||
1367 | }, | 1383 | }, |
1368 | /* DAI HiFi mode 2 - dummy */ | 1384 | /* DAI HiFi mode 2 - dummy */ |
1369 | { .name = "WM8753 HiFi", | 1385 | { .name = "WM8753 HiFi", |
@@ -1384,14 +1400,7 @@ static const struct snd_soc_dai wm8753_all_dai[] = { | |||
1384 | .channels_max = 2, | 1400 | .channels_max = 2, |
1385 | .rates = WM8753_RATES, | 1401 | .rates = WM8753_RATES, |
1386 | .formats = WM8753_FORMATS,}, | 1402 | .formats = WM8753_FORMATS,}, |
1387 | .ops = { | 1403 | .ops = &wm8753_dai_ops_voice_mode2, |
1388 | .hw_params = wm8753_pcm_hw_params, | ||
1389 | .digital_mute = wm8753_mute, | ||
1390 | .set_fmt = wm8753_mode2_set_dai_fmt, | ||
1391 | .set_clkdiv = wm8753_set_dai_clkdiv, | ||
1392 | .set_pll = wm8753_set_dai_pll, | ||
1393 | .set_sysclk = wm8753_set_dai_sysclk, | ||
1394 | }, | ||
1395 | }, | 1404 | }, |
1396 | /* DAI HiFi mode 3 */ | 1405 | /* DAI HiFi mode 3 */ |
1397 | { .name = "WM8753 HiFi", | 1406 | { .name = "WM8753 HiFi", |
@@ -1408,14 +1417,7 @@ static const struct snd_soc_dai wm8753_all_dai[] = { | |||
1408 | .channels_max = 2, | 1417 | .channels_max = 2, |
1409 | .rates = WM8753_RATES, | 1418 | .rates = WM8753_RATES, |
1410 | .formats = WM8753_FORMATS,}, | 1419 | .formats = WM8753_FORMATS,}, |
1411 | .ops = { | 1420 | .ops = &wm8753_dai_ops_hifi_mode3, |
1412 | .hw_params = wm8753_i2s_hw_params, | ||
1413 | .digital_mute = wm8753_mute, | ||
1414 | .set_fmt = wm8753_mode3_4_set_dai_fmt, | ||
1415 | .set_clkdiv = wm8753_set_dai_clkdiv, | ||
1416 | .set_pll = wm8753_set_dai_pll, | ||
1417 | .set_sysclk = wm8753_set_dai_sysclk, | ||
1418 | }, | ||
1419 | }, | 1421 | }, |
1420 | /* DAI Voice mode 3 - dummy */ | 1422 | /* DAI Voice mode 3 - dummy */ |
1421 | { .name = "WM8753 Voice", | 1423 | { .name = "WM8753 Voice", |
@@ -1436,14 +1438,7 @@ static const struct snd_soc_dai wm8753_all_dai[] = { | |||
1436 | .channels_max = 2, | 1438 | .channels_max = 2, |
1437 | .rates = WM8753_RATES, | 1439 | .rates = WM8753_RATES, |
1438 | .formats = WM8753_FORMATS,}, | 1440 | .formats = WM8753_FORMATS,}, |
1439 | .ops = { | 1441 | .ops = &wm8753_dai_ops_hifi_mode4, |
1440 | .hw_params = wm8753_i2s_hw_params, | ||
1441 | .digital_mute = wm8753_mute, | ||
1442 | .set_fmt = wm8753_mode3_4_set_dai_fmt, | ||
1443 | .set_clkdiv = wm8753_set_dai_clkdiv, | ||
1444 | .set_pll = wm8753_set_dai_pll, | ||
1445 | .set_sysclk = wm8753_set_dai_sysclk, | ||
1446 | }, | ||
1447 | }, | 1442 | }, |
1448 | /* DAI Voice mode 4 - dummy */ | 1443 | /* DAI Voice mode 4 - dummy */ |
1449 | { .name = "WM8753 Voice", | 1444 | { .name = "WM8753 Voice", |
@@ -1466,30 +1461,35 @@ static void wm8753_set_dai_mode(struct snd_soc_codec *codec, unsigned int mode) | |||
1466 | if (mode < 4) { | 1461 | if (mode < 4) { |
1467 | int playback_active, capture_active, codec_active, pop_wait; | 1462 | int playback_active, capture_active, codec_active, pop_wait; |
1468 | void *private_data; | 1463 | void *private_data; |
1464 | struct list_head list; | ||
1469 | 1465 | ||
1470 | playback_active = wm8753_dai[0].playback.active; | 1466 | playback_active = wm8753_dai[0].playback.active; |
1471 | capture_active = wm8753_dai[0].capture.active; | 1467 | capture_active = wm8753_dai[0].capture.active; |
1472 | codec_active = wm8753_dai[0].active; | 1468 | codec_active = wm8753_dai[0].active; |
1473 | private_data = wm8753_dai[0].private_data; | 1469 | private_data = wm8753_dai[0].private_data; |
1474 | pop_wait = wm8753_dai[0].pop_wait; | 1470 | pop_wait = wm8753_dai[0].pop_wait; |
1471 | list = wm8753_dai[0].list; | ||
1475 | wm8753_dai[0] = wm8753_all_dai[mode << 1]; | 1472 | wm8753_dai[0] = wm8753_all_dai[mode << 1]; |
1476 | wm8753_dai[0].playback.active = playback_active; | 1473 | wm8753_dai[0].playback.active = playback_active; |
1477 | wm8753_dai[0].capture.active = capture_active; | 1474 | wm8753_dai[0].capture.active = capture_active; |
1478 | wm8753_dai[0].active = codec_active; | 1475 | wm8753_dai[0].active = codec_active; |
1479 | wm8753_dai[0].private_data = private_data; | 1476 | wm8753_dai[0].private_data = private_data; |
1480 | wm8753_dai[0].pop_wait = pop_wait; | 1477 | wm8753_dai[0].pop_wait = pop_wait; |
1478 | wm8753_dai[0].list = list; | ||
1481 | 1479 | ||
1482 | playback_active = wm8753_dai[1].playback.active; | 1480 | playback_active = wm8753_dai[1].playback.active; |
1483 | capture_active = wm8753_dai[1].capture.active; | 1481 | capture_active = wm8753_dai[1].capture.active; |
1484 | codec_active = wm8753_dai[1].active; | 1482 | codec_active = wm8753_dai[1].active; |
1485 | private_data = wm8753_dai[1].private_data; | 1483 | private_data = wm8753_dai[1].private_data; |
1486 | pop_wait = wm8753_dai[1].pop_wait; | 1484 | pop_wait = wm8753_dai[1].pop_wait; |
1485 | list = wm8753_dai[1].list; | ||
1487 | wm8753_dai[1] = wm8753_all_dai[(mode << 1) + 1]; | 1486 | wm8753_dai[1] = wm8753_all_dai[(mode << 1) + 1]; |
1488 | wm8753_dai[1].playback.active = playback_active; | 1487 | wm8753_dai[1].playback.active = playback_active; |
1489 | wm8753_dai[1].capture.active = capture_active; | 1488 | wm8753_dai[1].capture.active = capture_active; |
1490 | wm8753_dai[1].active = codec_active; | 1489 | wm8753_dai[1].active = codec_active; |
1491 | wm8753_dai[1].private_data = private_data; | 1490 | wm8753_dai[1].private_data = private_data; |
1492 | wm8753_dai[1].pop_wait = pop_wait; | 1491 | wm8753_dai[1].pop_wait = pop_wait; |
1492 | wm8753_dai[1].list = list; | ||
1493 | } | 1493 | } |
1494 | wm8753_dai[0].codec = codec; | 1494 | wm8753_dai[0].codec = codec; |
1495 | wm8753_dai[1].codec = codec; | 1495 | wm8753_dai[1].codec = codec; |
@@ -1505,7 +1505,7 @@ static void wm8753_work(struct work_struct *work) | |||
1505 | static int wm8753_suspend(struct platform_device *pdev, pm_message_t state) | 1505 | static int wm8753_suspend(struct platform_device *pdev, pm_message_t state) |
1506 | { | 1506 | { |
1507 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1507 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
1508 | struct snd_soc_codec *codec = socdev->codec; | 1508 | struct snd_soc_codec *codec = socdev->card->codec; |
1509 | 1509 | ||
1510 | /* we only need to suspend if we are a valid card */ | 1510 | /* we only need to suspend if we are a valid card */ |
1511 | if (!codec->card) | 1511 | if (!codec->card) |
@@ -1518,7 +1518,7 @@ static int wm8753_suspend(struct platform_device *pdev, pm_message_t state) | |||
1518 | static int wm8753_resume(struct platform_device *pdev) | 1518 | static int wm8753_resume(struct platform_device *pdev) |
1519 | { | 1519 | { |
1520 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1520 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
1521 | struct snd_soc_codec *codec = socdev->codec; | 1521 | struct snd_soc_codec *codec = socdev->card->codec; |
1522 | int i; | 1522 | int i; |
1523 | u8 data[2]; | 1523 | u8 data[2]; |
1524 | u16 *cache = codec->reg_cache; | 1524 | u16 *cache = codec->reg_cache; |
@@ -1531,6 +1531,11 @@ static int wm8753_resume(struct platform_device *pdev) | |||
1531 | for (i = 0; i < ARRAY_SIZE(wm8753_reg); i++) { | 1531 | for (i = 0; i < ARRAY_SIZE(wm8753_reg); i++) { |
1532 | if (i + 1 == WM8753_RESET) | 1532 | if (i + 1 == WM8753_RESET) |
1533 | continue; | 1533 | continue; |
1534 | |||
1535 | /* No point in writing hardware default values back */ | ||
1536 | if (cache[i] == wm8753_reg[i]) | ||
1537 | continue; | ||
1538 | |||
1534 | data[0] = ((i + 1) << 1) | ((cache[i] >> 8) & 0x0001); | 1539 | data[0] = ((i + 1) << 1) | ((cache[i] >> 8) & 0x0001); |
1535 | data[1] = cache[i] & 0x00ff; | 1540 | data[1] = cache[i] & 0x00ff; |
1536 | codec->hw_write(codec->control_data, data, 2); | 1541 | codec->hw_write(codec->control_data, data, 2); |
@@ -1549,44 +1554,129 @@ static int wm8753_resume(struct platform_device *pdev) | |||
1549 | return 0; | 1554 | return 0; |
1550 | } | 1555 | } |
1551 | 1556 | ||
1557 | static struct snd_soc_codec *wm8753_codec; | ||
1558 | |||
1559 | static int wm8753_probe(struct platform_device *pdev) | ||
1560 | { | ||
1561 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1562 | struct snd_soc_codec *codec; | ||
1563 | int ret = 0; | ||
1564 | |||
1565 | if (!wm8753_codec) { | ||
1566 | dev_err(&pdev->dev, "WM8753 codec not yet registered\n"); | ||
1567 | return -EINVAL; | ||
1568 | } | ||
1569 | |||
1570 | socdev->card->codec = wm8753_codec; | ||
1571 | codec = wm8753_codec; | ||
1572 | |||
1573 | wm8753_set_dai_mode(codec, 0); | ||
1574 | |||
1575 | /* register pcms */ | ||
1576 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
1577 | if (ret < 0) { | ||
1578 | printk(KERN_ERR "wm8753: failed to create pcms\n"); | ||
1579 | goto pcm_err; | ||
1580 | } | ||
1581 | |||
1582 | snd_soc_add_controls(codec, wm8753_snd_controls, | ||
1583 | ARRAY_SIZE(wm8753_snd_controls)); | ||
1584 | wm8753_add_widgets(codec); | ||
1585 | ret = snd_soc_init_card(socdev); | ||
1586 | if (ret < 0) { | ||
1587 | printk(KERN_ERR "wm8753: failed to register card\n"); | ||
1588 | goto card_err; | ||
1589 | } | ||
1590 | |||
1591 | return 0; | ||
1592 | |||
1593 | card_err: | ||
1594 | snd_soc_free_pcms(socdev); | ||
1595 | snd_soc_dapm_free(socdev); | ||
1596 | |||
1597 | pcm_err: | ||
1598 | return ret; | ||
1599 | } | ||
1600 | |||
1552 | /* | 1601 | /* |
1553 | * initialise the WM8753 driver | 1602 | * This function forces any delayed work to be queued and run. |
1554 | * register the mixer and dsp interfaces with the kernel | ||
1555 | */ | 1603 | */ |
1556 | static int wm8753_init(struct snd_soc_device *socdev) | 1604 | static int run_delayed_work(struct delayed_work *dwork) |
1605 | { | ||
1606 | int ret; | ||
1607 | |||
1608 | /* cancel any work waiting to be queued. */ | ||
1609 | ret = cancel_delayed_work(dwork); | ||
1610 | |||
1611 | /* if there was any work waiting then we run it now and | ||
1612 | * wait for it's completion */ | ||
1613 | if (ret) { | ||
1614 | schedule_delayed_work(dwork, 0); | ||
1615 | flush_scheduled_work(); | ||
1616 | } | ||
1617 | return ret; | ||
1618 | } | ||
1619 | |||
1620 | /* power down chip */ | ||
1621 | static int wm8753_remove(struct platform_device *pdev) | ||
1557 | { | 1622 | { |
1558 | struct snd_soc_codec *codec = socdev->codec; | 1623 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
1559 | int reg, ret = 0; | 1624 | |
1625 | snd_soc_free_pcms(socdev); | ||
1626 | snd_soc_dapm_free(socdev); | ||
1627 | |||
1628 | return 0; | ||
1629 | } | ||
1630 | |||
1631 | struct snd_soc_codec_device soc_codec_dev_wm8753 = { | ||
1632 | .probe = wm8753_probe, | ||
1633 | .remove = wm8753_remove, | ||
1634 | .suspend = wm8753_suspend, | ||
1635 | .resume = wm8753_resume, | ||
1636 | }; | ||
1637 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8753); | ||
1638 | |||
1639 | static int wm8753_register(struct wm8753_priv *wm8753) | ||
1640 | { | ||
1641 | int ret, i; | ||
1642 | struct snd_soc_codec *codec = &wm8753->codec; | ||
1643 | u16 reg; | ||
1644 | |||
1645 | if (wm8753_codec) { | ||
1646 | dev_err(codec->dev, "Multiple WM8753 devices not supported\n"); | ||
1647 | ret = -EINVAL; | ||
1648 | goto err; | ||
1649 | } | ||
1650 | |||
1651 | mutex_init(&codec->mutex); | ||
1652 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1653 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1560 | 1654 | ||
1561 | codec->name = "WM8753"; | 1655 | codec->name = "WM8753"; |
1562 | codec->owner = THIS_MODULE; | 1656 | codec->owner = THIS_MODULE; |
1563 | codec->read = wm8753_read_reg_cache; | 1657 | codec->read = wm8753_read_reg_cache; |
1564 | codec->write = wm8753_write; | 1658 | codec->write = wm8753_write; |
1659 | codec->bias_level = SND_SOC_BIAS_STANDBY; | ||
1565 | codec->set_bias_level = wm8753_set_bias_level; | 1660 | codec->set_bias_level = wm8753_set_bias_level; |
1566 | codec->dai = wm8753_dai; | 1661 | codec->dai = wm8753_dai; |
1567 | codec->num_dai = 2; | 1662 | codec->num_dai = 2; |
1568 | codec->reg_cache_size = ARRAY_SIZE(wm8753_reg); | 1663 | codec->reg_cache_size = ARRAY_SIZE(wm8753->reg_cache); |
1569 | codec->reg_cache = kmemdup(wm8753_reg, sizeof(wm8753_reg), GFP_KERNEL); | 1664 | codec->reg_cache = &wm8753->reg_cache; |
1570 | 1665 | codec->private_data = wm8753; | |
1571 | if (codec->reg_cache == NULL) | ||
1572 | return -ENOMEM; | ||
1573 | |||
1574 | wm8753_set_dai_mode(codec, 0); | ||
1575 | 1666 | ||
1576 | wm8753_reset(codec); | 1667 | memcpy(codec->reg_cache, wm8753_reg, sizeof(codec->reg_cache)); |
1668 | INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work); | ||
1577 | 1669 | ||
1578 | /* register pcms */ | 1670 | ret = wm8753_reset(codec); |
1579 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
1580 | if (ret < 0) { | 1671 | if (ret < 0) { |
1581 | printk(KERN_ERR "wm8753: failed to create pcms\n"); | 1672 | dev_err(codec->dev, "Failed to issue reset\n"); |
1582 | goto pcm_err; | 1673 | goto err; |
1583 | } | 1674 | } |
1584 | 1675 | ||
1585 | /* charge output caps */ | 1676 | /* charge output caps */ |
1586 | wm8753_set_bias_level(codec, SND_SOC_BIAS_PREPARE); | 1677 | wm8753_set_bias_level(codec, SND_SOC_BIAS_PREPARE); |
1587 | codec->bias_level = SND_SOC_BIAS_STANDBY; | ||
1588 | schedule_delayed_work(&codec->delayed_work, | 1678 | schedule_delayed_work(&codec->delayed_work, |
1589 | msecs_to_jiffies(caps_charge)); | 1679 | msecs_to_jiffies(caps_charge)); |
1590 | 1680 | ||
1591 | /* set the update bits */ | 1681 | /* set the update bits */ |
1592 | reg = wm8753_read_reg_cache(codec, WM8753_LDAC); | 1682 | reg = wm8753_read_reg_cache(codec, WM8753_LDAC); |
@@ -1610,59 +1700,70 @@ static int wm8753_init(struct snd_soc_device *socdev) | |||
1610 | reg = wm8753_read_reg_cache(codec, WM8753_RINVOL); | 1700 | reg = wm8753_read_reg_cache(codec, WM8753_RINVOL); |
1611 | wm8753_write(codec, WM8753_RINVOL, reg | 0x0100); | 1701 | wm8753_write(codec, WM8753_RINVOL, reg | 0x0100); |
1612 | 1702 | ||
1613 | wm8753_add_controls(codec); | 1703 | wm8753_codec = codec; |
1614 | wm8753_add_widgets(codec); | 1704 | |
1615 | ret = snd_soc_init_card(socdev); | 1705 | for (i = 0; i < ARRAY_SIZE(wm8753_dai); i++) |
1616 | if (ret < 0) { | 1706 | wm8753_dai[i].dev = codec->dev; |
1617 | printk(KERN_ERR "wm8753: failed to register card\n"); | 1707 | |
1618 | goto card_err; | 1708 | ret = snd_soc_register_codec(codec); |
1709 | if (ret != 0) { | ||
1710 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
1711 | goto err; | ||
1619 | } | 1712 | } |
1620 | 1713 | ||
1621 | return ret; | 1714 | ret = snd_soc_register_dais(&wm8753_dai[0], ARRAY_SIZE(wm8753_dai)); |
1715 | if (ret != 0) { | ||
1716 | dev_err(codec->dev, "Failed to register DAIs: %d\n", ret); | ||
1717 | goto err_codec; | ||
1718 | } | ||
1622 | 1719 | ||
1623 | card_err: | 1720 | return 0; |
1624 | snd_soc_free_pcms(socdev); | 1721 | |
1625 | snd_soc_dapm_free(socdev); | 1722 | err_codec: |
1626 | pcm_err: | 1723 | run_delayed_work(&codec->delayed_work); |
1627 | kfree(codec->reg_cache); | 1724 | snd_soc_unregister_codec(codec); |
1725 | err: | ||
1726 | kfree(wm8753); | ||
1628 | return ret; | 1727 | return ret; |
1629 | } | 1728 | } |
1630 | 1729 | ||
1631 | /* If the i2c layer weren't so broken, we could pass this kind of data | 1730 | static void wm8753_unregister(struct wm8753_priv *wm8753) |
1632 | around */ | 1731 | { |
1633 | static struct snd_soc_device *wm8753_socdev; | 1732 | wm8753_set_bias_level(&wm8753->codec, SND_SOC_BIAS_OFF); |
1733 | run_delayed_work(&wm8753->codec.delayed_work); | ||
1734 | snd_soc_unregister_dais(&wm8753_dai[0], ARRAY_SIZE(wm8753_dai)); | ||
1735 | snd_soc_unregister_codec(&wm8753->codec); | ||
1736 | kfree(wm8753); | ||
1737 | wm8753_codec = NULL; | ||
1738 | } | ||
1634 | 1739 | ||
1635 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1740 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
1636 | 1741 | ||
1637 | /* | ||
1638 | * WM8753 2 wire address is determined by GPIO5 | ||
1639 | * state during powerup. | ||
1640 | * low = 0x1a | ||
1641 | * high = 0x1b | ||
1642 | */ | ||
1643 | |||
1644 | static int wm8753_i2c_probe(struct i2c_client *i2c, | 1742 | static int wm8753_i2c_probe(struct i2c_client *i2c, |
1645 | const struct i2c_device_id *id) | 1743 | const struct i2c_device_id *id) |
1646 | { | 1744 | { |
1647 | struct snd_soc_device *socdev = wm8753_socdev; | 1745 | struct snd_soc_codec *codec; |
1648 | struct snd_soc_codec *codec = socdev->codec; | 1746 | struct wm8753_priv *wm8753; |
1649 | int ret; | ||
1650 | 1747 | ||
1651 | i2c_set_clientdata(i2c, codec); | 1748 | wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL); |
1652 | codec->control_data = i2c; | 1749 | if (wm8753 == NULL) |
1750 | return -ENOMEM; | ||
1653 | 1751 | ||
1654 | ret = wm8753_init(socdev); | 1752 | codec = &wm8753->codec; |
1655 | if (ret < 0) | 1753 | codec->hw_write = (hw_write_t)i2c_master_send; |
1656 | pr_err("failed to initialise WM8753\n"); | 1754 | codec->control_data = i2c; |
1755 | i2c_set_clientdata(i2c, wm8753); | ||
1657 | 1756 | ||
1658 | return ret; | 1757 | codec->dev = &i2c->dev; |
1758 | |||
1759 | return wm8753_register(wm8753); | ||
1659 | } | 1760 | } |
1660 | 1761 | ||
1661 | static int wm8753_i2c_remove(struct i2c_client *client) | 1762 | static int wm8753_i2c_remove(struct i2c_client *client) |
1662 | { | 1763 | { |
1663 | struct snd_soc_codec *codec = i2c_get_clientdata(client); | 1764 | struct wm8753_priv *wm8753 = i2c_get_clientdata(client); |
1664 | kfree(codec->reg_cache); | 1765 | wm8753_unregister(wm8753); |
1665 | return 0; | 1766 | return 0; |
1666 | } | 1767 | } |
1667 | 1768 | ||
1668 | static const struct i2c_device_id wm8753_i2c_id[] = { | 1769 | static const struct i2c_device_id wm8753_i2c_id[] = { |
@@ -1673,86 +1774,16 @@ MODULE_DEVICE_TABLE(i2c, wm8753_i2c_id); | |||
1673 | 1774 | ||
1674 | static struct i2c_driver wm8753_i2c_driver = { | 1775 | static struct i2c_driver wm8753_i2c_driver = { |
1675 | .driver = { | 1776 | .driver = { |
1676 | .name = "WM8753 I2C Codec", | 1777 | .name = "wm8753", |
1677 | .owner = THIS_MODULE, | 1778 | .owner = THIS_MODULE, |
1678 | }, | 1779 | }, |
1679 | .probe = wm8753_i2c_probe, | 1780 | .probe = wm8753_i2c_probe, |
1680 | .remove = wm8753_i2c_remove, | 1781 | .remove = wm8753_i2c_remove, |
1681 | .id_table = wm8753_i2c_id, | 1782 | .id_table = wm8753_i2c_id, |
1682 | }; | 1783 | }; |
1683 | |||
1684 | static int wm8753_add_i2c_device(struct platform_device *pdev, | ||
1685 | const struct wm8753_setup_data *setup) | ||
1686 | { | ||
1687 | struct i2c_board_info info; | ||
1688 | struct i2c_adapter *adapter; | ||
1689 | struct i2c_client *client; | ||
1690 | int ret; | ||
1691 | |||
1692 | ret = i2c_add_driver(&wm8753_i2c_driver); | ||
1693 | if (ret != 0) { | ||
1694 | dev_err(&pdev->dev, "can't add i2c driver\n"); | ||
1695 | return ret; | ||
1696 | } | ||
1697 | |||
1698 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
1699 | info.addr = setup->i2c_address; | ||
1700 | strlcpy(info.type, "wm8753", I2C_NAME_SIZE); | ||
1701 | |||
1702 | adapter = i2c_get_adapter(setup->i2c_bus); | ||
1703 | if (!adapter) { | ||
1704 | dev_err(&pdev->dev, "can't get i2c adapter %d\n", | ||
1705 | setup->i2c_bus); | ||
1706 | goto err_driver; | ||
1707 | } | ||
1708 | |||
1709 | client = i2c_new_device(adapter, &info); | ||
1710 | i2c_put_adapter(adapter); | ||
1711 | if (!client) { | ||
1712 | dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", | ||
1713 | (unsigned int)info.addr); | ||
1714 | goto err_driver; | ||
1715 | } | ||
1716 | |||
1717 | return 0; | ||
1718 | |||
1719 | err_driver: | ||
1720 | i2c_del_driver(&wm8753_i2c_driver); | ||
1721 | return -ENODEV; | ||
1722 | } | ||
1723 | #endif | 1784 | #endif |
1724 | 1785 | ||
1725 | #if defined(CONFIG_SPI_MASTER) | 1786 | #if defined(CONFIG_SPI_MASTER) |
1726 | static int __devinit wm8753_spi_probe(struct spi_device *spi) | ||
1727 | { | ||
1728 | struct snd_soc_device *socdev = wm8753_socdev; | ||
1729 | struct snd_soc_codec *codec = socdev->codec; | ||
1730 | int ret; | ||
1731 | |||
1732 | codec->control_data = spi; | ||
1733 | |||
1734 | ret = wm8753_init(socdev); | ||
1735 | if (ret < 0) | ||
1736 | dev_err(&spi->dev, "failed to initialise WM8753\n"); | ||
1737 | |||
1738 | return ret; | ||
1739 | } | ||
1740 | |||
1741 | static int __devexit wm8753_spi_remove(struct spi_device *spi) | ||
1742 | { | ||
1743 | return 0; | ||
1744 | } | ||
1745 | |||
1746 | static struct spi_driver wm8753_spi_driver = { | ||
1747 | .driver = { | ||
1748 | .name = "wm8753", | ||
1749 | .bus = &spi_bus_type, | ||
1750 | .owner = THIS_MODULE, | ||
1751 | }, | ||
1752 | .probe = wm8753_spi_probe, | ||
1753 | .remove = __devexit_p(wm8753_spi_remove), | ||
1754 | }; | ||
1755 | |||
1756 | static int wm8753_spi_write(struct spi_device *spi, const char *data, int len) | 1787 | static int wm8753_spi_write(struct spi_device *spi, const char *data, int len) |
1757 | { | 1788 | { |
1758 | struct spi_transfer t; | 1789 | struct spi_transfer t; |
@@ -1776,120 +1807,69 @@ static int wm8753_spi_write(struct spi_device *spi, const char *data, int len) | |||
1776 | 1807 | ||
1777 | return len; | 1808 | return len; |
1778 | } | 1809 | } |
1779 | #endif | ||
1780 | 1810 | ||
1781 | 1811 | static int __devinit wm8753_spi_probe(struct spi_device *spi) | |
1782 | static int wm8753_probe(struct platform_device *pdev) | ||
1783 | { | 1812 | { |
1784 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1785 | struct wm8753_setup_data *setup; | ||
1786 | struct snd_soc_codec *codec; | 1813 | struct snd_soc_codec *codec; |
1787 | struct wm8753_priv *wm8753; | 1814 | struct wm8753_priv *wm8753; |
1788 | int ret = 0; | ||
1789 | |||
1790 | pr_info("WM8753 Audio Codec %s", WM8753_VERSION); | ||
1791 | |||
1792 | setup = socdev->codec_data; | ||
1793 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
1794 | if (codec == NULL) | ||
1795 | return -ENOMEM; | ||
1796 | 1815 | ||
1797 | wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL); | 1816 | wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL); |
1798 | if (wm8753 == NULL) { | 1817 | if (wm8753 == NULL) |
1799 | kfree(codec); | ||
1800 | return -ENOMEM; | 1818 | return -ENOMEM; |
1801 | } | ||
1802 | 1819 | ||
1803 | codec->private_data = wm8753; | 1820 | codec = &wm8753->codec; |
1804 | socdev->codec = codec; | 1821 | codec->control_data = spi; |
1805 | mutex_init(&codec->mutex); | 1822 | codec->hw_write = (hw_write_t)wm8753_spi_write; |
1806 | INIT_LIST_HEAD(&codec->dapm_widgets); | 1823 | codec->dev = &spi->dev; |
1807 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1808 | wm8753_socdev = socdev; | ||
1809 | INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work); | ||
1810 | 1824 | ||
1811 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1825 | spi->dev.driver_data = wm8753; |
1812 | if (setup->i2c_address) { | ||
1813 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
1814 | ret = wm8753_add_i2c_device(pdev, setup); | ||
1815 | } | ||
1816 | #endif | ||
1817 | #if defined(CONFIG_SPI_MASTER) | ||
1818 | if (setup->spi) { | ||
1819 | codec->hw_write = (hw_write_t)wm8753_spi_write; | ||
1820 | ret = spi_register_driver(&wm8753_spi_driver); | ||
1821 | if (ret != 0) | ||
1822 | printk(KERN_ERR "can't add spi driver"); | ||
1823 | } | ||
1824 | #endif | ||
1825 | 1826 | ||
1826 | if (ret != 0) { | 1827 | return wm8753_register(wm8753); |
1827 | kfree(codec->private_data); | ||
1828 | kfree(codec); | ||
1829 | } | ||
1830 | return ret; | ||
1831 | } | 1828 | } |
1832 | 1829 | ||
1833 | /* | 1830 | static int __devexit wm8753_spi_remove(struct spi_device *spi) |
1834 | * This function forces any delayed work to be queued and run. | ||
1835 | */ | ||
1836 | static int run_delayed_work(struct delayed_work *dwork) | ||
1837 | { | 1831 | { |
1838 | int ret; | 1832 | struct wm8753_priv *wm8753 = spi->dev.driver_data; |
1839 | 1833 | wm8753_unregister(wm8753); | |
1840 | /* cancel any work waiting to be queued. */ | 1834 | return 0; |
1841 | ret = cancel_delayed_work(dwork); | ||
1842 | |||
1843 | /* if there was any work waiting then we run it now and | ||
1844 | * wait for it's completion */ | ||
1845 | if (ret) { | ||
1846 | schedule_delayed_work(dwork, 0); | ||
1847 | flush_scheduled_work(); | ||
1848 | } | ||
1849 | return ret; | ||
1850 | } | 1835 | } |
1851 | 1836 | ||
1852 | /* power down chip */ | 1837 | static struct spi_driver wm8753_spi_driver = { |
1853 | static int wm8753_remove(struct platform_device *pdev) | 1838 | .driver = { |
1854 | { | 1839 | .name = "wm8753", |
1855 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1840 | .bus = &spi_bus_type, |
1856 | struct snd_soc_codec *codec = socdev->codec; | 1841 | .owner = THIS_MODULE, |
1842 | }, | ||
1843 | .probe = wm8753_spi_probe, | ||
1844 | .remove = __devexit_p(wm8753_spi_remove), | ||
1845 | }; | ||
1846 | #endif | ||
1857 | 1847 | ||
1858 | if (codec->control_data) | 1848 | static int __init wm8753_modinit(void) |
1859 | wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1849 | { |
1860 | run_delayed_work(&codec->delayed_work); | 1850 | int ret; |
1861 | snd_soc_free_pcms(socdev); | ||
1862 | snd_soc_dapm_free(socdev); | ||
1863 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1851 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
1864 | i2c_unregister_device(codec->control_data); | 1852 | ret = i2c_add_driver(&wm8753_i2c_driver); |
1865 | i2c_del_driver(&wm8753_i2c_driver); | 1853 | if (ret != 0) |
1854 | pr_err("Failed to register WM8753 I2C driver: %d\n", ret); | ||
1866 | #endif | 1855 | #endif |
1867 | #if defined(CONFIG_SPI_MASTER) | 1856 | #if defined(CONFIG_SPI_MASTER) |
1868 | spi_unregister_driver(&wm8753_spi_driver); | 1857 | ret = spi_register_driver(&wm8753_spi_driver); |
1858 | if (ret != 0) | ||
1859 | pr_err("Failed to register WM8753 SPI driver: %d\n", ret); | ||
1869 | #endif | 1860 | #endif |
1870 | kfree(codec->private_data); | ||
1871 | kfree(codec); | ||
1872 | |||
1873 | return 0; | 1861 | return 0; |
1874 | } | 1862 | } |
1875 | |||
1876 | struct snd_soc_codec_device soc_codec_dev_wm8753 = { | ||
1877 | .probe = wm8753_probe, | ||
1878 | .remove = wm8753_remove, | ||
1879 | .suspend = wm8753_suspend, | ||
1880 | .resume = wm8753_resume, | ||
1881 | }; | ||
1882 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8753); | ||
1883 | |||
1884 | static int __init wm8753_modinit(void) | ||
1885 | { | ||
1886 | return snd_soc_register_dais(wm8753_dai, ARRAY_SIZE(wm8753_dai)); | ||
1887 | } | ||
1888 | module_init(wm8753_modinit); | 1863 | module_init(wm8753_modinit); |
1889 | 1864 | ||
1890 | static void __exit wm8753_exit(void) | 1865 | static void __exit wm8753_exit(void) |
1891 | { | 1866 | { |
1892 | snd_soc_unregister_dais(wm8753_dai, ARRAY_SIZE(wm8753_dai)); | 1867 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
1868 | i2c_del_driver(&wm8753_i2c_driver); | ||
1869 | #endif | ||
1870 | #if defined(CONFIG_SPI_MASTER) | ||
1871 | spi_unregister_driver(&wm8753_spi_driver); | ||
1872 | #endif | ||
1893 | } | 1873 | } |
1894 | module_exit(wm8753_exit); | 1874 | module_exit(wm8753_exit); |
1895 | 1875 | ||
diff --git a/sound/soc/codecs/wm8753.h b/sound/soc/codecs/wm8753.h index f55704ce931b..57b2ba244040 100644 --- a/sound/soc/codecs/wm8753.h +++ b/sound/soc/codecs/wm8753.h | |||
@@ -77,12 +77,6 @@ | |||
77 | #define WM8753_BIASCTL 0x3d | 77 | #define WM8753_BIASCTL 0x3d |
78 | #define WM8753_ADCTL2 0x3f | 78 | #define WM8753_ADCTL2 0x3f |
79 | 79 | ||
80 | struct wm8753_setup_data { | ||
81 | int spi; | ||
82 | int i2c_bus; | ||
83 | unsigned short i2c_address; | ||
84 | }; | ||
85 | |||
86 | #define WM8753_PLL1 0 | 80 | #define WM8753_PLL1 0 |
87 | #define WM8753_PLL2 1 | 81 | #define WM8753_PLL2 1 |
88 | 82 | ||
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index 6767de10ded0..46c5ea1ff921 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c | |||
@@ -517,22 +517,6 @@ SOC_SINGLE("LINEOUT2 LP -12dB", WM8900_REG_LOUTMIXCTL1, | |||
517 | 517 | ||
518 | }; | 518 | }; |
519 | 519 | ||
520 | /* add non dapm controls */ | ||
521 | static int wm8900_add_controls(struct snd_soc_codec *codec) | ||
522 | { | ||
523 | int err, i; | ||
524 | |||
525 | for (i = 0; i < ARRAY_SIZE(wm8900_snd_controls); i++) { | ||
526 | err = snd_ctl_add(codec->card, | ||
527 | snd_soc_cnew(&wm8900_snd_controls[i], | ||
528 | codec, NULL)); | ||
529 | if (err < 0) | ||
530 | return err; | ||
531 | } | ||
532 | |||
533 | return 0; | ||
534 | } | ||
535 | |||
536 | static const struct snd_kcontrol_new wm8900_dapm_loutput2_control = | 520 | static const struct snd_kcontrol_new wm8900_dapm_loutput2_control = |
537 | SOC_DAPM_SINGLE("LINEOUT2L Switch", WM8900_REG_POWER3, 6, 1, 0); | 521 | SOC_DAPM_SINGLE("LINEOUT2L Switch", WM8900_REG_POWER3, 6, 1, 0); |
538 | 522 | ||
@@ -736,7 +720,7 @@ static int wm8900_hw_params(struct snd_pcm_substream *substream, | |||
736 | { | 720 | { |
737 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 721 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
738 | struct snd_soc_device *socdev = rtd->socdev; | 722 | struct snd_soc_device *socdev = rtd->socdev; |
739 | struct snd_soc_codec *codec = socdev->codec; | 723 | struct snd_soc_codec *codec = socdev->card->codec; |
740 | u16 reg; | 724 | u16 reg; |
741 | 725 | ||
742 | reg = wm8900_read(codec, WM8900_REG_AUDIO1) & ~0x60; | 726 | reg = wm8900_read(codec, WM8900_REG_AUDIO1) & ~0x60; |
@@ -1104,6 +1088,14 @@ static int wm8900_digital_mute(struct snd_soc_dai *codec_dai, int mute) | |||
1104 | (SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \ | 1088 | (SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \ |
1105 | SNDRV_PCM_FORMAT_S24_LE) | 1089 | SNDRV_PCM_FORMAT_S24_LE) |
1106 | 1090 | ||
1091 | static struct snd_soc_dai_ops wm8900_dai_ops = { | ||
1092 | .hw_params = wm8900_hw_params, | ||
1093 | .set_clkdiv = wm8900_set_dai_clkdiv, | ||
1094 | .set_pll = wm8900_set_dai_pll, | ||
1095 | .set_fmt = wm8900_set_dai_fmt, | ||
1096 | .digital_mute = wm8900_digital_mute, | ||
1097 | }; | ||
1098 | |||
1107 | struct snd_soc_dai wm8900_dai = { | 1099 | struct snd_soc_dai wm8900_dai = { |
1108 | .name = "WM8900 HiFi", | 1100 | .name = "WM8900 HiFi", |
1109 | .playback = { | 1101 | .playback = { |
@@ -1120,13 +1112,7 @@ struct snd_soc_dai wm8900_dai = { | |||
1120 | .rates = WM8900_RATES, | 1112 | .rates = WM8900_RATES, |
1121 | .formats = WM8900_PCM_FORMATS, | 1113 | .formats = WM8900_PCM_FORMATS, |
1122 | }, | 1114 | }, |
1123 | .ops = { | 1115 | .ops = &wm8900_dai_ops, |
1124 | .hw_params = wm8900_hw_params, | ||
1125 | .set_clkdiv = wm8900_set_dai_clkdiv, | ||
1126 | .set_pll = wm8900_set_dai_pll, | ||
1127 | .set_fmt = wm8900_set_dai_fmt, | ||
1128 | .digital_mute = wm8900_digital_mute, | ||
1129 | }, | ||
1130 | }; | 1116 | }; |
1131 | EXPORT_SYMBOL_GPL(wm8900_dai); | 1117 | EXPORT_SYMBOL_GPL(wm8900_dai); |
1132 | 1118 | ||
@@ -1226,7 +1212,7 @@ static int wm8900_set_bias_level(struct snd_soc_codec *codec, | |||
1226 | static int wm8900_suspend(struct platform_device *pdev, pm_message_t state) | 1212 | static int wm8900_suspend(struct platform_device *pdev, pm_message_t state) |
1227 | { | 1213 | { |
1228 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1214 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
1229 | struct snd_soc_codec *codec = socdev->codec; | 1215 | struct snd_soc_codec *codec = socdev->card->codec; |
1230 | struct wm8900_priv *wm8900 = codec->private_data; | 1216 | struct wm8900_priv *wm8900 = codec->private_data; |
1231 | int fll_out = wm8900->fll_out; | 1217 | int fll_out = wm8900->fll_out; |
1232 | int fll_in = wm8900->fll_in; | 1218 | int fll_in = wm8900->fll_in; |
@@ -1250,7 +1236,7 @@ static int wm8900_suspend(struct platform_device *pdev, pm_message_t state) | |||
1250 | static int wm8900_resume(struct platform_device *pdev) | 1236 | static int wm8900_resume(struct platform_device *pdev) |
1251 | { | 1237 | { |
1252 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1238 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
1253 | struct snd_soc_codec *codec = socdev->codec; | 1239 | struct snd_soc_codec *codec = socdev->card->codec; |
1254 | struct wm8900_priv *wm8900 = codec->private_data; | 1240 | struct wm8900_priv *wm8900 = codec->private_data; |
1255 | u16 *cache; | 1241 | u16 *cache; |
1256 | int i, ret; | 1242 | int i, ret; |
@@ -1288,8 +1274,8 @@ static int wm8900_resume(struct platform_device *pdev) | |||
1288 | 1274 | ||
1289 | static struct snd_soc_codec *wm8900_codec; | 1275 | static struct snd_soc_codec *wm8900_codec; |
1290 | 1276 | ||
1291 | static int wm8900_i2c_probe(struct i2c_client *i2c, | 1277 | static __devinit int wm8900_i2c_probe(struct i2c_client *i2c, |
1292 | const struct i2c_device_id *id) | 1278 | const struct i2c_device_id *id) |
1293 | { | 1279 | { |
1294 | struct wm8900_priv *wm8900; | 1280 | struct wm8900_priv *wm8900; |
1295 | struct snd_soc_codec *codec; | 1281 | struct snd_soc_codec *codec; |
@@ -1388,7 +1374,7 @@ err: | |||
1388 | return ret; | 1374 | return ret; |
1389 | } | 1375 | } |
1390 | 1376 | ||
1391 | static int wm8900_i2c_remove(struct i2c_client *client) | 1377 | static __devexit int wm8900_i2c_remove(struct i2c_client *client) |
1392 | { | 1378 | { |
1393 | snd_soc_unregister_dai(&wm8900_dai); | 1379 | snd_soc_unregister_dai(&wm8900_dai); |
1394 | snd_soc_unregister_codec(wm8900_codec); | 1380 | snd_soc_unregister_codec(wm8900_codec); |
@@ -1414,7 +1400,7 @@ static struct i2c_driver wm8900_i2c_driver = { | |||
1414 | .owner = THIS_MODULE, | 1400 | .owner = THIS_MODULE, |
1415 | }, | 1401 | }, |
1416 | .probe = wm8900_i2c_probe, | 1402 | .probe = wm8900_i2c_probe, |
1417 | .remove = wm8900_i2c_remove, | 1403 | .remove = __devexit_p(wm8900_i2c_remove), |
1418 | .id_table = wm8900_i2c_id, | 1404 | .id_table = wm8900_i2c_id, |
1419 | }; | 1405 | }; |
1420 | 1406 | ||
@@ -1430,7 +1416,7 @@ static int wm8900_probe(struct platform_device *pdev) | |||
1430 | } | 1416 | } |
1431 | 1417 | ||
1432 | codec = wm8900_codec; | 1418 | codec = wm8900_codec; |
1433 | socdev->codec = codec; | 1419 | socdev->card->codec = codec; |
1434 | 1420 | ||
1435 | /* Register pcms */ | 1421 | /* Register pcms */ |
1436 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | 1422 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); |
@@ -1439,7 +1425,8 @@ static int wm8900_probe(struct platform_device *pdev) | |||
1439 | goto pcm_err; | 1425 | goto pcm_err; |
1440 | } | 1426 | } |
1441 | 1427 | ||
1442 | wm8900_add_controls(codec); | 1428 | snd_soc_add_controls(codec, wm8900_snd_controls, |
1429 | ARRAY_SIZE(wm8900_snd_controls)); | ||
1443 | wm8900_add_widgets(codec); | 1430 | wm8900_add_widgets(codec); |
1444 | 1431 | ||
1445 | ret = snd_soc_init_card(socdev); | 1432 | ret = snd_soc_init_card(socdev); |
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index bde74546db4a..8cf571f1a803 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c | |||
@@ -744,21 +744,6 @@ SOC_DOUBLE_R_TLV("Speaker Volume", | |||
744 | 0, 63, 0, out_tlv), | 744 | 0, 63, 0, out_tlv), |
745 | }; | 745 | }; |
746 | 746 | ||
747 | static int wm8903_add_controls(struct snd_soc_codec *codec) | ||
748 | { | ||
749 | int err, i; | ||
750 | |||
751 | for (i = 0; i < ARRAY_SIZE(wm8903_snd_controls); i++) { | ||
752 | err = snd_ctl_add(codec->card, | ||
753 | snd_soc_cnew(&wm8903_snd_controls[i], | ||
754 | codec, NULL)); | ||
755 | if (err < 0) | ||
756 | return err; | ||
757 | } | ||
758 | |||
759 | return 0; | ||
760 | } | ||
761 | |||
762 | static const struct snd_kcontrol_new linput_mode_mux = | 747 | static const struct snd_kcontrol_new linput_mode_mux = |
763 | SOC_DAPM_ENUM("Left Input Mode Mux", linput_mode_enum); | 748 | SOC_DAPM_ENUM("Left Input Mode Mux", linput_mode_enum); |
764 | 749 | ||
@@ -1276,7 +1261,7 @@ static int wm8903_startup(struct snd_pcm_substream *substream, | |||
1276 | { | 1261 | { |
1277 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1262 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1278 | struct snd_soc_device *socdev = rtd->socdev; | 1263 | struct snd_soc_device *socdev = rtd->socdev; |
1279 | struct snd_soc_codec *codec = socdev->codec; | 1264 | struct snd_soc_codec *codec = socdev->card->codec; |
1280 | struct wm8903_priv *wm8903 = codec->private_data; | 1265 | struct wm8903_priv *wm8903 = codec->private_data; |
1281 | struct i2c_client *i2c = codec->control_data; | 1266 | struct i2c_client *i2c = codec->control_data; |
1282 | struct snd_pcm_runtime *master_runtime; | 1267 | struct snd_pcm_runtime *master_runtime; |
@@ -1318,7 +1303,7 @@ static void wm8903_shutdown(struct snd_pcm_substream *substream, | |||
1318 | { | 1303 | { |
1319 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1304 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1320 | struct snd_soc_device *socdev = rtd->socdev; | 1305 | struct snd_soc_device *socdev = rtd->socdev; |
1321 | struct snd_soc_codec *codec = socdev->codec; | 1306 | struct snd_soc_codec *codec = socdev->card->codec; |
1322 | struct wm8903_priv *wm8903 = codec->private_data; | 1307 | struct wm8903_priv *wm8903 = codec->private_data; |
1323 | 1308 | ||
1324 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 1309 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
@@ -1338,7 +1323,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, | |||
1338 | { | 1323 | { |
1339 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1324 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1340 | struct snd_soc_device *socdev = rtd->socdev; | 1325 | struct snd_soc_device *socdev = rtd->socdev; |
1341 | struct snd_soc_codec *codec = socdev->codec; | 1326 | struct snd_soc_codec *codec = socdev->card->codec; |
1342 | struct wm8903_priv *wm8903 = codec->private_data; | 1327 | struct wm8903_priv *wm8903 = codec->private_data; |
1343 | struct i2c_client *i2c = codec->control_data; | 1328 | struct i2c_client *i2c = codec->control_data; |
1344 | int fs = params_rate(params); | 1329 | int fs = params_rate(params); |
@@ -1512,6 +1497,15 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, | |||
1512 | SNDRV_PCM_FMTBIT_S20_3LE |\ | 1497 | SNDRV_PCM_FMTBIT_S20_3LE |\ |
1513 | SNDRV_PCM_FMTBIT_S24_LE) | 1498 | SNDRV_PCM_FMTBIT_S24_LE) |
1514 | 1499 | ||
1500 | static struct snd_soc_dai_ops wm8903_dai_ops = { | ||
1501 | .startup = wm8903_startup, | ||
1502 | .shutdown = wm8903_shutdown, | ||
1503 | .hw_params = wm8903_hw_params, | ||
1504 | .digital_mute = wm8903_digital_mute, | ||
1505 | .set_fmt = wm8903_set_dai_fmt, | ||
1506 | .set_sysclk = wm8903_set_dai_sysclk, | ||
1507 | }; | ||
1508 | |||
1515 | struct snd_soc_dai wm8903_dai = { | 1509 | struct snd_soc_dai wm8903_dai = { |
1516 | .name = "WM8903", | 1510 | .name = "WM8903", |
1517 | .playback = { | 1511 | .playback = { |
@@ -1528,21 +1522,14 @@ struct snd_soc_dai wm8903_dai = { | |||
1528 | .rates = WM8903_CAPTURE_RATES, | 1522 | .rates = WM8903_CAPTURE_RATES, |
1529 | .formats = WM8903_FORMATS, | 1523 | .formats = WM8903_FORMATS, |
1530 | }, | 1524 | }, |
1531 | .ops = { | 1525 | .ops = &wm8903_dai_ops, |
1532 | .startup = wm8903_startup, | ||
1533 | .shutdown = wm8903_shutdown, | ||
1534 | .hw_params = wm8903_hw_params, | ||
1535 | .digital_mute = wm8903_digital_mute, | ||
1536 | .set_fmt = wm8903_set_dai_fmt, | ||
1537 | .set_sysclk = wm8903_set_dai_sysclk | ||
1538 | } | ||
1539 | }; | 1526 | }; |
1540 | EXPORT_SYMBOL_GPL(wm8903_dai); | 1527 | EXPORT_SYMBOL_GPL(wm8903_dai); |
1541 | 1528 | ||
1542 | static int wm8903_suspend(struct platform_device *pdev, pm_message_t state) | 1529 | static int wm8903_suspend(struct platform_device *pdev, pm_message_t state) |
1543 | { | 1530 | { |
1544 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1531 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
1545 | struct snd_soc_codec *codec = socdev->codec; | 1532 | struct snd_soc_codec *codec = socdev->card->codec; |
1546 | 1533 | ||
1547 | wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1534 | wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1548 | 1535 | ||
@@ -1552,7 +1539,7 @@ static int wm8903_suspend(struct platform_device *pdev, pm_message_t state) | |||
1552 | static int wm8903_resume(struct platform_device *pdev) | 1539 | static int wm8903_resume(struct platform_device *pdev) |
1553 | { | 1540 | { |
1554 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1541 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
1555 | struct snd_soc_codec *codec = socdev->codec; | 1542 | struct snd_soc_codec *codec = socdev->card->codec; |
1556 | struct i2c_client *i2c = codec->control_data; | 1543 | struct i2c_client *i2c = codec->control_data; |
1557 | int i; | 1544 | int i; |
1558 | u16 *reg_cache = codec->reg_cache; | 1545 | u16 *reg_cache = codec->reg_cache; |
@@ -1577,8 +1564,8 @@ static int wm8903_resume(struct platform_device *pdev) | |||
1577 | 1564 | ||
1578 | static struct snd_soc_codec *wm8903_codec; | 1565 | static struct snd_soc_codec *wm8903_codec; |
1579 | 1566 | ||
1580 | static int wm8903_i2c_probe(struct i2c_client *i2c, | 1567 | static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, |
1581 | const struct i2c_device_id *id) | 1568 | const struct i2c_device_id *id) |
1582 | { | 1569 | { |
1583 | struct wm8903_priv *wm8903; | 1570 | struct wm8903_priv *wm8903; |
1584 | struct snd_soc_codec *codec; | 1571 | struct snd_soc_codec *codec; |
@@ -1684,7 +1671,7 @@ err: | |||
1684 | return ret; | 1671 | return ret; |
1685 | } | 1672 | } |
1686 | 1673 | ||
1687 | static int wm8903_i2c_remove(struct i2c_client *client) | 1674 | static __devexit int wm8903_i2c_remove(struct i2c_client *client) |
1688 | { | 1675 | { |
1689 | struct snd_soc_codec *codec = i2c_get_clientdata(client); | 1676 | struct snd_soc_codec *codec = i2c_get_clientdata(client); |
1690 | 1677 | ||
@@ -1714,7 +1701,7 @@ static struct i2c_driver wm8903_i2c_driver = { | |||
1714 | .owner = THIS_MODULE, | 1701 | .owner = THIS_MODULE, |
1715 | }, | 1702 | }, |
1716 | .probe = wm8903_i2c_probe, | 1703 | .probe = wm8903_i2c_probe, |
1717 | .remove = wm8903_i2c_remove, | 1704 | .remove = __devexit_p(wm8903_i2c_remove), |
1718 | .id_table = wm8903_i2c_id, | 1705 | .id_table = wm8903_i2c_id, |
1719 | }; | 1706 | }; |
1720 | 1707 | ||
@@ -1728,7 +1715,7 @@ static int wm8903_probe(struct platform_device *pdev) | |||
1728 | goto err; | 1715 | goto err; |
1729 | } | 1716 | } |
1730 | 1717 | ||
1731 | socdev->codec = wm8903_codec; | 1718 | socdev->card->codec = wm8903_codec; |
1732 | 1719 | ||
1733 | /* register pcms */ | 1720 | /* register pcms */ |
1734 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | 1721 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); |
@@ -1737,8 +1724,9 @@ static int wm8903_probe(struct platform_device *pdev) | |||
1737 | goto err; | 1724 | goto err; |
1738 | } | 1725 | } |
1739 | 1726 | ||
1740 | wm8903_add_controls(socdev->codec); | 1727 | snd_soc_add_controls(socdev->card->codec, wm8903_snd_controls, |
1741 | wm8903_add_widgets(socdev->codec); | 1728 | ARRAY_SIZE(wm8903_snd_controls)); |
1729 | wm8903_add_widgets(socdev->card->codec); | ||
1742 | 1730 | ||
1743 | ret = snd_soc_init_card(socdev); | 1731 | ret = snd_soc_init_card(socdev); |
1744 | if (ret < 0) { | 1732 | if (ret < 0) { |
@@ -1759,7 +1747,7 @@ err: | |||
1759 | static int wm8903_remove(struct platform_device *pdev) | 1747 | static int wm8903_remove(struct platform_device *pdev) |
1760 | { | 1748 | { |
1761 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1749 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
1762 | struct snd_soc_codec *codec = socdev->codec; | 1750 | struct snd_soc_codec *codec = socdev->card->codec; |
1763 | 1751 | ||
1764 | if (codec->control_data) | 1752 | if (codec->control_data) |
1765 | wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1753 | wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); |
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index 88ead7f8dd98..032dca22dbd3 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c | |||
@@ -195,21 +195,6 @@ static const struct snd_kcontrol_new wm8971_snd_controls[] = { | |||
195 | SOC_DOUBLE_R("Mic Boost", WM8971_LADCIN, WM8971_RADCIN, 4, 3, 0), | 195 | SOC_DOUBLE_R("Mic Boost", WM8971_LADCIN, WM8971_RADCIN, 4, 3, 0), |
196 | }; | 196 | }; |
197 | 197 | ||
198 | /* add non-DAPM controls */ | ||
199 | static int wm8971_add_controls(struct snd_soc_codec *codec) | ||
200 | { | ||
201 | int err, i; | ||
202 | |||
203 | for (i = 0; i < ARRAY_SIZE(wm8971_snd_controls); i++) { | ||
204 | err = snd_ctl_add(codec->card, | ||
205 | snd_soc_cnew(&wm8971_snd_controls[i], | ||
206 | codec, NULL)); | ||
207 | if (err < 0) | ||
208 | return err; | ||
209 | } | ||
210 | return 0; | ||
211 | } | ||
212 | |||
213 | /* | 198 | /* |
214 | * DAPM Controls | 199 | * DAPM Controls |
215 | */ | 200 | */ |
@@ -546,7 +531,7 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream, | |||
546 | { | 531 | { |
547 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 532 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
548 | struct snd_soc_device *socdev = rtd->socdev; | 533 | struct snd_soc_device *socdev = rtd->socdev; |
549 | struct snd_soc_codec *codec = socdev->codec; | 534 | struct snd_soc_codec *codec = socdev->card->codec; |
550 | struct wm8971_priv *wm8971 = codec->private_data; | 535 | struct wm8971_priv *wm8971 = codec->private_data; |
551 | u16 iface = wm8971_read_reg_cache(codec, WM8971_IFACE) & 0x1f3; | 536 | u16 iface = wm8971_read_reg_cache(codec, WM8971_IFACE) & 0x1f3; |
552 | u16 srate = wm8971_read_reg_cache(codec, WM8971_SRATE) & 0x1c0; | 537 | u16 srate = wm8971_read_reg_cache(codec, WM8971_SRATE) & 0x1c0; |
@@ -619,6 +604,13 @@ static int wm8971_set_bias_level(struct snd_soc_codec *codec, | |||
619 | #define WM8971_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | 604 | #define WM8971_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ |
620 | SNDRV_PCM_FMTBIT_S24_LE) | 605 | SNDRV_PCM_FMTBIT_S24_LE) |
621 | 606 | ||
607 | static struct snd_soc_dai_ops wm8971_dai_ops = { | ||
608 | .hw_params = wm8971_pcm_hw_params, | ||
609 | .digital_mute = wm8971_mute, | ||
610 | .set_fmt = wm8971_set_dai_fmt, | ||
611 | .set_sysclk = wm8971_set_dai_sysclk, | ||
612 | }; | ||
613 | |||
622 | struct snd_soc_dai wm8971_dai = { | 614 | struct snd_soc_dai wm8971_dai = { |
623 | .name = "WM8971", | 615 | .name = "WM8971", |
624 | .playback = { | 616 | .playback = { |
@@ -633,12 +625,7 @@ struct snd_soc_dai wm8971_dai = { | |||
633 | .channels_max = 2, | 625 | .channels_max = 2, |
634 | .rates = WM8971_RATES, | 626 | .rates = WM8971_RATES, |
635 | .formats = WM8971_FORMATS,}, | 627 | .formats = WM8971_FORMATS,}, |
636 | .ops = { | 628 | .ops = &wm8971_dai_ops, |
637 | .hw_params = wm8971_pcm_hw_params, | ||
638 | .digital_mute = wm8971_mute, | ||
639 | .set_fmt = wm8971_set_dai_fmt, | ||
640 | .set_sysclk = wm8971_set_dai_sysclk, | ||
641 | }, | ||
642 | }; | 629 | }; |
643 | EXPORT_SYMBOL_GPL(wm8971_dai); | 630 | EXPORT_SYMBOL_GPL(wm8971_dai); |
644 | 631 | ||
@@ -652,7 +639,7 @@ static void wm8971_work(struct work_struct *work) | |||
652 | static int wm8971_suspend(struct platform_device *pdev, pm_message_t state) | 639 | static int wm8971_suspend(struct platform_device *pdev, pm_message_t state) |
653 | { | 640 | { |
654 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 641 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
655 | struct snd_soc_codec *codec = socdev->codec; | 642 | struct snd_soc_codec *codec = socdev->card->codec; |
656 | 643 | ||
657 | wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF); | 644 | wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF); |
658 | return 0; | 645 | return 0; |
@@ -661,7 +648,7 @@ static int wm8971_suspend(struct platform_device *pdev, pm_message_t state) | |||
661 | static int wm8971_resume(struct platform_device *pdev) | 648 | static int wm8971_resume(struct platform_device *pdev) |
662 | { | 649 | { |
663 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 650 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
664 | struct snd_soc_codec *codec = socdev->codec; | 651 | struct snd_soc_codec *codec = socdev->card->codec; |
665 | int i; | 652 | int i; |
666 | u8 data[2]; | 653 | u8 data[2]; |
667 | u16 *cache = codec->reg_cache; | 654 | u16 *cache = codec->reg_cache; |
@@ -692,7 +679,7 @@ static int wm8971_resume(struct platform_device *pdev) | |||
692 | 679 | ||
693 | static int wm8971_init(struct snd_soc_device *socdev) | 680 | static int wm8971_init(struct snd_soc_device *socdev) |
694 | { | 681 | { |
695 | struct snd_soc_codec *codec = socdev->codec; | 682 | struct snd_soc_codec *codec = socdev->card->codec; |
696 | int reg, ret = 0; | 683 | int reg, ret = 0; |
697 | 684 | ||
698 | codec->name = "WM8971"; | 685 | codec->name = "WM8971"; |
@@ -745,7 +732,8 @@ static int wm8971_init(struct snd_soc_device *socdev) | |||
745 | reg = wm8971_read_reg_cache(codec, WM8971_RINVOL); | 732 | reg = wm8971_read_reg_cache(codec, WM8971_RINVOL); |
746 | wm8971_write(codec, WM8971_RINVOL, reg | 0x0100); | 733 | wm8971_write(codec, WM8971_RINVOL, reg | 0x0100); |
747 | 734 | ||
748 | wm8971_add_controls(codec); | 735 | snd_soc_add_controls(codec, wm8971_snd_controls, |
736 | ARRAY_SIZE(wm8971_snd_controls)); | ||
749 | wm8971_add_widgets(codec); | 737 | wm8971_add_widgets(codec); |
750 | ret = snd_soc_init_card(socdev); | 738 | ret = snd_soc_init_card(socdev); |
751 | if (ret < 0) { | 739 | if (ret < 0) { |
@@ -772,7 +760,7 @@ static int wm8971_i2c_probe(struct i2c_client *i2c, | |||
772 | const struct i2c_device_id *id) | 760 | const struct i2c_device_id *id) |
773 | { | 761 | { |
774 | struct snd_soc_device *socdev = wm8971_socdev; | 762 | struct snd_soc_device *socdev = wm8971_socdev; |
775 | struct snd_soc_codec *codec = socdev->codec; | 763 | struct snd_soc_codec *codec = socdev->card->codec; |
776 | int ret; | 764 | int ret; |
777 | 765 | ||
778 | i2c_set_clientdata(i2c, codec); | 766 | i2c_set_clientdata(i2c, codec); |
@@ -873,7 +861,7 @@ static int wm8971_probe(struct platform_device *pdev) | |||
873 | } | 861 | } |
874 | 862 | ||
875 | codec->private_data = wm8971; | 863 | codec->private_data = wm8971; |
876 | socdev->codec = codec; | 864 | socdev->card->codec = codec; |
877 | mutex_init(&codec->mutex); | 865 | mutex_init(&codec->mutex); |
878 | INIT_LIST_HEAD(&codec->dapm_widgets); | 866 | INIT_LIST_HEAD(&codec->dapm_widgets); |
879 | INIT_LIST_HEAD(&codec->dapm_paths); | 867 | INIT_LIST_HEAD(&codec->dapm_paths); |
@@ -908,7 +896,7 @@ static int wm8971_probe(struct platform_device *pdev) | |||
908 | static int wm8971_remove(struct platform_device *pdev) | 896 | static int wm8971_remove(struct platform_device *pdev) |
909 | { | 897 | { |
910 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 898 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
911 | struct snd_soc_codec *codec = socdev->codec; | 899 | struct snd_soc_codec *codec = socdev->card->codec; |
912 | 900 | ||
913 | if (codec->control_data) | 901 | if (codec->control_data) |
914 | wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF); | 902 | wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF); |
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index a5731faa150c..c518c3e5aa3f 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c | |||
@@ -115,7 +115,7 @@ static inline unsigned int wm8990_read_reg_cache(struct snd_soc_codec *codec, | |||
115 | unsigned int reg) | 115 | unsigned int reg) |
116 | { | 116 | { |
117 | u16 *cache = codec->reg_cache; | 117 | u16 *cache = codec->reg_cache; |
118 | BUG_ON(reg > (ARRAY_SIZE(wm8990_reg)) - 1); | 118 | BUG_ON(reg >= ARRAY_SIZE(wm8990_reg)); |
119 | return cache[reg]; | 119 | return cache[reg]; |
120 | } | 120 | } |
121 | 121 | ||
@@ -128,7 +128,7 @@ static inline void wm8990_write_reg_cache(struct snd_soc_codec *codec, | |||
128 | u16 *cache = codec->reg_cache; | 128 | u16 *cache = codec->reg_cache; |
129 | 129 | ||
130 | /* Reset register and reserved registers are uncached */ | 130 | /* Reset register and reserved registers are uncached */ |
131 | if (reg == 0 || reg > ARRAY_SIZE(wm8990_reg) - 1) | 131 | if (reg == 0 || reg >= ARRAY_SIZE(wm8990_reg)) |
132 | return; | 132 | return; |
133 | 133 | ||
134 | cache[reg] = value; | 134 | cache[reg] = value; |
@@ -418,21 +418,6 @@ SOC_SINGLE("RIN34 Mute Switch", WM8990_RIGHT_LINE_INPUT_3_4_VOLUME, | |||
418 | 418 | ||
419 | }; | 419 | }; |
420 | 420 | ||
421 | /* add non dapm controls */ | ||
422 | static int wm8990_add_controls(struct snd_soc_codec *codec) | ||
423 | { | ||
424 | int err, i; | ||
425 | |||
426 | for (i = 0; i < ARRAY_SIZE(wm8990_snd_controls); i++) { | ||
427 | err = snd_ctl_add(codec->card, | ||
428 | snd_soc_cnew(&wm8990_snd_controls[i], codec, | ||
429 | NULL)); | ||
430 | if (err < 0) | ||
431 | return err; | ||
432 | } | ||
433 | return 0; | ||
434 | } | ||
435 | |||
436 | /* | 421 | /* |
437 | * _DAPM_ Controls | 422 | * _DAPM_ Controls |
438 | */ | 423 | */ |
@@ -1178,7 +1163,7 @@ static int wm8990_hw_params(struct snd_pcm_substream *substream, | |||
1178 | { | 1163 | { |
1179 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1164 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1180 | struct snd_soc_device *socdev = rtd->socdev; | 1165 | struct snd_soc_device *socdev = rtd->socdev; |
1181 | struct snd_soc_codec *codec = socdev->codec; | 1166 | struct snd_soc_codec *codec = socdev->card->codec; |
1182 | u16 audio1 = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_1); | 1167 | u16 audio1 = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_1); |
1183 | 1168 | ||
1184 | audio1 &= ~WM8990_AIF_WL_MASK; | 1169 | audio1 &= ~WM8990_AIF_WL_MASK; |
@@ -1347,6 +1332,15 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec, | |||
1347 | * 1. ADC/DAC on Primary Interface | 1332 | * 1. ADC/DAC on Primary Interface |
1348 | * 2. ADC on Primary Interface/DAC on secondary | 1333 | * 2. ADC on Primary Interface/DAC on secondary |
1349 | */ | 1334 | */ |
1335 | static struct snd_soc_dai_ops wm8990_dai_ops = { | ||
1336 | .hw_params = wm8990_hw_params, | ||
1337 | .digital_mute = wm8990_mute, | ||
1338 | .set_fmt = wm8990_set_dai_fmt, | ||
1339 | .set_clkdiv = wm8990_set_dai_clkdiv, | ||
1340 | .set_pll = wm8990_set_dai_pll, | ||
1341 | .set_sysclk = wm8990_set_dai_sysclk, | ||
1342 | }; | ||
1343 | |||
1350 | struct snd_soc_dai wm8990_dai = { | 1344 | struct snd_soc_dai wm8990_dai = { |
1351 | /* ADC/DAC on primary */ | 1345 | /* ADC/DAC on primary */ |
1352 | .name = "WM8990 ADC/DAC Primary", | 1346 | .name = "WM8990 ADC/DAC Primary", |
@@ -1363,21 +1357,14 @@ struct snd_soc_dai wm8990_dai = { | |||
1363 | .channels_max = 2, | 1357 | .channels_max = 2, |
1364 | .rates = WM8990_RATES, | 1358 | .rates = WM8990_RATES, |
1365 | .formats = WM8990_FORMATS,}, | 1359 | .formats = WM8990_FORMATS,}, |
1366 | .ops = { | 1360 | .ops = &wm8990_dai_ops, |
1367 | .hw_params = wm8990_hw_params, | ||
1368 | .digital_mute = wm8990_mute, | ||
1369 | .set_fmt = wm8990_set_dai_fmt, | ||
1370 | .set_clkdiv = wm8990_set_dai_clkdiv, | ||
1371 | .set_pll = wm8990_set_dai_pll, | ||
1372 | .set_sysclk = wm8990_set_dai_sysclk, | ||
1373 | }, | ||
1374 | }; | 1361 | }; |
1375 | EXPORT_SYMBOL_GPL(wm8990_dai); | 1362 | EXPORT_SYMBOL_GPL(wm8990_dai); |
1376 | 1363 | ||
1377 | static int wm8990_suspend(struct platform_device *pdev, pm_message_t state) | 1364 | static int wm8990_suspend(struct platform_device *pdev, pm_message_t state) |
1378 | { | 1365 | { |
1379 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1366 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
1380 | struct snd_soc_codec *codec = socdev->codec; | 1367 | struct snd_soc_codec *codec = socdev->card->codec; |
1381 | 1368 | ||
1382 | /* we only need to suspend if we are a valid card */ | 1369 | /* we only need to suspend if we are a valid card */ |
1383 | if (!codec->card) | 1370 | if (!codec->card) |
@@ -1390,7 +1377,7 @@ static int wm8990_suspend(struct platform_device *pdev, pm_message_t state) | |||
1390 | static int wm8990_resume(struct platform_device *pdev) | 1377 | static int wm8990_resume(struct platform_device *pdev) |
1391 | { | 1378 | { |
1392 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1379 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
1393 | struct snd_soc_codec *codec = socdev->codec; | 1380 | struct snd_soc_codec *codec = socdev->card->codec; |
1394 | int i; | 1381 | int i; |
1395 | u8 data[2]; | 1382 | u8 data[2]; |
1396 | u16 *cache = codec->reg_cache; | 1383 | u16 *cache = codec->reg_cache; |
@@ -1418,7 +1405,7 @@ static int wm8990_resume(struct platform_device *pdev) | |||
1418 | */ | 1405 | */ |
1419 | static int wm8990_init(struct snd_soc_device *socdev) | 1406 | static int wm8990_init(struct snd_soc_device *socdev) |
1420 | { | 1407 | { |
1421 | struct snd_soc_codec *codec = socdev->codec; | 1408 | struct snd_soc_codec *codec = socdev->card->codec; |
1422 | u16 reg; | 1409 | u16 reg; |
1423 | int ret = 0; | 1410 | int ret = 0; |
1424 | 1411 | ||
@@ -1461,7 +1448,8 @@ static int wm8990_init(struct snd_soc_device *socdev) | |||
1461 | wm8990_write(codec, WM8990_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8)); | 1448 | wm8990_write(codec, WM8990_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8)); |
1462 | wm8990_write(codec, WM8990_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8)); | 1449 | wm8990_write(codec, WM8990_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8)); |
1463 | 1450 | ||
1464 | wm8990_add_controls(codec); | 1451 | snd_soc_add_controls(codec, wm8990_snd_controls, |
1452 | ARRAY_SIZE(wm8990_snd_controls)); | ||
1465 | wm8990_add_widgets(codec); | 1453 | wm8990_add_widgets(codec); |
1466 | ret = snd_soc_init_card(socdev); | 1454 | ret = snd_soc_init_card(socdev); |
1467 | if (ret < 0) { | 1455 | if (ret < 0) { |
@@ -1495,7 +1483,7 @@ static int wm8990_i2c_probe(struct i2c_client *i2c, | |||
1495 | const struct i2c_device_id *id) | 1483 | const struct i2c_device_id *id) |
1496 | { | 1484 | { |
1497 | struct snd_soc_device *socdev = wm8990_socdev; | 1485 | struct snd_soc_device *socdev = wm8990_socdev; |
1498 | struct snd_soc_codec *codec = socdev->codec; | 1486 | struct snd_soc_codec *codec = socdev->card->codec; |
1499 | int ret; | 1487 | int ret; |
1500 | 1488 | ||
1501 | i2c_set_clientdata(i2c, codec); | 1489 | i2c_set_clientdata(i2c, codec); |
@@ -1594,7 +1582,7 @@ static int wm8990_probe(struct platform_device *pdev) | |||
1594 | } | 1582 | } |
1595 | 1583 | ||
1596 | codec->private_data = wm8990; | 1584 | codec->private_data = wm8990; |
1597 | socdev->codec = codec; | 1585 | socdev->card->codec = codec; |
1598 | mutex_init(&codec->mutex); | 1586 | mutex_init(&codec->mutex); |
1599 | INIT_LIST_HEAD(&codec->dapm_widgets); | 1587 | INIT_LIST_HEAD(&codec->dapm_widgets); |
1600 | INIT_LIST_HEAD(&codec->dapm_paths); | 1588 | INIT_LIST_HEAD(&codec->dapm_paths); |
@@ -1620,7 +1608,7 @@ static int wm8990_probe(struct platform_device *pdev) | |||
1620 | static int wm8990_remove(struct platform_device *pdev) | 1608 | static int wm8990_remove(struct platform_device *pdev) |
1621 | { | 1609 | { |
1622 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1610 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
1623 | struct snd_soc_codec *codec = socdev->codec; | 1611 | struct snd_soc_codec *codec = socdev->card->codec; |
1624 | 1612 | ||
1625 | if (codec->control_data) | 1613 | if (codec->control_data) |
1626 | wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1614 | wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF); |
diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c new file mode 100644 index 000000000000..3265817c5c26 --- /dev/null +++ b/sound/soc/codecs/wm9705.c | |||
@@ -0,0 +1,415 @@ | |||
1 | /* | ||
2 | * wm9705.c -- ALSA Soc WM9705 codec support | ||
3 | * | ||
4 | * Copyright 2008 Ian Molton <spyro@f2s.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; Version 2 of the License only. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/init.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/device.h> | ||
16 | #include <sound/core.h> | ||
17 | #include <sound/pcm.h> | ||
18 | #include <sound/ac97_codec.h> | ||
19 | #include <sound/initval.h> | ||
20 | #include <sound/soc.h> | ||
21 | #include <sound/soc-dapm.h> | ||
22 | |||
23 | #include "wm9705.h" | ||
24 | |||
25 | /* | ||
26 | * WM9705 register cache | ||
27 | */ | ||
28 | static const u16 wm9705_reg[] = { | ||
29 | 0x6150, 0x8000, 0x8000, 0x8000, /* 0x0 */ | ||
30 | 0x0000, 0x8000, 0x8008, 0x8008, /* 0x8 */ | ||
31 | 0x8808, 0x8808, 0x8808, 0x8808, /* 0x10 */ | ||
32 | 0x8808, 0x0000, 0x8000, 0x0000, /* 0x18 */ | ||
33 | 0x0000, 0x0000, 0x0000, 0x000f, /* 0x20 */ | ||
34 | 0x0605, 0x0000, 0xbb80, 0x0000, /* 0x28 */ | ||
35 | 0x0000, 0xbb80, 0x0000, 0x0000, /* 0x30 */ | ||
36 | 0x0000, 0x2000, 0x0000, 0x0000, /* 0x38 */ | ||
37 | 0x0000, 0x0000, 0x0000, 0x0000, /* 0x40 */ | ||
38 | 0x0000, 0x0000, 0x0000, 0x0000, /* 0x48 */ | ||
39 | 0x0000, 0x0000, 0x0000, 0x0000, /* 0x50 */ | ||
40 | 0x0000, 0x0000, 0x0000, 0x0000, /* 0x58 */ | ||
41 | 0x0000, 0x0000, 0x0000, 0x0000, /* 0x60 */ | ||
42 | 0x0000, 0x0000, 0x0000, 0x0000, /* 0x68 */ | ||
43 | 0x0000, 0x0808, 0x0000, 0x0006, /* 0x70 */ | ||
44 | 0x0000, 0x0000, 0x574d, 0x4c05, /* 0x78 */ | ||
45 | }; | ||
46 | |||
47 | static const struct snd_kcontrol_new wm9705_snd_ac97_controls[] = { | ||
48 | SOC_DOUBLE("Master Playback Volume", AC97_MASTER, 8, 0, 31, 1), | ||
49 | SOC_SINGLE("Master Playback Switch", AC97_MASTER, 15, 1, 1), | ||
50 | SOC_DOUBLE("Headphone Playback Volume", AC97_HEADPHONE, 8, 0, 31, 1), | ||
51 | SOC_SINGLE("Headphone Playback Switch", AC97_HEADPHONE, 15, 1, 1), | ||
52 | SOC_DOUBLE("PCM Playback Volume", AC97_PCM, 8, 0, 31, 1), | ||
53 | SOC_SINGLE("PCM Playback Switch", AC97_PCM, 15, 1, 1), | ||
54 | SOC_SINGLE("Mono Playback Volume", AC97_MASTER_MONO, 0, 31, 1), | ||
55 | SOC_SINGLE("Mono Playback Switch", AC97_MASTER_MONO, 15, 1, 1), | ||
56 | SOC_SINGLE("PCBeep Playback Volume", AC97_PC_BEEP, 1, 15, 1), | ||
57 | SOC_SINGLE("Phone Playback Volume", AC97_PHONE, 0, 31, 1), | ||
58 | SOC_DOUBLE("Line Playback Volume", AC97_LINE, 8, 0, 31, 1), | ||
59 | SOC_DOUBLE("CD Playback Volume", AC97_CD, 8, 0, 31, 1), | ||
60 | SOC_SINGLE("Mic Playback Volume", AC97_MIC, 0, 31, 1), | ||
61 | SOC_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 6, 1, 0), | ||
62 | SOC_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 15, 0), | ||
63 | SOC_SINGLE("Capture Switch", AC97_REC_GAIN, 15, 1, 1), | ||
64 | }; | ||
65 | |||
66 | static const char *wm9705_mic[] = {"Mic 1", "Mic 2"}; | ||
67 | static const char *wm9705_rec_sel[] = {"Mic", "CD", "NC", "NC", | ||
68 | "Line", "Stereo Mix", "Mono Mix", "Phone"}; | ||
69 | |||
70 | static const struct soc_enum wm9705_enum_mic = | ||
71 | SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 8, 2, wm9705_mic); | ||
72 | static const struct soc_enum wm9705_enum_rec_l = | ||
73 | SOC_ENUM_SINGLE(AC97_REC_SEL, 8, 8, wm9705_rec_sel); | ||
74 | static const struct soc_enum wm9705_enum_rec_r = | ||
75 | SOC_ENUM_SINGLE(AC97_REC_SEL, 0, 8, wm9705_rec_sel); | ||
76 | |||
77 | /* Headphone Mixer */ | ||
78 | static const struct snd_kcontrol_new wm9705_hp_mixer_controls[] = { | ||
79 | SOC_DAPM_SINGLE("PCBeep Playback Switch", AC97_PC_BEEP, 15, 1, 1), | ||
80 | SOC_DAPM_SINGLE("CD Playback Switch", AC97_CD, 15, 1, 1), | ||
81 | SOC_DAPM_SINGLE("Mic Playback Switch", AC97_MIC, 15, 1, 1), | ||
82 | SOC_DAPM_SINGLE("Phone Playback Switch", AC97_PHONE, 15, 1, 1), | ||
83 | SOC_DAPM_SINGLE("Line Playback Switch", AC97_LINE, 15, 1, 1), | ||
84 | }; | ||
85 | |||
86 | /* Mic source */ | ||
87 | static const struct snd_kcontrol_new wm9705_mic_src_controls = | ||
88 | SOC_DAPM_ENUM("Route", wm9705_enum_mic); | ||
89 | |||
90 | /* Capture source */ | ||
91 | static const struct snd_kcontrol_new wm9705_capture_selectl_controls = | ||
92 | SOC_DAPM_ENUM("Route", wm9705_enum_rec_l); | ||
93 | static const struct snd_kcontrol_new wm9705_capture_selectr_controls = | ||
94 | SOC_DAPM_ENUM("Route", wm9705_enum_rec_r); | ||
95 | |||
96 | /* DAPM widgets */ | ||
97 | static const struct snd_soc_dapm_widget wm9705_dapm_widgets[] = { | ||
98 | SND_SOC_DAPM_MUX("Mic Source", SND_SOC_NOPM, 0, 0, | ||
99 | &wm9705_mic_src_controls), | ||
100 | SND_SOC_DAPM_MUX("Left Capture Source", SND_SOC_NOPM, 0, 0, | ||
101 | &wm9705_capture_selectl_controls), | ||
102 | SND_SOC_DAPM_MUX("Right Capture Source", SND_SOC_NOPM, 0, 0, | ||
103 | &wm9705_capture_selectr_controls), | ||
104 | SND_SOC_DAPM_DAC("Left DAC", "Left HiFi Playback", | ||
105 | SND_SOC_NOPM, 0, 0), | ||
106 | SND_SOC_DAPM_DAC("Right DAC", "Right HiFi Playback", | ||
107 | SND_SOC_NOPM, 0, 0), | ||
108 | SND_SOC_DAPM_MIXER_NAMED_CTL("HP Mixer", SND_SOC_NOPM, 0, 0, | ||
109 | &wm9705_hp_mixer_controls[0], | ||
110 | ARRAY_SIZE(wm9705_hp_mixer_controls)), | ||
111 | SND_SOC_DAPM_MIXER("Mono Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
112 | SND_SOC_DAPM_ADC("Left ADC", "Left HiFi Capture", SND_SOC_NOPM, 0, 0), | ||
113 | SND_SOC_DAPM_ADC("Right ADC", "Right HiFi Capture", SND_SOC_NOPM, 0, 0), | ||
114 | SND_SOC_DAPM_PGA("Headphone PGA", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
115 | SND_SOC_DAPM_PGA("Speaker PGA", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
116 | SND_SOC_DAPM_PGA("Line PGA", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
117 | SND_SOC_DAPM_PGA("Line out PGA", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
118 | SND_SOC_DAPM_PGA("Mono PGA", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
119 | SND_SOC_DAPM_PGA("Phone PGA", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
120 | SND_SOC_DAPM_PGA("Mic PGA", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
121 | SND_SOC_DAPM_PGA("PCBEEP PGA", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
122 | SND_SOC_DAPM_PGA("CD PGA", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
123 | SND_SOC_DAPM_PGA("ADC PGA", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
124 | SND_SOC_DAPM_OUTPUT("HPOUTL"), | ||
125 | SND_SOC_DAPM_OUTPUT("HPOUTR"), | ||
126 | SND_SOC_DAPM_OUTPUT("LOUT"), | ||
127 | SND_SOC_DAPM_OUTPUT("ROUT"), | ||
128 | SND_SOC_DAPM_OUTPUT("MONOOUT"), | ||
129 | SND_SOC_DAPM_INPUT("PHONE"), | ||
130 | SND_SOC_DAPM_INPUT("LINEINL"), | ||
131 | SND_SOC_DAPM_INPUT("LINEINR"), | ||
132 | SND_SOC_DAPM_INPUT("CDINL"), | ||
133 | SND_SOC_DAPM_INPUT("CDINR"), | ||
134 | SND_SOC_DAPM_INPUT("PCBEEP"), | ||
135 | SND_SOC_DAPM_INPUT("MIC1"), | ||
136 | SND_SOC_DAPM_INPUT("MIC2"), | ||
137 | }; | ||
138 | |||
139 | /* Audio map | ||
140 | * WM9705 has no switches to disable the route from the inputs to the HP mixer | ||
141 | * so in order to prevent active inputs from forcing the audio outputs to be | ||
142 | * constantly enabled, we use the mutes on those inputs to simulate such | ||
143 | * controls. | ||
144 | */ | ||
145 | static const struct snd_soc_dapm_route audio_map[] = { | ||
146 | /* HP mixer */ | ||
147 | {"HP Mixer", "PCBeep Playback Switch", "PCBEEP PGA"}, | ||
148 | {"HP Mixer", "CD Playback Switch", "CD PGA"}, | ||
149 | {"HP Mixer", "Mic Playback Switch", "Mic PGA"}, | ||
150 | {"HP Mixer", "Phone Playback Switch", "Phone PGA"}, | ||
151 | {"HP Mixer", "Line Playback Switch", "Line PGA"}, | ||
152 | {"HP Mixer", NULL, "Left DAC"}, | ||
153 | {"HP Mixer", NULL, "Right DAC"}, | ||
154 | |||
155 | /* mono mixer */ | ||
156 | {"Mono Mixer", NULL, "HP Mixer"}, | ||
157 | |||
158 | /* outputs */ | ||
159 | {"Headphone PGA", NULL, "HP Mixer"}, | ||
160 | {"HPOUTL", NULL, "Headphone PGA"}, | ||
161 | {"HPOUTR", NULL, "Headphone PGA"}, | ||
162 | {"Line out PGA", NULL, "HP Mixer"}, | ||
163 | {"LOUT", NULL, "Line out PGA"}, | ||
164 | {"ROUT", NULL, "Line out PGA"}, | ||
165 | {"Mono PGA", NULL, "Mono Mixer"}, | ||
166 | {"MONOOUT", NULL, "Mono PGA"}, | ||
167 | |||
168 | /* inputs */ | ||
169 | {"CD PGA", NULL, "CDINL"}, | ||
170 | {"CD PGA", NULL, "CDINR"}, | ||
171 | {"Line PGA", NULL, "LINEINL"}, | ||
172 | {"Line PGA", NULL, "LINEINR"}, | ||
173 | {"Phone PGA", NULL, "PHONE"}, | ||
174 | {"Mic Source", "Mic 1", "MIC1"}, | ||
175 | {"Mic Source", "Mic 2", "MIC2"}, | ||
176 | {"Mic PGA", NULL, "Mic Source"}, | ||
177 | {"PCBEEP PGA", NULL, "PCBEEP"}, | ||
178 | |||
179 | /* Left capture selector */ | ||
180 | {"Left Capture Source", "Mic", "Mic Source"}, | ||
181 | {"Left Capture Source", "CD", "CDINL"}, | ||
182 | {"Left Capture Source", "Line", "LINEINL"}, | ||
183 | {"Left Capture Source", "Stereo Mix", "HP Mixer"}, | ||
184 | {"Left Capture Source", "Mono Mix", "HP Mixer"}, | ||
185 | {"Left Capture Source", "Phone", "PHONE"}, | ||
186 | |||
187 | /* Right capture source */ | ||
188 | {"Right Capture Source", "Mic", "Mic Source"}, | ||
189 | {"Right Capture Source", "CD", "CDINR"}, | ||
190 | {"Right Capture Source", "Line", "LINEINR"}, | ||
191 | {"Right Capture Source", "Stereo Mix", "HP Mixer"}, | ||
192 | {"Right Capture Source", "Mono Mix", "HP Mixer"}, | ||
193 | {"Right Capture Source", "Phone", "PHONE"}, | ||
194 | |||
195 | {"ADC PGA", NULL, "Left Capture Source"}, | ||
196 | {"ADC PGA", NULL, "Right Capture Source"}, | ||
197 | |||
198 | /* ADC's */ | ||
199 | {"Left ADC", NULL, "ADC PGA"}, | ||
200 | {"Right ADC", NULL, "ADC PGA"}, | ||
201 | }; | ||
202 | |||
203 | static int wm9705_add_widgets(struct snd_soc_codec *codec) | ||
204 | { | ||
205 | snd_soc_dapm_new_controls(codec, wm9705_dapm_widgets, | ||
206 | ARRAY_SIZE(wm9705_dapm_widgets)); | ||
207 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | ||
208 | snd_soc_dapm_new_widgets(codec); | ||
209 | |||
210 | return 0; | ||
211 | } | ||
212 | |||
213 | /* We use a register cache to enhance read performance. */ | ||
214 | static unsigned int ac97_read(struct snd_soc_codec *codec, unsigned int reg) | ||
215 | { | ||
216 | u16 *cache = codec->reg_cache; | ||
217 | |||
218 | switch (reg) { | ||
219 | case AC97_RESET: | ||
220 | case AC97_VENDOR_ID1: | ||
221 | case AC97_VENDOR_ID2: | ||
222 | return soc_ac97_ops.read(codec->ac97, reg); | ||
223 | default: | ||
224 | reg = reg >> 1; | ||
225 | |||
226 | if (reg >= (ARRAY_SIZE(wm9705_reg))) | ||
227 | return -EIO; | ||
228 | |||
229 | return cache[reg]; | ||
230 | } | ||
231 | } | ||
232 | |||
233 | static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, | ||
234 | unsigned int val) | ||
235 | { | ||
236 | u16 *cache = codec->reg_cache; | ||
237 | |||
238 | soc_ac97_ops.write(codec->ac97, reg, val); | ||
239 | reg = reg >> 1; | ||
240 | if (reg < (ARRAY_SIZE(wm9705_reg))) | ||
241 | cache[reg] = val; | ||
242 | |||
243 | return 0; | ||
244 | } | ||
245 | |||
246 | static int ac97_prepare(struct snd_pcm_substream *substream, | ||
247 | struct snd_soc_dai *dai) | ||
248 | { | ||
249 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
250 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
251 | struct snd_soc_device *socdev = rtd->socdev; | ||
252 | struct snd_soc_codec *codec = socdev->card->codec; | ||
253 | int reg; | ||
254 | u16 vra; | ||
255 | |||
256 | vra = ac97_read(codec, AC97_EXTENDED_STATUS); | ||
257 | ac97_write(codec, AC97_EXTENDED_STATUS, vra | 0x1); | ||
258 | |||
259 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
260 | reg = AC97_PCM_FRONT_DAC_RATE; | ||
261 | else | ||
262 | reg = AC97_PCM_LR_ADC_RATE; | ||
263 | |||
264 | return ac97_write(codec, reg, runtime->rate); | ||
265 | } | ||
266 | |||
267 | #define WM9705_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | \ | ||
268 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \ | ||
269 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ | ||
270 | SNDRV_PCM_RATE_48000) | ||
271 | |||
272 | static struct snd_soc_dai_ops wm9705_dai_ops = { | ||
273 | .prepare = ac97_prepare, | ||
274 | }; | ||
275 | |||
276 | struct snd_soc_dai wm9705_dai[] = { | ||
277 | { | ||
278 | .name = "AC97 HiFi", | ||
279 | .ac97_control = 1, | ||
280 | .playback = { | ||
281 | .stream_name = "HiFi Playback", | ||
282 | .channels_min = 1, | ||
283 | .channels_max = 2, | ||
284 | .rates = WM9705_AC97_RATES, | ||
285 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
286 | }, | ||
287 | .capture = { | ||
288 | .stream_name = "HiFi Capture", | ||
289 | .channels_min = 1, | ||
290 | .channels_max = 2, | ||
291 | .rates = WM9705_AC97_RATES, | ||
292 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
293 | }, | ||
294 | .ops = &wm9705_dai_ops, | ||
295 | }, | ||
296 | { | ||
297 | .name = "AC97 Aux", | ||
298 | .playback = { | ||
299 | .stream_name = "Aux Playback", | ||
300 | .channels_min = 1, | ||
301 | .channels_max = 1, | ||
302 | .rates = WM9705_AC97_RATES, | ||
303 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
304 | }, | ||
305 | } | ||
306 | }; | ||
307 | EXPORT_SYMBOL_GPL(wm9705_dai); | ||
308 | |||
309 | static int wm9705_reset(struct snd_soc_codec *codec) | ||
310 | { | ||
311 | if (soc_ac97_ops.reset) { | ||
312 | soc_ac97_ops.reset(codec->ac97); | ||
313 | if (ac97_read(codec, 0) == wm9705_reg[0]) | ||
314 | return 0; /* Success */ | ||
315 | } | ||
316 | |||
317 | return -EIO; | ||
318 | } | ||
319 | |||
320 | static int wm9705_soc_probe(struct platform_device *pdev) | ||
321 | { | ||
322 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
323 | struct snd_soc_codec *codec; | ||
324 | int ret = 0; | ||
325 | |||
326 | printk(KERN_INFO "WM9705 SoC Audio Codec\n"); | ||
327 | |||
328 | socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), | ||
329 | GFP_KERNEL); | ||
330 | if (socdev->card->codec == NULL) | ||
331 | return -ENOMEM; | ||
332 | codec = socdev->card->codec; | ||
333 | mutex_init(&codec->mutex); | ||
334 | |||
335 | codec->reg_cache = kmemdup(wm9705_reg, sizeof(wm9705_reg), GFP_KERNEL); | ||
336 | if (codec->reg_cache == NULL) { | ||
337 | ret = -ENOMEM; | ||
338 | goto cache_err; | ||
339 | } | ||
340 | codec->reg_cache_size = sizeof(wm9705_reg); | ||
341 | codec->reg_cache_step = 2; | ||
342 | |||
343 | codec->name = "WM9705"; | ||
344 | codec->owner = THIS_MODULE; | ||
345 | codec->dai = wm9705_dai; | ||
346 | codec->num_dai = ARRAY_SIZE(wm9705_dai); | ||
347 | codec->write = ac97_write; | ||
348 | codec->read = ac97_read; | ||
349 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
350 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
351 | |||
352 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); | ||
353 | if (ret < 0) { | ||
354 | printk(KERN_ERR "wm9705: failed to register AC97 codec\n"); | ||
355 | goto codec_err; | ||
356 | } | ||
357 | |||
358 | /* register pcms */ | ||
359 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
360 | if (ret < 0) | ||
361 | goto pcm_err; | ||
362 | |||
363 | ret = wm9705_reset(codec); | ||
364 | if (ret) | ||
365 | goto reset_err; | ||
366 | |||
367 | snd_soc_add_controls(codec, wm9705_snd_ac97_controls, | ||
368 | ARRAY_SIZE(wm9705_snd_ac97_controls)); | ||
369 | wm9705_add_widgets(codec); | ||
370 | |||
371 | ret = snd_soc_init_card(socdev); | ||
372 | if (ret < 0) { | ||
373 | printk(KERN_ERR "wm9705: failed to register card\n"); | ||
374 | goto pcm_err; | ||
375 | } | ||
376 | |||
377 | return 0; | ||
378 | |||
379 | reset_err: | ||
380 | snd_soc_free_pcms(socdev); | ||
381 | pcm_err: | ||
382 | snd_soc_free_ac97_codec(codec); | ||
383 | codec_err: | ||
384 | kfree(codec->reg_cache); | ||
385 | cache_err: | ||
386 | kfree(socdev->card->codec); | ||
387 | socdev->card->codec = NULL; | ||
388 | return ret; | ||
389 | } | ||
390 | |||
391 | static int wm9705_soc_remove(struct platform_device *pdev) | ||
392 | { | ||
393 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
394 | struct snd_soc_codec *codec = socdev->card->codec; | ||
395 | |||
396 | if (codec == NULL) | ||
397 | return 0; | ||
398 | |||
399 | snd_soc_dapm_free(socdev); | ||
400 | snd_soc_free_pcms(socdev); | ||
401 | snd_soc_free_ac97_codec(codec); | ||
402 | kfree(codec->reg_cache); | ||
403 | kfree(codec); | ||
404 | return 0; | ||
405 | } | ||
406 | |||
407 | struct snd_soc_codec_device soc_codec_dev_wm9705 = { | ||
408 | .probe = wm9705_soc_probe, | ||
409 | .remove = wm9705_soc_remove, | ||
410 | }; | ||
411 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm9705); | ||
412 | |||
413 | MODULE_DESCRIPTION("ASoC WM9705 driver"); | ||
414 | MODULE_AUTHOR("Ian Molton"); | ||
415 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/codecs/wm9705.h b/sound/soc/codecs/wm9705.h new file mode 100644 index 000000000000..d380f110f9e2 --- /dev/null +++ b/sound/soc/codecs/wm9705.h | |||
@@ -0,0 +1,14 @@ | |||
1 | /* | ||
2 | * wm9705.h -- WM9705 Soc Audio driver | ||
3 | */ | ||
4 | |||
5 | #ifndef _WM9705_H | ||
6 | #define _WM9705_H | ||
7 | |||
8 | #define WM9705_DAI_AC97_HIFI 0 | ||
9 | #define WM9705_DAI_AC97_AUX 1 | ||
10 | |||
11 | extern struct snd_soc_dai wm9705_dai[2]; | ||
12 | extern struct snd_soc_codec_device soc_codec_dev_wm9705; | ||
13 | |||
14 | #endif | ||
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index af83d629078a..765cf1e7369e 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c | |||
@@ -154,21 +154,6 @@ SOC_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1), | |||
154 | SOC_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 7, 1, 0), | 154 | SOC_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 7, 1, 0), |
155 | }; | 155 | }; |
156 | 156 | ||
157 | /* add non dapm controls */ | ||
158 | static int wm9712_add_controls(struct snd_soc_codec *codec) | ||
159 | { | ||
160 | int err, i; | ||
161 | |||
162 | for (i = 0; i < ARRAY_SIZE(wm9712_snd_ac97_controls); i++) { | ||
163 | err = snd_ctl_add(codec->card, | ||
164 | snd_soc_cnew(&wm9712_snd_ac97_controls[i], | ||
165 | codec, NULL)); | ||
166 | if (err < 0) | ||
167 | return err; | ||
168 | } | ||
169 | return 0; | ||
170 | } | ||
171 | |||
172 | /* We have to create a fake left and right HP mixers because | 157 | /* We have to create a fake left and right HP mixers because |
173 | * the codec only has a single control that is shared by both channels. | 158 | * the codec only has a single control that is shared by both channels. |
174 | * This makes it impossible to determine the audio path. | 159 | * This makes it impossible to determine the audio path. |
@@ -467,7 +452,7 @@ static unsigned int ac97_read(struct snd_soc_codec *codec, | |||
467 | else { | 452 | else { |
468 | reg = reg >> 1; | 453 | reg = reg >> 1; |
469 | 454 | ||
470 | if (reg > (ARRAY_SIZE(wm9712_reg))) | 455 | if (reg >= (ARRAY_SIZE(wm9712_reg))) |
471 | return -EIO; | 456 | return -EIO; |
472 | 457 | ||
473 | return cache[reg]; | 458 | return cache[reg]; |
@@ -481,7 +466,7 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, | |||
481 | 466 | ||
482 | soc_ac97_ops.write(codec->ac97, reg, val); | 467 | soc_ac97_ops.write(codec->ac97, reg, val); |
483 | reg = reg >> 1; | 468 | reg = reg >> 1; |
484 | if (reg <= (ARRAY_SIZE(wm9712_reg))) | 469 | if (reg < (ARRAY_SIZE(wm9712_reg))) |
485 | cache[reg] = val; | 470 | cache[reg] = val; |
486 | 471 | ||
487 | return 0; | 472 | return 0; |
@@ -493,7 +478,7 @@ static int ac97_prepare(struct snd_pcm_substream *substream, | |||
493 | struct snd_pcm_runtime *runtime = substream->runtime; | 478 | struct snd_pcm_runtime *runtime = substream->runtime; |
494 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 479 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
495 | struct snd_soc_device *socdev = rtd->socdev; | 480 | struct snd_soc_device *socdev = rtd->socdev; |
496 | struct snd_soc_codec *codec = socdev->codec; | 481 | struct snd_soc_codec *codec = socdev->card->codec; |
497 | int reg; | 482 | int reg; |
498 | u16 vra; | 483 | u16 vra; |
499 | 484 | ||
@@ -514,7 +499,7 @@ static int ac97_aux_prepare(struct snd_pcm_substream *substream, | |||
514 | struct snd_pcm_runtime *runtime = substream->runtime; | 499 | struct snd_pcm_runtime *runtime = substream->runtime; |
515 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 500 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
516 | struct snd_soc_device *socdev = rtd->socdev; | 501 | struct snd_soc_device *socdev = rtd->socdev; |
517 | struct snd_soc_codec *codec = socdev->codec; | 502 | struct snd_soc_codec *codec = socdev->card->codec; |
518 | u16 vra, xsle; | 503 | u16 vra, xsle; |
519 | 504 | ||
520 | vra = ac97_read(codec, AC97_EXTENDED_STATUS); | 505 | vra = ac97_read(codec, AC97_EXTENDED_STATUS); |
@@ -532,6 +517,14 @@ static int ac97_aux_prepare(struct snd_pcm_substream *substream, | |||
532 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 |\ | 517 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 |\ |
533 | SNDRV_PCM_RATE_48000) | 518 | SNDRV_PCM_RATE_48000) |
534 | 519 | ||
520 | static struct snd_soc_dai_ops wm9712_dai_ops_hifi = { | ||
521 | .prepare = ac97_prepare, | ||
522 | }; | ||
523 | |||
524 | static struct snd_soc_dai_ops wm9712_dai_ops_aux = { | ||
525 | .prepare = ac97_aux_prepare, | ||
526 | }; | ||
527 | |||
535 | struct snd_soc_dai wm9712_dai[] = { | 528 | struct snd_soc_dai wm9712_dai[] = { |
536 | { | 529 | { |
537 | .name = "AC97 HiFi", | 530 | .name = "AC97 HiFi", |
@@ -548,8 +541,7 @@ struct snd_soc_dai wm9712_dai[] = { | |||
548 | .channels_max = 2, | 541 | .channels_max = 2, |
549 | .rates = WM9712_AC97_RATES, | 542 | .rates = WM9712_AC97_RATES, |
550 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | 543 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, |
551 | .ops = { | 544 | .ops = &wm9712_dai_ops_hifi, |
552 | .prepare = ac97_prepare,}, | ||
553 | }, | 545 | }, |
554 | { | 546 | { |
555 | .name = "AC97 Aux", | 547 | .name = "AC97 Aux", |
@@ -559,8 +551,7 @@ struct snd_soc_dai wm9712_dai[] = { | |||
559 | .channels_max = 1, | 551 | .channels_max = 1, |
560 | .rates = WM9712_AC97_RATES, | 552 | .rates = WM9712_AC97_RATES, |
561 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | 553 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, |
562 | .ops = { | 554 | .ops = &wm9712_dai_ops_aux, |
563 | .prepare = ac97_aux_prepare,}, | ||
564 | } | 555 | } |
565 | }; | 556 | }; |
566 | EXPORT_SYMBOL_GPL(wm9712_dai); | 557 | EXPORT_SYMBOL_GPL(wm9712_dai); |
@@ -607,7 +598,7 @@ static int wm9712_soc_suspend(struct platform_device *pdev, | |||
607 | pm_message_t state) | 598 | pm_message_t state) |
608 | { | 599 | { |
609 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 600 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
610 | struct snd_soc_codec *codec = socdev->codec; | 601 | struct snd_soc_codec *codec = socdev->card->codec; |
611 | 602 | ||
612 | wm9712_set_bias_level(codec, SND_SOC_BIAS_OFF); | 603 | wm9712_set_bias_level(codec, SND_SOC_BIAS_OFF); |
613 | return 0; | 604 | return 0; |
@@ -616,7 +607,7 @@ static int wm9712_soc_suspend(struct platform_device *pdev, | |||
616 | static int wm9712_soc_resume(struct platform_device *pdev) | 607 | static int wm9712_soc_resume(struct platform_device *pdev) |
617 | { | 608 | { |
618 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 609 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
619 | struct snd_soc_codec *codec = socdev->codec; | 610 | struct snd_soc_codec *codec = socdev->card->codec; |
620 | int i, ret; | 611 | int i, ret; |
621 | u16 *cache = codec->reg_cache; | 612 | u16 *cache = codec->reg_cache; |
622 | 613 | ||
@@ -652,10 +643,11 @@ static int wm9712_soc_probe(struct platform_device *pdev) | |||
652 | 643 | ||
653 | printk(KERN_INFO "WM9711/WM9712 SoC Audio Codec %s\n", WM9712_VERSION); | 644 | printk(KERN_INFO "WM9711/WM9712 SoC Audio Codec %s\n", WM9712_VERSION); |
654 | 645 | ||
655 | socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | 646 | socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), |
656 | if (socdev->codec == NULL) | 647 | GFP_KERNEL); |
648 | if (socdev->card->codec == NULL) | ||
657 | return -ENOMEM; | 649 | return -ENOMEM; |
658 | codec = socdev->codec; | 650 | codec = socdev->card->codec; |
659 | mutex_init(&codec->mutex); | 651 | mutex_init(&codec->mutex); |
660 | 652 | ||
661 | codec->reg_cache = kmemdup(wm9712_reg, sizeof(wm9712_reg), GFP_KERNEL); | 653 | codec->reg_cache = kmemdup(wm9712_reg, sizeof(wm9712_reg), GFP_KERNEL); |
@@ -698,7 +690,8 @@ static int wm9712_soc_probe(struct platform_device *pdev) | |||
698 | ac97_write(codec, AC97_VIDEO, ac97_read(codec, AC97_VIDEO) | 0x3000); | 690 | ac97_write(codec, AC97_VIDEO, ac97_read(codec, AC97_VIDEO) | 0x3000); |
699 | 691 | ||
700 | wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 692 | wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
701 | wm9712_add_controls(codec); | 693 | snd_soc_add_controls(codec, wm9712_snd_ac97_controls, |
694 | ARRAY_SIZE(wm9712_snd_ac97_controls)); | ||
702 | wm9712_add_widgets(codec); | 695 | wm9712_add_widgets(codec); |
703 | ret = snd_soc_init_card(socdev); | 696 | ret = snd_soc_init_card(socdev); |
704 | if (ret < 0) { | 697 | if (ret < 0) { |
@@ -718,15 +711,15 @@ codec_err: | |||
718 | kfree(codec->reg_cache); | 711 | kfree(codec->reg_cache); |
719 | 712 | ||
720 | cache_err: | 713 | cache_err: |
721 | kfree(socdev->codec); | 714 | kfree(socdev->card->codec); |
722 | socdev->codec = NULL; | 715 | socdev->card->codec = NULL; |
723 | return ret; | 716 | return ret; |
724 | } | 717 | } |
725 | 718 | ||
726 | static int wm9712_soc_remove(struct platform_device *pdev) | 719 | static int wm9712_soc_remove(struct platform_device *pdev) |
727 | { | 720 | { |
728 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 721 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
729 | struct snd_soc_codec *codec = socdev->codec; | 722 | struct snd_soc_codec *codec = socdev->card->codec; |
730 | 723 | ||
731 | if (codec == NULL) | 724 | if (codec == NULL) |
732 | return 0; | 725 | return 0; |
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index f3ca8aaf0139..523bad077fa0 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c | |||
@@ -32,7 +32,6 @@ | |||
32 | 32 | ||
33 | struct wm9713_priv { | 33 | struct wm9713_priv { |
34 | u32 pll_in; /* PLL input frequency */ | 34 | u32 pll_in; /* PLL input frequency */ |
35 | u32 pll_out; /* PLL output frequency */ | ||
36 | }; | 35 | }; |
37 | 36 | ||
38 | static unsigned int ac97_read(struct snd_soc_codec *codec, | 37 | static unsigned int ac97_read(struct snd_soc_codec *codec, |
@@ -190,21 +189,6 @@ SOC_SINGLE("3D Lower Cut-off Switch", AC97_REC_GAIN_MIC, 4, 1, 0), | |||
190 | SOC_SINGLE("3D Depth", AC97_REC_GAIN_MIC, 0, 15, 1), | 189 | SOC_SINGLE("3D Depth", AC97_REC_GAIN_MIC, 0, 15, 1), |
191 | }; | 190 | }; |
192 | 191 | ||
193 | /* add non dapm controls */ | ||
194 | static int wm9713_add_controls(struct snd_soc_codec *codec) | ||
195 | { | ||
196 | int err, i; | ||
197 | |||
198 | for (i = 0; i < ARRAY_SIZE(wm9713_snd_ac97_controls); i++) { | ||
199 | err = snd_ctl_add(codec->card, | ||
200 | snd_soc_cnew(&wm9713_snd_ac97_controls[i], | ||
201 | codec, NULL)); | ||
202 | if (err < 0) | ||
203 | return err; | ||
204 | } | ||
205 | return 0; | ||
206 | } | ||
207 | |||
208 | /* We have to create a fake left and right HP mixers because | 192 | /* We have to create a fake left and right HP mixers because |
209 | * the codec only has a single control that is shared by both channels. | 193 | * the codec only has a single control that is shared by both channels. |
210 | * This makes it impossible to determine the audio path using the current | 194 | * This makes it impossible to determine the audio path using the current |
@@ -636,7 +620,7 @@ static unsigned int ac97_read(struct snd_soc_codec *codec, | |||
636 | else { | 620 | else { |
637 | reg = reg >> 1; | 621 | reg = reg >> 1; |
638 | 622 | ||
639 | if (reg > (ARRAY_SIZE(wm9713_reg))) | 623 | if (reg >= (ARRAY_SIZE(wm9713_reg))) |
640 | return -EIO; | 624 | return -EIO; |
641 | 625 | ||
642 | return cache[reg]; | 626 | return cache[reg]; |
@@ -650,7 +634,7 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, | |||
650 | if (reg < 0x7c) | 634 | if (reg < 0x7c) |
651 | soc_ac97_ops.write(codec->ac97, reg, val); | 635 | soc_ac97_ops.write(codec->ac97, reg, val); |
652 | reg = reg >> 1; | 636 | reg = reg >> 1; |
653 | if (reg <= (ARRAY_SIZE(wm9713_reg))) | 637 | if (reg < (ARRAY_SIZE(wm9713_reg))) |
654 | cache[reg] = val; | 638 | cache[reg] = val; |
655 | 639 | ||
656 | return 0; | 640 | return 0; |
@@ -738,13 +722,13 @@ static int wm9713_set_pll(struct snd_soc_codec *codec, | |||
738 | struct _pll_div pll_div; | 722 | struct _pll_div pll_div; |
739 | 723 | ||
740 | /* turn PLL off ? */ | 724 | /* turn PLL off ? */ |
741 | if (freq_in == 0 || freq_out == 0) { | 725 | if (freq_in == 0) { |
742 | /* disable PLL power and select ext source */ | 726 | /* disable PLL power and select ext source */ |
743 | reg = ac97_read(codec, AC97_HANDSET_RATE); | 727 | reg = ac97_read(codec, AC97_HANDSET_RATE); |
744 | ac97_write(codec, AC97_HANDSET_RATE, reg | 0x0080); | 728 | ac97_write(codec, AC97_HANDSET_RATE, reg | 0x0080); |
745 | reg = ac97_read(codec, AC97_EXTENDED_MID); | 729 | reg = ac97_read(codec, AC97_EXTENDED_MID); |
746 | ac97_write(codec, AC97_EXTENDED_MID, reg | 0x0200); | 730 | ac97_write(codec, AC97_EXTENDED_MID, reg | 0x0200); |
747 | wm9713->pll_out = 0; | 731 | wm9713->pll_in = 0; |
748 | return 0; | 732 | return 0; |
749 | } | 733 | } |
750 | 734 | ||
@@ -788,7 +772,6 @@ static int wm9713_set_pll(struct snd_soc_codec *codec, | |||
788 | ac97_write(codec, AC97_EXTENDED_MID, reg & 0xfdff); | 772 | ac97_write(codec, AC97_EXTENDED_MID, reg & 0xfdff); |
789 | reg = ac97_read(codec, AC97_HANDSET_RATE); | 773 | reg = ac97_read(codec, AC97_HANDSET_RATE); |
790 | ac97_write(codec, AC97_HANDSET_RATE, reg & 0xff7f); | 774 | ac97_write(codec, AC97_HANDSET_RATE, reg & 0xff7f); |
791 | wm9713->pll_out = freq_out; | ||
792 | wm9713->pll_in = freq_in; | 775 | wm9713->pll_in = freq_in; |
793 | 776 | ||
794 | /* wait 10ms AC97 link frames for the link to stabilise */ | 777 | /* wait 10ms AC97 link frames for the link to stabilise */ |
@@ -957,13 +940,14 @@ static void wm9713_voiceshutdown(struct snd_pcm_substream *substream, | |||
957 | struct snd_soc_dai *dai) | 940 | struct snd_soc_dai *dai) |
958 | { | 941 | { |
959 | struct snd_soc_codec *codec = dai->codec; | 942 | struct snd_soc_codec *codec = dai->codec; |
960 | u16 status; | 943 | u16 status, rate; |
961 | 944 | ||
962 | /* Gracefully shut down the voice interface. */ | 945 | /* Gracefully shut down the voice interface. */ |
963 | status = ac97_read(codec, AC97_EXTENDED_STATUS) | 0x1000; | 946 | status = ac97_read(codec, AC97_EXTENDED_STATUS) | 0x1000; |
964 | ac97_write(codec, AC97_HANDSET_RATE, 0x0280); | 947 | rate = ac97_read(codec, AC97_HANDSET_RATE) & 0xF0FF; |
948 | ac97_write(codec, AC97_HANDSET_RATE, rate | 0x0200); | ||
965 | schedule_timeout_interruptible(msecs_to_jiffies(1)); | 949 | schedule_timeout_interruptible(msecs_to_jiffies(1)); |
966 | ac97_write(codec, AC97_HANDSET_RATE, 0x0F80); | 950 | ac97_write(codec, AC97_HANDSET_RATE, rate | 0x0F00); |
967 | ac97_write(codec, AC97_EXTENDED_MID, status); | 951 | ac97_write(codec, AC97_EXTENDED_MID, status); |
968 | } | 952 | } |
969 | 953 | ||
@@ -1021,6 +1005,27 @@ static int ac97_aux_prepare(struct snd_pcm_substream *substream, | |||
1021 | (SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \ | 1005 | (SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \ |
1022 | SNDRV_PCM_FORMAT_S24_LE) | 1006 | SNDRV_PCM_FORMAT_S24_LE) |
1023 | 1007 | ||
1008 | static struct snd_soc_dai_ops wm9713_dai_ops_hifi = { | ||
1009 | .prepare = ac97_hifi_prepare, | ||
1010 | .set_clkdiv = wm9713_set_dai_clkdiv, | ||
1011 | .set_pll = wm9713_set_dai_pll, | ||
1012 | }; | ||
1013 | |||
1014 | static struct snd_soc_dai_ops wm9713_dai_ops_aux = { | ||
1015 | .prepare = ac97_aux_prepare, | ||
1016 | .set_clkdiv = wm9713_set_dai_clkdiv, | ||
1017 | .set_pll = wm9713_set_dai_pll, | ||
1018 | }; | ||
1019 | |||
1020 | static struct snd_soc_dai_ops wm9713_dai_ops_voice = { | ||
1021 | .hw_params = wm9713_pcm_hw_params, | ||
1022 | .shutdown = wm9713_voiceshutdown, | ||
1023 | .set_clkdiv = wm9713_set_dai_clkdiv, | ||
1024 | .set_pll = wm9713_set_dai_pll, | ||
1025 | .set_fmt = wm9713_set_dai_fmt, | ||
1026 | .set_tristate = wm9713_set_dai_tristate, | ||
1027 | }; | ||
1028 | |||
1024 | struct snd_soc_dai wm9713_dai[] = { | 1029 | struct snd_soc_dai wm9713_dai[] = { |
1025 | { | 1030 | { |
1026 | .name = "AC97 HiFi", | 1031 | .name = "AC97 HiFi", |
@@ -1037,10 +1042,7 @@ struct snd_soc_dai wm9713_dai[] = { | |||
1037 | .channels_max = 2, | 1042 | .channels_max = 2, |
1038 | .rates = WM9713_RATES, | 1043 | .rates = WM9713_RATES, |
1039 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | 1044 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, |
1040 | .ops = { | 1045 | .ops = &wm9713_dai_ops_hifi, |
1041 | .prepare = ac97_hifi_prepare, | ||
1042 | .set_clkdiv = wm9713_set_dai_clkdiv, | ||
1043 | .set_pll = wm9713_set_dai_pll,}, | ||
1044 | }, | 1046 | }, |
1045 | { | 1047 | { |
1046 | .name = "AC97 Aux", | 1048 | .name = "AC97 Aux", |
@@ -1050,10 +1052,7 @@ struct snd_soc_dai wm9713_dai[] = { | |||
1050 | .channels_max = 1, | 1052 | .channels_max = 1, |
1051 | .rates = WM9713_RATES, | 1053 | .rates = WM9713_RATES, |
1052 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | 1054 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, |
1053 | .ops = { | 1055 | .ops = &wm9713_dai_ops_aux, |
1054 | .prepare = ac97_aux_prepare, | ||
1055 | .set_clkdiv = wm9713_set_dai_clkdiv, | ||
1056 | .set_pll = wm9713_set_dai_pll,}, | ||
1057 | }, | 1056 | }, |
1058 | { | 1057 | { |
1059 | .name = "WM9713 Voice", | 1058 | .name = "WM9713 Voice", |
@@ -1069,14 +1068,7 @@ struct snd_soc_dai wm9713_dai[] = { | |||
1069 | .channels_max = 2, | 1068 | .channels_max = 2, |
1070 | .rates = WM9713_PCM_RATES, | 1069 | .rates = WM9713_PCM_RATES, |
1071 | .formats = WM9713_PCM_FORMATS,}, | 1070 | .formats = WM9713_PCM_FORMATS,}, |
1072 | .ops = { | 1071 | .ops = &wm9713_dai_ops_voice, |
1073 | .hw_params = wm9713_pcm_hw_params, | ||
1074 | .shutdown = wm9713_voiceshutdown, | ||
1075 | .set_clkdiv = wm9713_set_dai_clkdiv, | ||
1076 | .set_pll = wm9713_set_dai_pll, | ||
1077 | .set_fmt = wm9713_set_dai_fmt, | ||
1078 | .set_tristate = wm9713_set_dai_tristate, | ||
1079 | }, | ||
1080 | }, | 1072 | }, |
1081 | }; | 1073 | }; |
1082 | EXPORT_SYMBOL_GPL(wm9713_dai); | 1074 | EXPORT_SYMBOL_GPL(wm9713_dai); |
@@ -1132,7 +1124,7 @@ static int wm9713_soc_suspend(struct platform_device *pdev, | |||
1132 | pm_message_t state) | 1124 | pm_message_t state) |
1133 | { | 1125 | { |
1134 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1126 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
1135 | struct snd_soc_codec *codec = socdev->codec; | 1127 | struct snd_soc_codec *codec = socdev->card->codec; |
1136 | u16 reg; | 1128 | u16 reg; |
1137 | 1129 | ||
1138 | /* Disable everything except touchpanel - that will be handled | 1130 | /* Disable everything except touchpanel - that will be handled |
@@ -1150,7 +1142,7 @@ static int wm9713_soc_suspend(struct platform_device *pdev, | |||
1150 | static int wm9713_soc_resume(struct platform_device *pdev) | 1142 | static int wm9713_soc_resume(struct platform_device *pdev) |
1151 | { | 1143 | { |
1152 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1144 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
1153 | struct snd_soc_codec *codec = socdev->codec; | 1145 | struct snd_soc_codec *codec = socdev->card->codec; |
1154 | struct wm9713_priv *wm9713 = codec->private_data; | 1146 | struct wm9713_priv *wm9713 = codec->private_data; |
1155 | int i, ret; | 1147 | int i, ret; |
1156 | u16 *cache = codec->reg_cache; | 1148 | u16 *cache = codec->reg_cache; |
@@ -1164,8 +1156,8 @@ static int wm9713_soc_resume(struct platform_device *pdev) | |||
1164 | wm9713_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1156 | wm9713_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1165 | 1157 | ||
1166 | /* do we need to re-start the PLL ? */ | 1158 | /* do we need to re-start the PLL ? */ |
1167 | if (wm9713->pll_out) | 1159 | if (wm9713->pll_in) |
1168 | wm9713_set_pll(codec, 0, wm9713->pll_in, wm9713->pll_out); | 1160 | wm9713_set_pll(codec, 0, wm9713->pll_in, 0); |
1169 | 1161 | ||
1170 | /* only synchronise the codec if warm reset failed */ | 1162 | /* only synchronise the codec if warm reset failed */ |
1171 | if (ret == 0) { | 1163 | if (ret == 0) { |
@@ -1191,10 +1183,11 @@ static int wm9713_soc_probe(struct platform_device *pdev) | |||
1191 | 1183 | ||
1192 | printk(KERN_INFO "WM9713/WM9714 SoC Audio Codec %s\n", WM9713_VERSION); | 1184 | printk(KERN_INFO "WM9713/WM9714 SoC Audio Codec %s\n", WM9713_VERSION); |
1193 | 1185 | ||
1194 | socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | 1186 | socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), |
1195 | if (socdev->codec == NULL) | 1187 | GFP_KERNEL); |
1188 | if (socdev->card->codec == NULL) | ||
1196 | return -ENOMEM; | 1189 | return -ENOMEM; |
1197 | codec = socdev->codec; | 1190 | codec = socdev->card->codec; |
1198 | mutex_init(&codec->mutex); | 1191 | mutex_init(&codec->mutex); |
1199 | 1192 | ||
1200 | codec->reg_cache = kmemdup(wm9713_reg, sizeof(wm9713_reg), GFP_KERNEL); | 1193 | codec->reg_cache = kmemdup(wm9713_reg, sizeof(wm9713_reg), GFP_KERNEL); |
@@ -1245,7 +1238,8 @@ static int wm9713_soc_probe(struct platform_device *pdev) | |||
1245 | reg = ac97_read(codec, AC97_CD) & 0x7fff; | 1238 | reg = ac97_read(codec, AC97_CD) & 0x7fff; |
1246 | ac97_write(codec, AC97_CD, reg); | 1239 | ac97_write(codec, AC97_CD, reg); |
1247 | 1240 | ||
1248 | wm9713_add_controls(codec); | 1241 | snd_soc_add_controls(codec, wm9713_snd_ac97_controls, |
1242 | ARRAY_SIZE(wm9713_snd_ac97_controls)); | ||
1249 | wm9713_add_widgets(codec); | 1243 | wm9713_add_widgets(codec); |
1250 | ret = snd_soc_init_card(socdev); | 1244 | ret = snd_soc_init_card(socdev); |
1251 | if (ret < 0) | 1245 | if (ret < 0) |
@@ -1265,15 +1259,15 @@ priv_err: | |||
1265 | kfree(codec->reg_cache); | 1259 | kfree(codec->reg_cache); |
1266 | 1260 | ||
1267 | cache_err: | 1261 | cache_err: |
1268 | kfree(socdev->codec); | 1262 | kfree(socdev->card->codec); |
1269 | socdev->codec = NULL; | 1263 | socdev->card->codec = NULL; |
1270 | return ret; | 1264 | return ret; |
1271 | } | 1265 | } |
1272 | 1266 | ||
1273 | static int wm9713_soc_remove(struct platform_device *pdev) | 1267 | static int wm9713_soc_remove(struct platform_device *pdev) |
1274 | { | 1268 | { |
1275 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1269 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
1276 | struct snd_soc_codec *codec = socdev->codec; | 1270 | struct snd_soc_codec *codec = socdev->card->codec; |
1277 | 1271 | ||
1278 | if (codec == NULL) | 1272 | if (codec == NULL) |
1279 | return 0; | 1273 | return 0; |
diff --git a/sound/soc/davinci/Kconfig b/sound/soc/davinci/Kconfig index b502741692d6..bd7392c9657e 100644 --- a/sound/soc/davinci/Kconfig +++ b/sound/soc/davinci/Kconfig | |||
@@ -20,7 +20,7 @@ config SND_DAVINCI_SOC_EVM | |||
20 | 20 | ||
21 | config SND_DAVINCI_SOC_SFFSDR | 21 | config SND_DAVINCI_SOC_SFFSDR |
22 | tristate "SoC Audio support for SFFSDR" | 22 | tristate "SoC Audio support for SFFSDR" |
23 | depends on SND_DAVINCI_SOC && MACH_DAVINCI_SFFSDR | 23 | depends on SND_DAVINCI_SOC && MACH_SFFSDR |
24 | select SND_DAVINCI_SOC_I2S | 24 | select SND_DAVINCI_SOC_I2S |
25 | select SND_SOC_PCM3008 | 25 | select SND_SOC_PCM3008 |
26 | select SFFSDR_FPGA | 26 | select SFFSDR_FPGA |
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c index 54851f318568..9b90b347007c 100644 --- a/sound/soc/davinci/davinci-evm.c +++ b/sound/soc/davinci/davinci-evm.c | |||
@@ -186,7 +186,8 @@ static int __init evm_init(void) | |||
186 | 186 | ||
187 | platform_set_drvdata(evm_snd_device, &evm_snd_devdata); | 187 | platform_set_drvdata(evm_snd_device, &evm_snd_devdata); |
188 | evm_snd_devdata.dev = &evm_snd_device->dev; | 188 | evm_snd_devdata.dev = &evm_snd_device->dev; |
189 | evm_snd_device->dev.platform_data = &evm_snd_data; | 189 | platform_device_add_data(evm_snd_device, &evm_snd_data, |
190 | sizeof(evm_snd_data)); | ||
190 | 191 | ||
191 | ret = platform_device_add_resources(evm_snd_device, evm_snd_resources, | 192 | ret = platform_device_add_resources(evm_snd_device, evm_snd_resources, |
192 | ARRAY_SIZE(evm_snd_resources)); | 193 | ARRAY_SIZE(evm_snd_resources)); |
diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c index 0fee779e3c76..ffdb9439d3d8 100644 --- a/sound/soc/davinci/davinci-i2s.c +++ b/sound/soc/davinci/davinci-i2s.c | |||
@@ -499,6 +499,13 @@ static void davinci_i2s_remove(struct platform_device *pdev, | |||
499 | 499 | ||
500 | #define DAVINCI_I2S_RATES SNDRV_PCM_RATE_8000_96000 | 500 | #define DAVINCI_I2S_RATES SNDRV_PCM_RATE_8000_96000 |
501 | 501 | ||
502 | static struct snd_soc_dai_ops davinci_i2s_dai_ops = { | ||
503 | .startup = davinci_i2s_startup, | ||
504 | .trigger = davinci_i2s_trigger, | ||
505 | .hw_params = davinci_i2s_hw_params, | ||
506 | .set_fmt = davinci_i2s_set_dai_fmt, | ||
507 | }; | ||
508 | |||
502 | struct snd_soc_dai davinci_i2s_dai = { | 509 | struct snd_soc_dai davinci_i2s_dai = { |
503 | .name = "davinci-i2s", | 510 | .name = "davinci-i2s", |
504 | .id = 0, | 511 | .id = 0, |
@@ -514,12 +521,7 @@ struct snd_soc_dai davinci_i2s_dai = { | |||
514 | .channels_max = 2, | 521 | .channels_max = 2, |
515 | .rates = DAVINCI_I2S_RATES, | 522 | .rates = DAVINCI_I2S_RATES, |
516 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | 523 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, |
517 | .ops = { | 524 | .ops = &davinci_i2s_dai_ops, |
518 | .startup = davinci_i2s_startup, | ||
519 | .trigger = davinci_i2s_trigger, | ||
520 | .hw_params = davinci_i2s_hw_params, | ||
521 | .set_fmt = davinci_i2s_set_dai_fmt, | ||
522 | }, | ||
523 | }; | 525 | }; |
524 | EXPORT_SYMBOL_GPL(davinci_i2s_dai); | 526 | EXPORT_SYMBOL_GPL(davinci_i2s_dai); |
525 | 527 | ||
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c index 366049d8578c..7af3b5b3a53d 100644 --- a/sound/soc/davinci/davinci-pcm.c +++ b/sound/soc/davinci/davinci-pcm.c | |||
@@ -286,7 +286,7 @@ static int davinci_pcm_mmap(struct snd_pcm_substream *substream, | |||
286 | runtime->dma_bytes); | 286 | runtime->dma_bytes); |
287 | } | 287 | } |
288 | 288 | ||
289 | struct snd_pcm_ops davinci_pcm_ops = { | 289 | static struct snd_pcm_ops davinci_pcm_ops = { |
290 | .open = davinci_pcm_open, | 290 | .open = davinci_pcm_open, |
291 | .close = davinci_pcm_close, | 291 | .close = davinci_pcm_close, |
292 | .ioctl = snd_pcm_lib_ioctl, | 292 | .ioctl = snd_pcm_lib_ioctl, |
diff --git a/sound/soc/davinci/davinci-sffsdr.c b/sound/soc/davinci/davinci-sffsdr.c index 4935d1bcbd8d..40eccfe9e358 100644 --- a/sound/soc/davinci/davinci-sffsdr.c +++ b/sound/soc/davinci/davinci-sffsdr.c | |||
@@ -25,7 +25,9 @@ | |||
25 | 25 | ||
26 | #include <asm/dma.h> | 26 | #include <asm/dma.h> |
27 | #include <asm/mach-types.h> | 27 | #include <asm/mach-types.h> |
28 | #ifdef CONFIG_SFFSDR_FPGA | ||
28 | #include <asm/plat-sffsdr/sffsdr-fpga.h> | 29 | #include <asm/plat-sffsdr/sffsdr-fpga.h> |
30 | #endif | ||
29 | 31 | ||
30 | #include <mach/mcbsp.h> | 32 | #include <mach/mcbsp.h> |
31 | #include <mach/edma.h> | 33 | #include <mach/edma.h> |
@@ -34,31 +36,45 @@ | |||
34 | #include "davinci-pcm.h" | 36 | #include "davinci-pcm.h" |
35 | #include "davinci-i2s.h" | 37 | #include "davinci-i2s.h" |
36 | 38 | ||
39 | /* | ||
40 | * CLKX and CLKR are the inputs for the Sample Rate Generator. | ||
41 | * FSX and FSR are outputs, driven by the sample Rate Generator. | ||
42 | */ | ||
43 | #define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \ | ||
44 | SND_SOC_DAIFMT_CBM_CFS | \ | ||
45 | SND_SOC_DAIFMT_IB_NF) | ||
46 | |||
37 | static int sffsdr_hw_params(struct snd_pcm_substream *substream, | 47 | static int sffsdr_hw_params(struct snd_pcm_substream *substream, |
38 | struct snd_pcm_hw_params *params, | 48 | struct snd_pcm_hw_params *params) |
39 | struct snd_soc_dai *dai) | ||
40 | { | 49 | { |
41 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 50 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
42 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 51 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; |
43 | int fs; | 52 | int fs; |
44 | int ret = 0; | 53 | int ret = 0; |
45 | 54 | ||
46 | /* Set cpu DAI configuration: | ||
47 | * CLKX and CLKR are the inputs for the Sample Rate Generator. | ||
48 | * FSX and FSR are outputs, driven by the sample Rate Generator. */ | ||
49 | ret = snd_soc_dai_set_fmt(cpu_dai, | ||
50 | SND_SOC_DAIFMT_RIGHT_J | | ||
51 | SND_SOC_DAIFMT_CBM_CFS | | ||
52 | SND_SOC_DAIFMT_IB_NF); | ||
53 | if (ret < 0) | ||
54 | return ret; | ||
55 | |||
56 | /* Fsref can be 32000, 44100 or 48000. */ | 55 | /* Fsref can be 32000, 44100 or 48000. */ |
57 | fs = params_rate(params); | 56 | fs = params_rate(params); |
58 | 57 | ||
58 | #ifndef CONFIG_SFFSDR_FPGA | ||
59 | /* Without the FPGA module, the Fs is fixed at 44100 Hz */ | ||
60 | if (fs != 44100) { | ||
61 | pr_debug("warning: only 44.1 kHz is supported without SFFSDR FPGA module\n"); | ||
62 | return -EINVAL; | ||
63 | } | ||
64 | #endif | ||
65 | |||
66 | /* set cpu DAI configuration */ | ||
67 | ret = snd_soc_dai_set_fmt(cpu_dai, AUDIO_FORMAT); | ||
68 | if (ret < 0) | ||
69 | return ret; | ||
70 | |||
59 | pr_debug("sffsdr_hw_params: rate = %d Hz\n", fs); | 71 | pr_debug("sffsdr_hw_params: rate = %d Hz\n", fs); |
60 | 72 | ||
73 | #ifndef CONFIG_SFFSDR_FPGA | ||
74 | return 0; | ||
75 | #else | ||
61 | return sffsdr_fpga_set_codec_fs(fs); | 76 | return sffsdr_fpga_set_codec_fs(fs); |
77 | #endif | ||
62 | } | 78 | } |
63 | 79 | ||
64 | static struct snd_soc_ops sffsdr_ops = { | 80 | static struct snd_soc_ops sffsdr_ops = { |
@@ -127,7 +143,8 @@ static int __init sffsdr_init(void) | |||
127 | 143 | ||
128 | platform_set_drvdata(sffsdr_snd_device, &sffsdr_snd_devdata); | 144 | platform_set_drvdata(sffsdr_snd_device, &sffsdr_snd_devdata); |
129 | sffsdr_snd_devdata.dev = &sffsdr_snd_device->dev; | 145 | sffsdr_snd_devdata.dev = &sffsdr_snd_device->dev; |
130 | sffsdr_snd_device->dev.platform_data = &sffsdr_snd_data; | 146 | platform_device_add_data(sffsdr_snd_device, &sffsdr_snd_data, |
147 | sizeof(sffsdr_snd_data)); | ||
131 | 148 | ||
132 | ret = platform_device_add_resources(sffsdr_snd_device, | 149 | ret = platform_device_add_resources(sffsdr_snd_device, |
133 | sffsdr_snd_resources, | 150 | sffsdr_snd_resources, |
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 95c12b26fe37..9fc908283371 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig | |||
@@ -1,17 +1,18 @@ | |||
1 | config SND_SOC_OF_SIMPLE | 1 | config SND_SOC_OF_SIMPLE |
2 | tristate | 2 | tristate |
3 | 3 | ||
4 | # ASoC platform support for the Freescale MPC8610 SOC. This compiles drivers | ||
5 | # for the SSI and the Elo DMA controller. You will still need to select | ||
6 | # a platform driver and a codec driver. | ||
4 | config SND_SOC_MPC8610 | 7 | config SND_SOC_MPC8610 |
5 | bool "ALSA SoC support for the MPC8610 SOC" | 8 | tristate |
6 | depends on MPC8610_HPCD | 9 | depends on MPC8610 |
7 | default y if MPC8610 | ||
8 | help | ||
9 | Say Y if you want to add support for codecs attached to the SSI | ||
10 | device on an MPC8610. | ||
11 | 10 | ||
12 | config SND_SOC_MPC8610_HPCD | 11 | config SND_SOC_MPC8610_HPCD |
13 | bool "ALSA SoC support for the Freescale MPC8610 HPCD board" | 12 | tristate "ALSA SoC support for the Freescale MPC8610 HPCD board" |
14 | depends on SND_SOC_MPC8610 | 13 | # I2C is necessary for the CS4270 driver |
14 | depends on MPC8610_HPCD && I2C | ||
15 | select SND_SOC_MPC8610 | ||
15 | select SND_SOC_CS4270 | 16 | select SND_SOC_CS4270 |
16 | select SND_SOC_CS4270_VD33_ERRATA | 17 | select SND_SOC_CS4270_VD33_ERRATA |
17 | default y if MPC8610_HPCD | 18 | default y if MPC8610_HPCD |
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index 035da4afec34..f85134c86387 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile | |||
@@ -2,10 +2,13 @@ | |||
2 | obj-$(CONFIG_SND_SOC_OF_SIMPLE) += soc-of-simple.o | 2 | obj-$(CONFIG_SND_SOC_OF_SIMPLE) += soc-of-simple.o |
3 | 3 | ||
4 | # MPC8610 HPCD Machine Support | 4 | # MPC8610 HPCD Machine Support |
5 | obj-$(CONFIG_SND_SOC_MPC8610_HPCD) += mpc8610_hpcd.o | 5 | snd-soc-mpc8610-hpcd-objs := mpc8610_hpcd.o |
6 | obj-$(CONFIG_SND_SOC_MPC8610_HPCD) += snd-soc-mpc8610-hpcd.o | ||
6 | 7 | ||
7 | # MPC8610 Platform Support | 8 | # MPC8610 Platform Support |
8 | obj-$(CONFIG_SND_SOC_MPC8610) += fsl_ssi.o fsl_dma.o | 9 | snd-soc-fsl-ssi-objs := fsl_ssi.o |
10 | snd-soc-fsl-dma-objs := fsl_dma.o | ||
11 | obj-$(CONFIG_SND_SOC_MPC8610) += snd-soc-fsl-ssi.o snd-soc-fsl-dma.o | ||
9 | 12 | ||
10 | obj-$(CONFIG_SND_SOC_MPC5200_I2S) += mpc5200_psc_i2s.o | 13 | obj-$(CONFIG_SND_SOC_MPC5200_I2S) += mpc5200_psc_i2s.o |
11 | 14 | ||
diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c index 64993eda5679..b3eb8570cd7b 100644 --- a/sound/soc/fsl/fsl_dma.c +++ b/sound/soc/fsl/fsl_dma.c | |||
@@ -142,7 +142,8 @@ static const struct snd_pcm_hardware fsl_dma_hardware = { | |||
142 | .info = SNDRV_PCM_INFO_INTERLEAVED | | 142 | .info = SNDRV_PCM_INFO_INTERLEAVED | |
143 | SNDRV_PCM_INFO_MMAP | | 143 | SNDRV_PCM_INFO_MMAP | |
144 | SNDRV_PCM_INFO_MMAP_VALID | | 144 | SNDRV_PCM_INFO_MMAP_VALID | |
145 | SNDRV_PCM_INFO_JOINT_DUPLEX, | 145 | SNDRV_PCM_INFO_JOINT_DUPLEX | |
146 | SNDRV_PCM_INFO_PAUSE, | ||
146 | .formats = FSLDMA_PCM_FORMATS, | 147 | .formats = FSLDMA_PCM_FORMATS, |
147 | .rates = FSLDMA_PCM_RATES, | 148 | .rates = FSLDMA_PCM_RATES, |
148 | .rate_min = 5512, | 149 | .rate_min = 5512, |
@@ -464,11 +465,7 @@ static int fsl_dma_open(struct snd_pcm_substream *substream) | |||
464 | sizeof(struct fsl_dma_link_descriptor); | 465 | sizeof(struct fsl_dma_link_descriptor); |
465 | 466 | ||
466 | for (i = 0; i < NUM_DMA_LINKS; i++) { | 467 | for (i = 0; i < NUM_DMA_LINKS; i++) { |
467 | struct fsl_dma_link_descriptor *link = &dma_private->link[i]; | 468 | dma_private->link[i].next = cpu_to_be64(temp_link); |
468 | |||
469 | link->source_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP); | ||
470 | link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP); | ||
471 | link->next = cpu_to_be64(temp_link); | ||
472 | 469 | ||
473 | temp_link += sizeof(struct fsl_dma_link_descriptor); | 470 | temp_link += sizeof(struct fsl_dma_link_descriptor); |
474 | } | 471 | } |
@@ -525,79 +522,9 @@ static int fsl_dma_open(struct snd_pcm_substream *substream) | |||
525 | * This function obtains hardware parameters about the opened stream and | 522 | * This function obtains hardware parameters about the opened stream and |
526 | * programs the DMA controller accordingly. | 523 | * programs the DMA controller accordingly. |
527 | * | 524 | * |
528 | * Note that due to a quirk of the SSI's STX register, the target address | 525 | * One drawback of big-endian is that when copying integers of different |
529 | * for the DMA operations depends on the sample size. So we don't program | 526 | * sizes to a fixed-sized register, the address to which the integer must be |
530 | * the dest_addr (for playback -- source_addr for capture) fields in the | 527 | * copied is dependent on the size of the integer. |
531 | * link descriptors here. We do that in fsl_dma_prepare() | ||
532 | */ | ||
533 | static int fsl_dma_hw_params(struct snd_pcm_substream *substream, | ||
534 | struct snd_pcm_hw_params *hw_params) | ||
535 | { | ||
536 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
537 | struct fsl_dma_private *dma_private = runtime->private_data; | ||
538 | |||
539 | dma_addr_t temp_addr; /* Pointer to next period */ | ||
540 | |||
541 | unsigned int i; | ||
542 | |||
543 | /* Get all the parameters we need */ | ||
544 | size_t buffer_size = params_buffer_bytes(hw_params); | ||
545 | size_t period_size = params_period_bytes(hw_params); | ||
546 | |||
547 | /* Initialize our DMA tracking variables */ | ||
548 | dma_private->period_size = period_size; | ||
549 | dma_private->num_periods = params_periods(hw_params); | ||
550 | dma_private->dma_buf_end = dma_private->dma_buf_phys + buffer_size; | ||
551 | dma_private->dma_buf_next = dma_private->dma_buf_phys + | ||
552 | (NUM_DMA_LINKS * period_size); | ||
553 | if (dma_private->dma_buf_next >= dma_private->dma_buf_end) | ||
554 | dma_private->dma_buf_next = dma_private->dma_buf_phys; | ||
555 | |||
556 | /* | ||
557 | * The actual address in STX0 (destination for playback, source for | ||
558 | * capture) is based on the sample size, but we don't know the sample | ||
559 | * size in this function, so we'll have to adjust that later. See | ||
560 | * comments in fsl_dma_prepare(). | ||
561 | * | ||
562 | * The DMA controller does not have a cache, so the CPU does not | ||
563 | * need to tell it to flush its cache. However, the DMA | ||
564 | * controller does need to tell the CPU to flush its cache. | ||
565 | * That's what the SNOOP bit does. | ||
566 | * | ||
567 | * Also, even though the DMA controller supports 36-bit addressing, for | ||
568 | * simplicity we currently support only 32-bit addresses for the audio | ||
569 | * buffer itself. | ||
570 | */ | ||
571 | temp_addr = substream->dma_buffer.addr; | ||
572 | |||
573 | for (i = 0; i < NUM_DMA_LINKS; i++) { | ||
574 | struct fsl_dma_link_descriptor *link = &dma_private->link[i]; | ||
575 | |||
576 | link->count = cpu_to_be32(period_size); | ||
577 | |||
578 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
579 | link->source_addr = cpu_to_be32(temp_addr); | ||
580 | else | ||
581 | link->dest_addr = cpu_to_be32(temp_addr); | ||
582 | |||
583 | temp_addr += period_size; | ||
584 | } | ||
585 | |||
586 | return 0; | ||
587 | } | ||
588 | |||
589 | /** | ||
590 | * fsl_dma_prepare - prepare the DMA registers for playback. | ||
591 | * | ||
592 | * This function is called after the specifics of the audio data are known, | ||
593 | * i.e. snd_pcm_runtime is initialized. | ||
594 | * | ||
595 | * In this function, we finish programming the registers of the DMA | ||
596 | * controller that are dependent on the sample size. | ||
597 | * | ||
598 | * One of the drawbacks with big-endian is that when copying integers of | ||
599 | * different sizes to a fixed-sized register, the address to which the | ||
600 | * integer must be copied is dependent on the size of the integer. | ||
601 | * | 528 | * |
602 | * For example, if P is the address of a 32-bit register, and X is a 32-bit | 529 | * For example, if P is the address of a 32-bit register, and X is a 32-bit |
603 | * integer, then X should be copied to address P. However, if X is a 16-bit | 530 | * integer, then X should be copied to address P. However, if X is a 16-bit |
@@ -613,22 +540,58 @@ static int fsl_dma_hw_params(struct snd_pcm_substream *substream, | |||
613 | * and 8 bytes at a time). So we do not support packed 24-bit samples. | 540 | * and 8 bytes at a time). So we do not support packed 24-bit samples. |
614 | * 24-bit data must be padded to 32 bits. | 541 | * 24-bit data must be padded to 32 bits. |
615 | */ | 542 | */ |
616 | static int fsl_dma_prepare(struct snd_pcm_substream *substream) | 543 | static int fsl_dma_hw_params(struct snd_pcm_substream *substream, |
544 | struct snd_pcm_hw_params *hw_params) | ||
617 | { | 545 | { |
618 | struct snd_pcm_runtime *runtime = substream->runtime; | 546 | struct snd_pcm_runtime *runtime = substream->runtime; |
619 | struct fsl_dma_private *dma_private = runtime->private_data; | 547 | struct fsl_dma_private *dma_private = runtime->private_data; |
548 | |||
549 | /* Number of bits per sample */ | ||
550 | unsigned int sample_size = | ||
551 | snd_pcm_format_physical_width(params_format(hw_params)); | ||
552 | |||
553 | /* Number of bytes per frame */ | ||
554 | unsigned int frame_size = 2 * (sample_size / 8); | ||
555 | |||
556 | /* Bus address of SSI STX register */ | ||
557 | dma_addr_t ssi_sxx_phys = dma_private->ssi_sxx_phys; | ||
558 | |||
559 | /* Size of the DMA buffer, in bytes */ | ||
560 | size_t buffer_size = params_buffer_bytes(hw_params); | ||
561 | |||
562 | /* Number of bytes per period */ | ||
563 | size_t period_size = params_period_bytes(hw_params); | ||
564 | |||
565 | /* Pointer to next period */ | ||
566 | dma_addr_t temp_addr = substream->dma_buffer.addr; | ||
567 | |||
568 | /* Pointer to DMA controller */ | ||
620 | struct ccsr_dma_channel __iomem *dma_channel = dma_private->dma_channel; | 569 | struct ccsr_dma_channel __iomem *dma_channel = dma_private->dma_channel; |
621 | u32 mr; | 570 | |
571 | u32 mr; /* DMA Mode Register */ | ||
572 | |||
622 | unsigned int i; | 573 | unsigned int i; |
623 | dma_addr_t ssi_sxx_phys; /* Bus address of SSI STX register */ | ||
624 | unsigned int frame_size; /* Number of bytes per frame */ | ||
625 | 574 | ||
626 | ssi_sxx_phys = dma_private->ssi_sxx_phys; | 575 | /* Initialize our DMA tracking variables */ |
576 | dma_private->period_size = period_size; | ||
577 | dma_private->num_periods = params_periods(hw_params); | ||
578 | dma_private->dma_buf_end = dma_private->dma_buf_phys + buffer_size; | ||
579 | dma_private->dma_buf_next = dma_private->dma_buf_phys + | ||
580 | (NUM_DMA_LINKS * period_size); | ||
581 | |||
582 | if (dma_private->dma_buf_next >= dma_private->dma_buf_end) | ||
583 | /* This happens if the number of periods == NUM_DMA_LINKS */ | ||
584 | dma_private->dma_buf_next = dma_private->dma_buf_phys; | ||
627 | 585 | ||
628 | mr = in_be32(&dma_channel->mr) & ~(CCSR_DMA_MR_BWC_MASK | | 586 | mr = in_be32(&dma_channel->mr) & ~(CCSR_DMA_MR_BWC_MASK | |
629 | CCSR_DMA_MR_SAHTS_MASK | CCSR_DMA_MR_DAHTS_MASK); | 587 | CCSR_DMA_MR_SAHTS_MASK | CCSR_DMA_MR_DAHTS_MASK); |
630 | 588 | ||
631 | switch (runtime->sample_bits) { | 589 | /* Due to a quirk of the SSI's STX register, the target address |
590 | * for the DMA operations depends on the sample size. So we calculate | ||
591 | * that offset here. While we're at it, also tell the DMA controller | ||
592 | * how much data to transfer per sample. | ||
593 | */ | ||
594 | switch (sample_size) { | ||
632 | case 8: | 595 | case 8: |
633 | mr |= CCSR_DMA_MR_DAHTS_1 | CCSR_DMA_MR_SAHTS_1; | 596 | mr |= CCSR_DMA_MR_DAHTS_1 | CCSR_DMA_MR_SAHTS_1; |
634 | ssi_sxx_phys += 3; | 597 | ssi_sxx_phys += 3; |
@@ -641,12 +604,12 @@ static int fsl_dma_prepare(struct snd_pcm_substream *substream) | |||
641 | mr |= CCSR_DMA_MR_DAHTS_4 | CCSR_DMA_MR_SAHTS_4; | 604 | mr |= CCSR_DMA_MR_DAHTS_4 | CCSR_DMA_MR_SAHTS_4; |
642 | break; | 605 | break; |
643 | default: | 606 | default: |
607 | /* We should never get here */ | ||
644 | dev_err(substream->pcm->card->dev, | 608 | dev_err(substream->pcm->card->dev, |
645 | "unsupported sample size %u\n", runtime->sample_bits); | 609 | "unsupported sample size %u\n", sample_size); |
646 | return -EINVAL; | 610 | return -EINVAL; |
647 | } | 611 | } |
648 | 612 | ||
649 | frame_size = runtime->frame_bits / 8; | ||
650 | /* | 613 | /* |
651 | * BWC should always be a multiple of the frame size. BWC determines | 614 | * BWC should always be a multiple of the frame size. BWC determines |
652 | * how many bytes are sent/received before the DMA controller checks the | 615 | * how many bytes are sent/received before the DMA controller checks the |
@@ -655,7 +618,6 @@ static int fsl_dma_prepare(struct snd_pcm_substream *substream) | |||
655 | * capture, the receive FIFO is triggered when it contains one frame, so | 618 | * capture, the receive FIFO is triggered when it contains one frame, so |
656 | * we want to receive one frame at a time. | 619 | * we want to receive one frame at a time. |
657 | */ | 620 | */ |
658 | |||
659 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 621 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
660 | mr |= CCSR_DMA_MR_BWC(2 * frame_size); | 622 | mr |= CCSR_DMA_MR_BWC(2 * frame_size); |
661 | else | 623 | else |
@@ -663,16 +625,48 @@ static int fsl_dma_prepare(struct snd_pcm_substream *substream) | |||
663 | 625 | ||
664 | out_be32(&dma_channel->mr, mr); | 626 | out_be32(&dma_channel->mr, mr); |
665 | 627 | ||
666 | /* | ||
667 | * Program the address of the DMA transfer to/from the SSI. | ||
668 | */ | ||
669 | for (i = 0; i < NUM_DMA_LINKS; i++) { | 628 | for (i = 0; i < NUM_DMA_LINKS; i++) { |
670 | struct fsl_dma_link_descriptor *link = &dma_private->link[i]; | 629 | struct fsl_dma_link_descriptor *link = &dma_private->link[i]; |
671 | 630 | ||
672 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 631 | link->count = cpu_to_be32(period_size); |
632 | |||
633 | /* Even though the DMA controller supports 36-bit addressing, | ||
634 | * for simplicity we allow only 32-bit addresses for the audio | ||
635 | * buffer itself. This was enforced in fsl_dma_new() with the | ||
636 | * DMA mask. | ||
637 | * | ||
638 | * The snoop bit tells the DMA controller whether it should tell | ||
639 | * the ECM to snoop during a read or write to an address. For | ||
640 | * audio, we use DMA to transfer data between memory and an I/O | ||
641 | * device (the SSI's STX0 or SRX0 register). Snooping is only | ||
642 | * needed if there is a cache, so we need to snoop memory | ||
643 | * addresses only. For playback, that means we snoop the source | ||
644 | * but not the destination. For capture, we snoop the | ||
645 | * destination but not the source. | ||
646 | * | ||
647 | * Note that failing to snoop properly is unlikely to cause | ||
648 | * cache incoherency if the period size is larger than the | ||
649 | * size of L1 cache. This is because filling in one period will | ||
650 | * flush out the data for the previous period. So if you | ||
651 | * increased period_bytes_min to a large enough size, you might | ||
652 | * get more performance by not snooping, and you'll still be | ||
653 | * okay. | ||
654 | */ | ||
655 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
656 | link->source_addr = cpu_to_be32(temp_addr); | ||
657 | link->source_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP); | ||
658 | |||
673 | link->dest_addr = cpu_to_be32(ssi_sxx_phys); | 659 | link->dest_addr = cpu_to_be32(ssi_sxx_phys); |
674 | else | 660 | link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_NOSNOOP); |
661 | } else { | ||
675 | link->source_addr = cpu_to_be32(ssi_sxx_phys); | 662 | link->source_addr = cpu_to_be32(ssi_sxx_phys); |
663 | link->source_attr = cpu_to_be32(CCSR_DMA_ATR_NOSNOOP); | ||
664 | |||
665 | link->dest_addr = cpu_to_be32(temp_addr); | ||
666 | link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP); | ||
667 | } | ||
668 | |||
669 | temp_addr += period_size; | ||
676 | } | 670 | } |
677 | 671 | ||
678 | return 0; | 672 | return 0; |
@@ -808,7 +802,6 @@ static struct snd_pcm_ops fsl_dma_ops = { | |||
808 | .ioctl = snd_pcm_lib_ioctl, | 802 | .ioctl = snd_pcm_lib_ioctl, |
809 | .hw_params = fsl_dma_hw_params, | 803 | .hw_params = fsl_dma_hw_params, |
810 | .hw_free = fsl_dma_hw_free, | 804 | .hw_free = fsl_dma_hw_free, |
811 | .prepare = fsl_dma_prepare, | ||
812 | .pointer = fsl_dma_pointer, | 805 | .pointer = fsl_dma_pointer, |
813 | }; | 806 | }; |
814 | 807 | ||
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index c6d6eb71dc1d..169bca295b78 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c | |||
@@ -72,6 +72,7 @@ | |||
72 | * @dev: struct device pointer | 72 | * @dev: struct device pointer |
73 | * @playback: the number of playback streams opened | 73 | * @playback: the number of playback streams opened |
74 | * @capture: the number of capture streams opened | 74 | * @capture: the number of capture streams opened |
75 | * @asynchronous: 0=synchronous mode, 1=asynchronous mode | ||
75 | * @cpu_dai: the CPU DAI for this device | 76 | * @cpu_dai: the CPU DAI for this device |
76 | * @dev_attr: the sysfs device attribute structure | 77 | * @dev_attr: the sysfs device attribute structure |
77 | * @stats: SSI statistics | 78 | * @stats: SSI statistics |
@@ -86,6 +87,7 @@ struct fsl_ssi_private { | |||
86 | struct device *dev; | 87 | struct device *dev; |
87 | unsigned int playback; | 88 | unsigned int playback; |
88 | unsigned int capture; | 89 | unsigned int capture; |
90 | int asynchronous; | ||
89 | struct snd_soc_dai cpu_dai; | 91 | struct snd_soc_dai cpu_dai; |
90 | struct device_attribute dev_attr; | 92 | struct device_attribute dev_attr; |
91 | 93 | ||
@@ -301,9 +303,10 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, | |||
301 | * | 303 | * |
302 | * FIXME: Little-endian samples require a different shift dir | 304 | * FIXME: Little-endian samples require a different shift dir |
303 | */ | 305 | */ |
304 | clrsetbits_be32(&ssi->scr, CCSR_SSI_SCR_I2S_MODE_MASK, | 306 | clrsetbits_be32(&ssi->scr, |
305 | CCSR_SSI_SCR_TFR_CLK_DIS | | 307 | CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN, |
306 | CCSR_SSI_SCR_I2S_MODE_SLAVE | CCSR_SSI_SCR_SYN); | 308 | CCSR_SSI_SCR_TFR_CLK_DIS | CCSR_SSI_SCR_I2S_MODE_SLAVE |
309 | | (ssi_private->asynchronous ? 0 : CCSR_SSI_SCR_SYN)); | ||
307 | 310 | ||
308 | out_be32(&ssi->stcr, | 311 | out_be32(&ssi->stcr, |
309 | CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 | | 312 | CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 | |
@@ -382,10 +385,15 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, | |||
382 | SNDRV_PCM_HW_PARAM_RATE, | 385 | SNDRV_PCM_HW_PARAM_RATE, |
383 | first_runtime->rate, first_runtime->rate); | 386 | first_runtime->rate, first_runtime->rate); |
384 | 387 | ||
385 | snd_pcm_hw_constraint_minmax(substream->runtime, | 388 | /* If we're in synchronous mode, then we need to constrain |
386 | SNDRV_PCM_HW_PARAM_SAMPLE_BITS, | 389 | * the sample size as well. We don't support independent sample |
387 | first_runtime->sample_bits, | 390 | * rates in asynchronous mode. |
388 | first_runtime->sample_bits); | 391 | */ |
392 | if (!ssi_private->asynchronous) | ||
393 | snd_pcm_hw_constraint_minmax(substream->runtime, | ||
394 | SNDRV_PCM_HW_PARAM_SAMPLE_BITS, | ||
395 | first_runtime->sample_bits, | ||
396 | first_runtime->sample_bits); | ||
389 | 397 | ||
390 | ssi_private->second_stream = substream; | 398 | ssi_private->second_stream = substream; |
391 | } | 399 | } |
@@ -400,7 +408,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, | |||
400 | } | 408 | } |
401 | 409 | ||
402 | /** | 410 | /** |
403 | * fsl_ssi_prepare: prepare the SSI. | 411 | * fsl_ssi_hw_params - program the sample size |
404 | * | 412 | * |
405 | * Most of the SSI registers have been programmed in the startup function, | 413 | * Most of the SSI registers have been programmed in the startup function, |
406 | * but the word length must be programmed here. Unfortunately, programming | 414 | * but the word length must be programmed here. Unfortunately, programming |
@@ -412,23 +420,27 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, | |||
412 | * Note: The SxCCR.DC and SxCCR.PM bits are only used if the SSI is the | 420 | * Note: The SxCCR.DC and SxCCR.PM bits are only used if the SSI is the |
413 | * clock master. | 421 | * clock master. |
414 | */ | 422 | */ |
415 | static int fsl_ssi_prepare(struct snd_pcm_substream *substream, | 423 | static int fsl_ssi_hw_params(struct snd_pcm_substream *substream, |
416 | struct snd_soc_dai *dai) | 424 | struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *cpu_dai) |
417 | { | 425 | { |
418 | struct snd_pcm_runtime *runtime = substream->runtime; | 426 | struct fsl_ssi_private *ssi_private = cpu_dai->private_data; |
419 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
420 | struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data; | ||
421 | |||
422 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | ||
423 | 427 | ||
424 | if (substream == ssi_private->first_stream) { | 428 | if (substream == ssi_private->first_stream) { |
425 | u32 wl; | 429 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; |
430 | unsigned int sample_size = | ||
431 | snd_pcm_format_width(params_format(hw_params)); | ||
432 | u32 wl = CCSR_SSI_SxCCR_WL(sample_size); | ||
426 | 433 | ||
427 | /* The SSI should always be disabled at this points (SSIEN=0) */ | 434 | /* The SSI should always be disabled at this points (SSIEN=0) */ |
428 | wl = CCSR_SSI_SxCCR_WL(snd_pcm_format_width(runtime->format)); | ||
429 | 435 | ||
430 | /* In synchronous mode, the SSI uses STCCR for capture */ | 436 | /* In synchronous mode, the SSI uses STCCR for capture */ |
431 | clrsetbits_be32(&ssi->stccr, CCSR_SSI_SxCCR_WL_MASK, wl); | 437 | if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) || |
438 | !ssi_private->asynchronous) | ||
439 | clrsetbits_be32(&ssi->stccr, | ||
440 | CCSR_SSI_SxCCR_WL_MASK, wl); | ||
441 | else | ||
442 | clrsetbits_be32(&ssi->srccr, | ||
443 | CCSR_SSI_SxCCR_WL_MASK, wl); | ||
432 | } | 444 | } |
433 | 445 | ||
434 | return 0; | 446 | return 0; |
@@ -452,28 +464,33 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd, | |||
452 | 464 | ||
453 | switch (cmd) { | 465 | switch (cmd) { |
454 | case SNDRV_PCM_TRIGGER_START: | 466 | case SNDRV_PCM_TRIGGER_START: |
455 | case SNDRV_PCM_TRIGGER_RESUME: | 467 | clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN); |
456 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 468 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
457 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 469 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
458 | clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN); | ||
459 | setbits32(&ssi->scr, | 470 | setbits32(&ssi->scr, |
460 | CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE); | 471 | CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE); |
461 | } else { | 472 | } else { |
462 | clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN); | 473 | long timeout = jiffies + 10; |
474 | |||
463 | setbits32(&ssi->scr, | 475 | setbits32(&ssi->scr, |
464 | CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_RE); | 476 | CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_RE); |
465 | 477 | ||
466 | /* | 478 | /* Wait until the SSI has filled its FIFO. Without this |
467 | * I think we need this delay to allow time for the SSI | 479 | * delay, ALSA complains about overruns. When the FIFO |
468 | * to put data into its FIFO. Without it, ALSA starts | 480 | * is full, the DMA controller initiates its first |
469 | * to complain about overruns. | 481 | * transfer. Until then, however, the DMA's DAR |
482 | * register is zero, which translates to an | ||
483 | * out-of-bounds pointer. This makes ALSA think an | ||
484 | * overrun has occurred. | ||
470 | */ | 485 | */ |
471 | mdelay(1); | 486 | while (!(in_be32(&ssi->sisr) & CCSR_SSI_SISR_RFF0) && |
487 | (jiffies < timeout)); | ||
488 | if (!(in_be32(&ssi->sisr) & CCSR_SSI_SISR_RFF0)) | ||
489 | return -EIO; | ||
472 | } | 490 | } |
473 | break; | 491 | break; |
474 | 492 | ||
475 | case SNDRV_PCM_TRIGGER_STOP: | 493 | case SNDRV_PCM_TRIGGER_STOP: |
476 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
477 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 494 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
478 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 495 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
479 | clrbits32(&ssi->scr, CCSR_SSI_SCR_TE); | 496 | clrbits32(&ssi->scr, CCSR_SSI_SCR_TE); |
@@ -563,6 +580,15 @@ static int fsl_ssi_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int format) | |||
563 | /** | 580 | /** |
564 | * fsl_ssi_dai_template: template CPU DAI for the SSI | 581 | * fsl_ssi_dai_template: template CPU DAI for the SSI |
565 | */ | 582 | */ |
583 | static struct snd_soc_dai_ops fsl_ssi_dai_ops = { | ||
584 | .startup = fsl_ssi_startup, | ||
585 | .hw_params = fsl_ssi_hw_params, | ||
586 | .shutdown = fsl_ssi_shutdown, | ||
587 | .trigger = fsl_ssi_trigger, | ||
588 | .set_sysclk = fsl_ssi_set_sysclk, | ||
589 | .set_fmt = fsl_ssi_set_fmt, | ||
590 | }; | ||
591 | |||
566 | static struct snd_soc_dai fsl_ssi_dai_template = { | 592 | static struct snd_soc_dai fsl_ssi_dai_template = { |
567 | .playback = { | 593 | .playback = { |
568 | /* The SSI does not support monaural audio. */ | 594 | /* The SSI does not support monaural audio. */ |
@@ -577,14 +603,7 @@ static struct snd_soc_dai fsl_ssi_dai_template = { | |||
577 | .rates = FSLSSI_I2S_RATES, | 603 | .rates = FSLSSI_I2S_RATES, |
578 | .formats = FSLSSI_I2S_FORMATS, | 604 | .formats = FSLSSI_I2S_FORMATS, |
579 | }, | 605 | }, |
580 | .ops = { | 606 | .ops = &fsl_ssi_dai_ops, |
581 | .startup = fsl_ssi_startup, | ||
582 | .prepare = fsl_ssi_prepare, | ||
583 | .shutdown = fsl_ssi_shutdown, | ||
584 | .trigger = fsl_ssi_trigger, | ||
585 | .set_sysclk = fsl_ssi_set_sysclk, | ||
586 | .set_fmt = fsl_ssi_set_fmt, | ||
587 | }, | ||
588 | }; | 607 | }; |
589 | 608 | ||
590 | /** | 609 | /** |
@@ -654,6 +673,7 @@ struct snd_soc_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info) | |||
654 | ssi_private->ssi_phys = ssi_info->ssi_phys; | 673 | ssi_private->ssi_phys = ssi_info->ssi_phys; |
655 | ssi_private->irq = ssi_info->irq; | 674 | ssi_private->irq = ssi_info->irq; |
656 | ssi_private->dev = ssi_info->dev; | 675 | ssi_private->dev = ssi_info->dev; |
676 | ssi_private->asynchronous = ssi_info->asynchronous; | ||
657 | 677 | ||
658 | ssi_private->dev->driver_data = fsl_ssi_dai; | 678 | ssi_private->dev->driver_data = fsl_ssi_dai; |
659 | 679 | ||
@@ -704,6 +724,14 @@ void fsl_ssi_destroy_dai(struct snd_soc_dai *fsl_ssi_dai) | |||
704 | } | 724 | } |
705 | EXPORT_SYMBOL_GPL(fsl_ssi_destroy_dai); | 725 | EXPORT_SYMBOL_GPL(fsl_ssi_destroy_dai); |
706 | 726 | ||
727 | static int __init fsl_ssi_init(void) | ||
728 | { | ||
729 | printk(KERN_INFO "Freescale Synchronous Serial Interface (SSI) ASoC Driver\n"); | ||
730 | |||
731 | return 0; | ||
732 | } | ||
733 | module_init(fsl_ssi_init); | ||
734 | |||
707 | MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); | 735 | MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); |
708 | MODULE_DESCRIPTION("Freescale Synchronous Serial Interface (SSI) ASoC Driver"); | 736 | MODULE_DESCRIPTION("Freescale Synchronous Serial Interface (SSI) ASoC Driver"); |
709 | MODULE_LICENSE("GPL"); | 737 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/fsl/fsl_ssi.h b/sound/soc/fsl/fsl_ssi.h index 83b44d700e33..eade01feaab6 100644 --- a/sound/soc/fsl/fsl_ssi.h +++ b/sound/soc/fsl/fsl_ssi.h | |||
@@ -208,6 +208,7 @@ struct ccsr_ssi { | |||
208 | * ssi_phys: physical address of the SSI registers | 208 | * ssi_phys: physical address of the SSI registers |
209 | * irq: IRQ of this SSI | 209 | * irq: IRQ of this SSI |
210 | * dev: struct device, used to create the sysfs statistics file | 210 | * dev: struct device, used to create the sysfs statistics file |
211 | * asynchronous: 0=synchronous mode, 1=asynchronous mode | ||
211 | */ | 212 | */ |
212 | struct fsl_ssi_info { | 213 | struct fsl_ssi_info { |
213 | unsigned int id; | 214 | unsigned int id; |
@@ -215,6 +216,7 @@ struct fsl_ssi_info { | |||
215 | dma_addr_t ssi_phys; | 216 | dma_addr_t ssi_phys; |
216 | unsigned int irq; | 217 | unsigned int irq; |
217 | struct device *dev; | 218 | struct device *dev; |
219 | int asynchronous; | ||
218 | }; | 220 | }; |
219 | 221 | ||
220 | struct snd_soc_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info); | 222 | struct snd_soc_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info); |
diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c index 9eb1ce185bd0..3aa729df27b5 100644 --- a/sound/soc/fsl/mpc5200_psc_i2s.c +++ b/sound/soc/fsl/mpc5200_psc_i2s.c | |||
@@ -468,6 +468,16 @@ static int psc_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int format) | |||
468 | /** | 468 | /** |
469 | * psc_i2s_dai_template: template CPU Digital Audio Interface | 469 | * psc_i2s_dai_template: template CPU Digital Audio Interface |
470 | */ | 470 | */ |
471 | static struct snd_soc_dai_ops psc_i2s_dai_ops = { | ||
472 | .startup = psc_i2s_startup, | ||
473 | .hw_params = psc_i2s_hw_params, | ||
474 | .hw_free = psc_i2s_hw_free, | ||
475 | .shutdown = psc_i2s_shutdown, | ||
476 | .trigger = psc_i2s_trigger, | ||
477 | .set_sysclk = psc_i2s_set_sysclk, | ||
478 | .set_fmt = psc_i2s_set_fmt, | ||
479 | }; | ||
480 | |||
471 | static struct snd_soc_dai psc_i2s_dai_template = { | 481 | static struct snd_soc_dai psc_i2s_dai_template = { |
472 | .playback = { | 482 | .playback = { |
473 | .channels_min = 2, | 483 | .channels_min = 2, |
@@ -481,15 +491,7 @@ static struct snd_soc_dai psc_i2s_dai_template = { | |||
481 | .rates = PSC_I2S_RATES, | 491 | .rates = PSC_I2S_RATES, |
482 | .formats = PSC_I2S_FORMATS, | 492 | .formats = PSC_I2S_FORMATS, |
483 | }, | 493 | }, |
484 | .ops = { | 494 | .ops = &psc_i2s_dai_ops, |
485 | .startup = psc_i2s_startup, | ||
486 | .hw_params = psc_i2s_hw_params, | ||
487 | .hw_free = psc_i2s_hw_free, | ||
488 | .shutdown = psc_i2s_shutdown, | ||
489 | .trigger = psc_i2s_trigger, | ||
490 | .set_sysclk = psc_i2s_set_sysclk, | ||
491 | .set_fmt = psc_i2s_set_fmt, | ||
492 | }, | ||
493 | }; | 495 | }; |
494 | 496 | ||
495 | /* --------------------------------------------------------------------- | 497 | /* --------------------------------------------------------------------- |
diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c index acf39a646b2f..ef67d1cdffe7 100644 --- a/sound/soc/fsl/mpc8610_hpcd.c +++ b/sound/soc/fsl/mpc8610_hpcd.c | |||
@@ -353,6 +353,11 @@ static int mpc8610_hpcd_probe(struct of_device *ofdev, | |||
353 | } | 353 | } |
354 | ssi_info.irq = machine_data->ssi_irq; | 354 | ssi_info.irq = machine_data->ssi_irq; |
355 | 355 | ||
356 | /* Do we want to use asynchronous mode? */ | ||
357 | ssi_info.asynchronous = | ||
358 | of_find_property(np, "fsl,ssi-asynchronous", NULL) ? 1 : 0; | ||
359 | if (ssi_info.asynchronous) | ||
360 | dev_info(&ofdev->dev, "using asynchronous mode\n"); | ||
356 | 361 | ||
357 | /* Map the global utilities registers. */ | 362 | /* Map the global utilities registers. */ |
358 | guts_np = of_find_compatible_node(NULL, NULL, "fsl,mpc8610-guts"); | 363 | guts_np = of_find_compatible_node(NULL, NULL, "fsl,mpc8610-guts"); |
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig index 4f7f04014585..675732e724d5 100644 --- a/sound/soc/omap/Kconfig +++ b/sound/soc/omap/Kconfig | |||
@@ -8,7 +8,7 @@ config SND_OMAP_SOC_MCBSP | |||
8 | 8 | ||
9 | config SND_OMAP_SOC_N810 | 9 | config SND_OMAP_SOC_N810 |
10 | tristate "SoC Audio support for Nokia N810" | 10 | tristate "SoC Audio support for Nokia N810" |
11 | depends on SND_OMAP_SOC && MACH_NOKIA_N810 | 11 | depends on SND_OMAP_SOC && MACH_NOKIA_N810 && I2C |
12 | select SND_OMAP_SOC_MCBSP | 12 | select SND_OMAP_SOC_MCBSP |
13 | select OMAP_MUX | 13 | select OMAP_MUX |
14 | select SND_SOC_TLV320AIC3X | 14 | select SND_SOC_TLV320AIC3X |
@@ -17,7 +17,7 @@ config SND_OMAP_SOC_N810 | |||
17 | 17 | ||
18 | config SND_OMAP_SOC_OSK5912 | 18 | config SND_OMAP_SOC_OSK5912 |
19 | tristate "SoC Audio support for omap osk5912" | 19 | tristate "SoC Audio support for omap osk5912" |
20 | depends on SND_OMAP_SOC && MACH_OMAP_OSK | 20 | depends on SND_OMAP_SOC && MACH_OMAP_OSK && I2C |
21 | select SND_OMAP_SOC_MCBSP | 21 | select SND_OMAP_SOC_MCBSP |
22 | select SND_SOC_TLV320AIC23 | 22 | select SND_SOC_TLV320AIC23 |
23 | help | 23 | help |
@@ -55,3 +55,13 @@ config SND_OMAP_SOC_OMAP3_PANDORA | |||
55 | select SND_SOC_TWL4030 | 55 | select SND_SOC_TWL4030 |
56 | help | 56 | help |
57 | Say Y if you want to add support for SoC audio on the OMAP3 Pandora. | 57 | Say Y if you want to add support for SoC audio on the OMAP3 Pandora. |
58 | |||
59 | config SND_OMAP_SOC_OMAP3_BEAGLE | ||
60 | tristate "SoC Audio support for OMAP3 Beagle" | ||
61 | depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP3_BEAGLE | ||
62 | select SND_OMAP_SOC_MCBSP | ||
63 | select SND_SOC_TWL4030 | ||
64 | help | ||
65 | Say Y if you want to add support for SoC audio on the Beagleboard. | ||
66 | |||
67 | |||
diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile index 76fedd96e365..0c9e4ac37660 100644 --- a/sound/soc/omap/Makefile +++ b/sound/soc/omap/Makefile | |||
@@ -12,6 +12,7 @@ snd-soc-overo-objs := overo.o | |||
12 | snd-soc-omap2evm-objs := omap2evm.o | 12 | snd-soc-omap2evm-objs := omap2evm.o |
13 | snd-soc-sdp3430-objs := sdp3430.o | 13 | snd-soc-sdp3430-objs := sdp3430.o |
14 | snd-soc-omap3pandora-objs := omap3pandora.o | 14 | snd-soc-omap3pandora-objs := omap3pandora.o |
15 | snd-soc-omap3beagle-objs := omap3beagle.o | ||
15 | 16 | ||
16 | obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o | 17 | obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o |
17 | obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o | 18 | obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o |
@@ -19,3 +20,4 @@ obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o | |||
19 | obj-$(CONFIG_MACH_OMAP2EVM) += snd-soc-omap2evm.o | 20 | obj-$(CONFIG_MACH_OMAP2EVM) += snd-soc-omap2evm.o |
20 | obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o | 21 | obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o |
21 | obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o | 22 | obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o |
23 | obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o | ||
diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c index 25593fee9121..a6d1178ce128 100644 --- a/sound/soc/omap/n810.c +++ b/sound/soc/omap/n810.c | |||
@@ -40,6 +40,13 @@ | |||
40 | #define N810_HEADSET_AMP_GPIO 10 | 40 | #define N810_HEADSET_AMP_GPIO 10 |
41 | #define N810_SPEAKER_AMP_GPIO 101 | 41 | #define N810_SPEAKER_AMP_GPIO 101 |
42 | 42 | ||
43 | enum { | ||
44 | N810_JACK_DISABLED, | ||
45 | N810_JACK_HP, | ||
46 | N810_JACK_HS, | ||
47 | N810_JACK_MIC, | ||
48 | }; | ||
49 | |||
43 | static struct clk *sys_clkout2; | 50 | static struct clk *sys_clkout2; |
44 | static struct clk *sys_clkout2_src; | 51 | static struct clk *sys_clkout2_src; |
45 | static struct clk *func96m_clk; | 52 | static struct clk *func96m_clk; |
@@ -50,15 +57,32 @@ static int n810_dmic_func; | |||
50 | 57 | ||
51 | static void n810_ext_control(struct snd_soc_codec *codec) | 58 | static void n810_ext_control(struct snd_soc_codec *codec) |
52 | { | 59 | { |
60 | int hp = 0, line1l = 0; | ||
61 | |||
62 | switch (n810_jack_func) { | ||
63 | case N810_JACK_HS: | ||
64 | line1l = 1; | ||
65 | case N810_JACK_HP: | ||
66 | hp = 1; | ||
67 | break; | ||
68 | case N810_JACK_MIC: | ||
69 | line1l = 1; | ||
70 | break; | ||
71 | } | ||
72 | |||
53 | if (n810_spk_func) | 73 | if (n810_spk_func) |
54 | snd_soc_dapm_enable_pin(codec, "Ext Spk"); | 74 | snd_soc_dapm_enable_pin(codec, "Ext Spk"); |
55 | else | 75 | else |
56 | snd_soc_dapm_disable_pin(codec, "Ext Spk"); | 76 | snd_soc_dapm_disable_pin(codec, "Ext Spk"); |
57 | 77 | ||
58 | if (n810_jack_func) | 78 | if (hp) |
59 | snd_soc_dapm_enable_pin(codec, "Headphone Jack"); | 79 | snd_soc_dapm_enable_pin(codec, "Headphone Jack"); |
60 | else | 80 | else |
61 | snd_soc_dapm_disable_pin(codec, "Headphone Jack"); | 81 | snd_soc_dapm_disable_pin(codec, "Headphone Jack"); |
82 | if (line1l) | ||
83 | snd_soc_dapm_enable_pin(codec, "LINE1L"); | ||
84 | else | ||
85 | snd_soc_dapm_disable_pin(codec, "LINE1L"); | ||
62 | 86 | ||
63 | if (n810_dmic_func) | 87 | if (n810_dmic_func) |
64 | snd_soc_dapm_enable_pin(codec, "DMic"); | 88 | snd_soc_dapm_enable_pin(codec, "DMic"); |
@@ -72,7 +96,7 @@ static int n810_startup(struct snd_pcm_substream *substream) | |||
72 | { | 96 | { |
73 | struct snd_pcm_runtime *runtime = substream->runtime; | 97 | struct snd_pcm_runtime *runtime = substream->runtime; |
74 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 98 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
75 | struct snd_soc_codec *codec = rtd->socdev->codec; | 99 | struct snd_soc_codec *codec = rtd->socdev->card->codec; |
76 | 100 | ||
77 | snd_pcm_hw_constraint_minmax(runtime, | 101 | snd_pcm_hw_constraint_minmax(runtime, |
78 | SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2); | 102 | SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2); |
@@ -229,7 +253,7 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
229 | }; | 253 | }; |
230 | 254 | ||
231 | static const char *spk_function[] = {"Off", "On"}; | 255 | static const char *spk_function[] = {"Off", "On"}; |
232 | static const char *jack_function[] = {"Off", "Headphone"}; | 256 | static const char *jack_function[] = {"Off", "Headphone", "Headset", "Mic"}; |
233 | static const char *input_function[] = {"ADC", "Digital Mic"}; | 257 | static const char *input_function[] = {"ADC", "Digital Mic"}; |
234 | static const struct soc_enum n810_enum[] = { | 258 | static const struct soc_enum n810_enum[] = { |
235 | SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spk_function), spk_function), | 259 | SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spk_function), spk_function), |
@@ -248,20 +272,23 @@ static const struct snd_kcontrol_new aic33_n810_controls[] = { | |||
248 | 272 | ||
249 | static int n810_aic33_init(struct snd_soc_codec *codec) | 273 | static int n810_aic33_init(struct snd_soc_codec *codec) |
250 | { | 274 | { |
251 | int i, err; | 275 | int err; |
252 | 276 | ||
253 | /* Not connected */ | 277 | /* Not connected */ |
254 | snd_soc_dapm_nc_pin(codec, "MONO_LOUT"); | 278 | snd_soc_dapm_nc_pin(codec, "MONO_LOUT"); |
255 | snd_soc_dapm_nc_pin(codec, "HPLCOM"); | 279 | snd_soc_dapm_nc_pin(codec, "HPLCOM"); |
256 | snd_soc_dapm_nc_pin(codec, "HPRCOM"); | 280 | snd_soc_dapm_nc_pin(codec, "HPRCOM"); |
281 | snd_soc_dapm_nc_pin(codec, "MIC3L"); | ||
282 | snd_soc_dapm_nc_pin(codec, "MIC3R"); | ||
283 | snd_soc_dapm_nc_pin(codec, "LINE1R"); | ||
284 | snd_soc_dapm_nc_pin(codec, "LINE2L"); | ||
285 | snd_soc_dapm_nc_pin(codec, "LINE2R"); | ||
257 | 286 | ||
258 | /* Add N810 specific controls */ | 287 | /* Add N810 specific controls */ |
259 | for (i = 0; i < ARRAY_SIZE(aic33_n810_controls); i++) { | 288 | err = snd_soc_add_controls(codec, aic33_n810_controls, |
260 | err = snd_ctl_add(codec->card, | 289 | ARRAY_SIZE(aic33_n810_controls)); |
261 | snd_soc_cnew(&aic33_n810_controls[i], codec, NULL)); | 290 | if (err < 0) |
262 | if (err < 0) | 291 | return err; |
263 | return err; | ||
264 | } | ||
265 | 292 | ||
266 | /* Add N810 specific widgets */ | 293 | /* Add N810 specific widgets */ |
267 | snd_soc_dapm_new_controls(codec, aic33_dapm_widgets, | 294 | snd_soc_dapm_new_controls(codec, aic33_dapm_widgets, |
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index 05dd5abcddf4..d6882be33452 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c | |||
@@ -461,6 +461,16 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, | |||
461 | return err; | 461 | return err; |
462 | } | 462 | } |
463 | 463 | ||
464 | static struct snd_soc_dai_ops omap_mcbsp_dai_ops = { | ||
465 | .startup = omap_mcbsp_dai_startup, | ||
466 | .shutdown = omap_mcbsp_dai_shutdown, | ||
467 | .trigger = omap_mcbsp_dai_trigger, | ||
468 | .hw_params = omap_mcbsp_dai_hw_params, | ||
469 | .set_fmt = omap_mcbsp_dai_set_dai_fmt, | ||
470 | .set_clkdiv = omap_mcbsp_dai_set_clkdiv, | ||
471 | .set_sysclk = omap_mcbsp_dai_set_dai_sysclk, | ||
472 | }; | ||
473 | |||
464 | #define OMAP_MCBSP_DAI_BUILDER(link_id) \ | 474 | #define OMAP_MCBSP_DAI_BUILDER(link_id) \ |
465 | { \ | 475 | { \ |
466 | .name = "omap-mcbsp-dai-"#link_id, \ | 476 | .name = "omap-mcbsp-dai-"#link_id, \ |
@@ -477,15 +487,7 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, | |||
477 | .rates = OMAP_MCBSP_RATES, \ | 487 | .rates = OMAP_MCBSP_RATES, \ |
478 | .formats = SNDRV_PCM_FMTBIT_S16_LE, \ | 488 | .formats = SNDRV_PCM_FMTBIT_S16_LE, \ |
479 | }, \ | 489 | }, \ |
480 | .ops = { \ | 490 | .ops = &omap_mcbsp_dai_ops, \ |
481 | .startup = omap_mcbsp_dai_startup, \ | ||
482 | .shutdown = omap_mcbsp_dai_shutdown, \ | ||
483 | .trigger = omap_mcbsp_dai_trigger, \ | ||
484 | .hw_params = omap_mcbsp_dai_hw_params, \ | ||
485 | .set_fmt = omap_mcbsp_dai_set_dai_fmt, \ | ||
486 | .set_clkdiv = omap_mcbsp_dai_set_clkdiv, \ | ||
487 | .set_sysclk = omap_mcbsp_dai_set_dai_sysclk, \ | ||
488 | }, \ | ||
489 | .private_data = &mcbsp_data[(link_id)].bus_id, \ | 491 | .private_data = &mcbsp_data[(link_id)].bus_id, \ |
490 | } | 492 | } |
491 | 493 | ||
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index dd3bb2933762..8e1431cb46bb 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c | |||
@@ -265,7 +265,7 @@ static int omap_pcm_mmap(struct snd_pcm_substream *substream, | |||
265 | runtime->dma_bytes); | 265 | runtime->dma_bytes); |
266 | } | 266 | } |
267 | 267 | ||
268 | struct snd_pcm_ops omap_pcm_ops = { | 268 | static struct snd_pcm_ops omap_pcm_ops = { |
269 | .open = omap_pcm_open, | 269 | .open = omap_pcm_open, |
270 | .close = omap_pcm_close, | 270 | .close = omap_pcm_close, |
271 | .ioctl = snd_pcm_lib_ioctl, | 271 | .ioctl = snd_pcm_lib_ioctl, |
diff --git a/sound/soc/omap/omap3pandora.c b/sound/soc/omap/omap3pandora.c index fcc2f5d9a878..fe282d4ef422 100644 --- a/sound/soc/omap/omap3pandora.c +++ b/sound/soc/omap/omap3pandora.c | |||
@@ -143,7 +143,7 @@ static const struct snd_soc_dapm_widget omap3pandora_out_dapm_widgets[] = { | |||
143 | }; | 143 | }; |
144 | 144 | ||
145 | static const struct snd_soc_dapm_widget omap3pandora_in_dapm_widgets[] = { | 145 | static const struct snd_soc_dapm_widget omap3pandora_in_dapm_widgets[] = { |
146 | SND_SOC_DAPM_MIC("Mic (Internal)", NULL), | 146 | SND_SOC_DAPM_MIC("Mic (internal)", NULL), |
147 | SND_SOC_DAPM_MIC("Mic (external)", NULL), | 147 | SND_SOC_DAPM_MIC("Mic (external)", NULL), |
148 | SND_SOC_DAPM_LINE("Line In", NULL), | 148 | SND_SOC_DAPM_LINE("Line In", NULL), |
149 | }; | 149 | }; |
@@ -155,16 +155,33 @@ static const struct snd_soc_dapm_route omap3pandora_out_map[] = { | |||
155 | }; | 155 | }; |
156 | 156 | ||
157 | static const struct snd_soc_dapm_route omap3pandora_in_map[] = { | 157 | static const struct snd_soc_dapm_route omap3pandora_in_map[] = { |
158 | {"INL", NULL, "Line In"}, | 158 | {"AUXL", NULL, "Line In"}, |
159 | {"INR", NULL, "Line In"}, | 159 | {"AUXR", NULL, "Line In"}, |
160 | {"INL", NULL, "Mic (Internal)"}, | 160 | |
161 | {"INR", NULL, "Mic (external)"}, | 161 | {"MAINMIC", NULL, "Mic Bias 1"}, |
162 | {"Mic Bias 1", NULL, "Mic (internal)"}, | ||
163 | |||
164 | {"SUBMIC", NULL, "Mic Bias 2"}, | ||
165 | {"Mic Bias 2", NULL, "Mic (external)"}, | ||
162 | }; | 166 | }; |
163 | 167 | ||
164 | static int omap3pandora_out_init(struct snd_soc_codec *codec) | 168 | static int omap3pandora_out_init(struct snd_soc_codec *codec) |
165 | { | 169 | { |
166 | int ret; | 170 | int ret; |
167 | 171 | ||
172 | /* All TWL4030 output pins are floating */ | ||
173 | snd_soc_dapm_nc_pin(codec, "OUTL"); | ||
174 | snd_soc_dapm_nc_pin(codec, "OUTR"); | ||
175 | snd_soc_dapm_nc_pin(codec, "EARPIECE"); | ||
176 | snd_soc_dapm_nc_pin(codec, "PREDRIVEL"); | ||
177 | snd_soc_dapm_nc_pin(codec, "PREDRIVER"); | ||
178 | snd_soc_dapm_nc_pin(codec, "HSOL"); | ||
179 | snd_soc_dapm_nc_pin(codec, "HSOR"); | ||
180 | snd_soc_dapm_nc_pin(codec, "CARKITL"); | ||
181 | snd_soc_dapm_nc_pin(codec, "CARKITR"); | ||
182 | snd_soc_dapm_nc_pin(codec, "HFL"); | ||
183 | snd_soc_dapm_nc_pin(codec, "HFR"); | ||
184 | |||
168 | ret = snd_soc_dapm_new_controls(codec, omap3pandora_out_dapm_widgets, | 185 | ret = snd_soc_dapm_new_controls(codec, omap3pandora_out_dapm_widgets, |
169 | ARRAY_SIZE(omap3pandora_out_dapm_widgets)); | 186 | ARRAY_SIZE(omap3pandora_out_dapm_widgets)); |
170 | if (ret < 0) | 187 | if (ret < 0) |
@@ -180,18 +197,11 @@ static int omap3pandora_in_init(struct snd_soc_codec *codec) | |||
180 | { | 197 | { |
181 | int ret; | 198 | int ret; |
182 | 199 | ||
183 | /* All TWL4030 output pins are floating */ | 200 | /* Not comnnected */ |
184 | snd_soc_dapm_nc_pin(codec, "OUTL"), | 201 | snd_soc_dapm_nc_pin(codec, "HSMIC"); |
185 | snd_soc_dapm_nc_pin(codec, "OUTR"), | 202 | snd_soc_dapm_nc_pin(codec, "CARKITMIC"); |
186 | snd_soc_dapm_nc_pin(codec, "EARPIECE"), | 203 | snd_soc_dapm_nc_pin(codec, "DIGIMIC0"); |
187 | snd_soc_dapm_nc_pin(codec, "PREDRIVEL"), | 204 | snd_soc_dapm_nc_pin(codec, "DIGIMIC1"); |
188 | snd_soc_dapm_nc_pin(codec, "PREDRIVER"), | ||
189 | snd_soc_dapm_nc_pin(codec, "HSOL"), | ||
190 | snd_soc_dapm_nc_pin(codec, "HSOR"), | ||
191 | snd_soc_dapm_nc_pin(codec, "CARKITL"), | ||
192 | snd_soc_dapm_nc_pin(codec, "CARKITR"), | ||
193 | snd_soc_dapm_nc_pin(codec, "HFL"), | ||
194 | snd_soc_dapm_nc_pin(codec, "HFR"), | ||
195 | 205 | ||
196 | ret = snd_soc_dapm_new_controls(codec, omap3pandora_in_dapm_widgets, | 206 | ret = snd_soc_dapm_new_controls(codec, omap3pandora_in_dapm_widgets, |
197 | ARRAY_SIZE(omap3pandora_in_dapm_widgets)); | 207 | ARRAY_SIZE(omap3pandora_in_dapm_widgets)); |
@@ -251,10 +261,9 @@ static int __init omap3pandora_soc_init(void) | |||
251 | { | 261 | { |
252 | int ret; | 262 | int ret; |
253 | 263 | ||
254 | if (!machine_is_omap3_pandora()) { | 264 | if (!machine_is_omap3_pandora()) |
255 | pr_debug(PREFIX "Not OMAP3 Pandora\n"); | ||
256 | return -ENODEV; | 265 | return -ENODEV; |
257 | } | 266 | |
258 | pr_info("OMAP3 Pandora SoC init\n"); | 267 | pr_info("OMAP3 Pandora SoC init\n"); |
259 | 268 | ||
260 | ret = gpio_request(OMAP3_PANDORA_DAC_POWER_GPIO, "dac_power"); | 269 | ret = gpio_request(OMAP3_PANDORA_DAC_POWER_GPIO, "dac_power"); |
diff --git a/sound/soc/omap/osk5912.c b/sound/soc/omap/osk5912.c index cd41a948df7b..a952a4eb3361 100644 --- a/sound/soc/omap/osk5912.c +++ b/sound/soc/omap/osk5912.c | |||
@@ -186,13 +186,6 @@ static int __init osk_soc_init(void) | |||
186 | return -ENODEV; | 186 | return -ENODEV; |
187 | } | 187 | } |
188 | 188 | ||
189 | if (clk_get_usecount(tlv320aic23_mclk) > 0) { | ||
190 | /* MCLK is already in use */ | ||
191 | printk(KERN_WARNING | ||
192 | "MCLK in use at %d Hz. We change it to %d Hz\n", | ||
193 | (uint) clk_get_rate(tlv320aic23_mclk), CODEC_CLOCK); | ||
194 | } | ||
195 | |||
196 | /* | 189 | /* |
197 | * Configure 12 MHz output on MCLK. | 190 | * Configure 12 MHz output on MCLK. |
198 | */ | 191 | */ |
@@ -205,9 +198,8 @@ static int __init osk_soc_init(void) | |||
205 | } | 198 | } |
206 | } | 199 | } |
207 | 200 | ||
208 | printk(KERN_INFO "MCLK = %d [%d], usecount = %d\n", | 201 | printk(KERN_INFO "MCLK = %d [%d]\n", |
209 | (uint) clk_get_rate(tlv320aic23_mclk), CODEC_CLOCK, | 202 | (uint) clk_get_rate(tlv320aic23_mclk), CODEC_CLOCK); |
210 | clk_get_usecount(tlv320aic23_mclk)); | ||
211 | 203 | ||
212 | return 0; | 204 | return 0; |
213 | err1: | 205 | err1: |
diff --git a/sound/soc/omap/sdp3430.c b/sound/soc/omap/sdp3430.c index e226fa75669c..10f1c867f11d 100644 --- a/sound/soc/omap/sdp3430.c +++ b/sound/soc/omap/sdp3430.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <sound/pcm.h> | 28 | #include <sound/pcm.h> |
29 | #include <sound/soc.h> | 29 | #include <sound/soc.h> |
30 | #include <sound/soc-dapm.h> | 30 | #include <sound/soc-dapm.h> |
31 | #include <sound/jack.h> | ||
31 | 32 | ||
32 | #include <asm/mach-types.h> | 33 | #include <asm/mach-types.h> |
33 | #include <mach/hardware.h> | 34 | #include <mach/hardware.h> |
@@ -38,6 +39,8 @@ | |||
38 | #include "omap-pcm.h" | 39 | #include "omap-pcm.h" |
39 | #include "../codecs/twl4030.h" | 40 | #include "../codecs/twl4030.h" |
40 | 41 | ||
42 | static struct snd_soc_card snd_soc_sdp3430; | ||
43 | |||
41 | static int sdp3430_hw_params(struct snd_pcm_substream *substream, | 44 | static int sdp3430_hw_params(struct snd_pcm_substream *substream, |
42 | struct snd_pcm_hw_params *params) | 45 | struct snd_pcm_hw_params *params) |
43 | { | 46 | { |
@@ -81,12 +84,121 @@ static struct snd_soc_ops sdp3430_ops = { | |||
81 | .hw_params = sdp3430_hw_params, | 84 | .hw_params = sdp3430_hw_params, |
82 | }; | 85 | }; |
83 | 86 | ||
87 | /* Headset jack */ | ||
88 | static struct snd_soc_jack hs_jack; | ||
89 | |||
90 | /* Headset jack detection DAPM pins */ | ||
91 | static struct snd_soc_jack_pin hs_jack_pins[] = { | ||
92 | { | ||
93 | .pin = "Headset Mic", | ||
94 | .mask = SND_JACK_MICROPHONE, | ||
95 | }, | ||
96 | { | ||
97 | .pin = "Headset Stereophone", | ||
98 | .mask = SND_JACK_HEADPHONE, | ||
99 | }, | ||
100 | }; | ||
101 | |||
102 | /* Headset jack detection gpios */ | ||
103 | static struct snd_soc_jack_gpio hs_jack_gpios[] = { | ||
104 | { | ||
105 | .gpio = (OMAP_MAX_GPIO_LINES + 2), | ||
106 | .name = "hsdet-gpio", | ||
107 | .report = SND_JACK_HEADSET, | ||
108 | .debounce_time = 200, | ||
109 | }, | ||
110 | }; | ||
111 | |||
112 | /* SDP3430 machine DAPM */ | ||
113 | static const struct snd_soc_dapm_widget sdp3430_twl4030_dapm_widgets[] = { | ||
114 | SND_SOC_DAPM_MIC("Ext Mic", NULL), | ||
115 | SND_SOC_DAPM_SPK("Ext Spk", NULL), | ||
116 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | ||
117 | SND_SOC_DAPM_HP("Headset Stereophone", NULL), | ||
118 | }; | ||
119 | |||
120 | static const struct snd_soc_dapm_route audio_map[] = { | ||
121 | /* External Mics: MAINMIC, SUBMIC with bias*/ | ||
122 | {"MAINMIC", NULL, "Mic Bias 1"}, | ||
123 | {"SUBMIC", NULL, "Mic Bias 2"}, | ||
124 | {"Mic Bias 1", NULL, "Ext Mic"}, | ||
125 | {"Mic Bias 2", NULL, "Ext Mic"}, | ||
126 | |||
127 | /* External Speakers: HFL, HFR */ | ||
128 | {"Ext Spk", NULL, "HFL"}, | ||
129 | {"Ext Spk", NULL, "HFR"}, | ||
130 | |||
131 | /* Headset Mic: HSMIC with bias */ | ||
132 | {"HSMIC", NULL, "Headset Mic Bias"}, | ||
133 | {"Headset Mic Bias", NULL, "Headset Mic"}, | ||
134 | |||
135 | /* Headset Stereophone (Headphone): HSOL, HSOR */ | ||
136 | {"Headset Stereophone", NULL, "HSOL"}, | ||
137 | {"Headset Stereophone", NULL, "HSOR"}, | ||
138 | }; | ||
139 | |||
140 | static int sdp3430_twl4030_init(struct snd_soc_codec *codec) | ||
141 | { | ||
142 | int ret; | ||
143 | |||
144 | /* Add SDP3430 specific widgets */ | ||
145 | ret = snd_soc_dapm_new_controls(codec, sdp3430_twl4030_dapm_widgets, | ||
146 | ARRAY_SIZE(sdp3430_twl4030_dapm_widgets)); | ||
147 | if (ret) | ||
148 | return ret; | ||
149 | |||
150 | /* Set up SDP3430 specific audio path audio_map */ | ||
151 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | ||
152 | |||
153 | /* SDP3430 connected pins */ | ||
154 | snd_soc_dapm_enable_pin(codec, "Ext Mic"); | ||
155 | snd_soc_dapm_enable_pin(codec, "Ext Spk"); | ||
156 | snd_soc_dapm_disable_pin(codec, "Headset Mic"); | ||
157 | snd_soc_dapm_disable_pin(codec, "Headset Stereophone"); | ||
158 | |||
159 | /* TWL4030 not connected pins */ | ||
160 | snd_soc_dapm_nc_pin(codec, "AUXL"); | ||
161 | snd_soc_dapm_nc_pin(codec, "AUXR"); | ||
162 | snd_soc_dapm_nc_pin(codec, "CARKITMIC"); | ||
163 | snd_soc_dapm_nc_pin(codec, "DIGIMIC0"); | ||
164 | snd_soc_dapm_nc_pin(codec, "DIGIMIC1"); | ||
165 | |||
166 | snd_soc_dapm_nc_pin(codec, "OUTL"); | ||
167 | snd_soc_dapm_nc_pin(codec, "OUTR"); | ||
168 | snd_soc_dapm_nc_pin(codec, "EARPIECE"); | ||
169 | snd_soc_dapm_nc_pin(codec, "PREDRIVEL"); | ||
170 | snd_soc_dapm_nc_pin(codec, "PREDRIVER"); | ||
171 | snd_soc_dapm_nc_pin(codec, "CARKITL"); | ||
172 | snd_soc_dapm_nc_pin(codec, "CARKITR"); | ||
173 | |||
174 | ret = snd_soc_dapm_sync(codec); | ||
175 | if (ret) | ||
176 | return ret; | ||
177 | |||
178 | /* Headset jack detection */ | ||
179 | ret = snd_soc_jack_new(&snd_soc_sdp3430, "Headset Jack", | ||
180 | SND_JACK_HEADSET, &hs_jack); | ||
181 | if (ret) | ||
182 | return ret; | ||
183 | |||
184 | ret = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins), | ||
185 | hs_jack_pins); | ||
186 | if (ret) | ||
187 | return ret; | ||
188 | |||
189 | ret = snd_soc_jack_add_gpios(&hs_jack, ARRAY_SIZE(hs_jack_gpios), | ||
190 | hs_jack_gpios); | ||
191 | |||
192 | return ret; | ||
193 | } | ||
194 | |||
84 | /* Digital audio interface glue - connects codec <--> CPU */ | 195 | /* Digital audio interface glue - connects codec <--> CPU */ |
85 | static struct snd_soc_dai_link sdp3430_dai = { | 196 | static struct snd_soc_dai_link sdp3430_dai = { |
86 | .name = "TWL4030", | 197 | .name = "TWL4030", |
87 | .stream_name = "TWL4030", | 198 | .stream_name = "TWL4030", |
88 | .cpu_dai = &omap_mcbsp_dai[0], | 199 | .cpu_dai = &omap_mcbsp_dai[0], |
89 | .codec_dai = &twl4030_dai, | 200 | .codec_dai = &twl4030_dai, |
201 | .init = sdp3430_twl4030_init, | ||
90 | .ops = &sdp3430_ops, | 202 | .ops = &sdp3430_ops, |
91 | }; | 203 | }; |
92 | 204 | ||
@@ -142,6 +254,9 @@ module_init(sdp3430_soc_init); | |||
142 | 254 | ||
143 | static void __exit sdp3430_soc_exit(void) | 255 | static void __exit sdp3430_soc_exit(void) |
144 | { | 256 | { |
257 | snd_soc_jack_free_gpios(&hs_jack, ARRAY_SIZE(hs_jack_gpios), | ||
258 | hs_jack_gpios); | ||
259 | |||
145 | platform_device_unregister(sdp3430_snd_device); | 260 | platform_device_unregister(sdp3430_snd_device); |
146 | } | 261 | } |
147 | module_exit(sdp3430_soc_exit); | 262 | module_exit(sdp3430_soc_exit); |
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index f82e10699471..5998ab366e83 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig | |||
@@ -61,6 +61,24 @@ config SND_PXA2XX_SOC_TOSA | |||
61 | Say Y if you want to add support for SoC audio on Sharp | 61 | Say Y if you want to add support for SoC audio on Sharp |
62 | Zaurus SL-C6000x models (Tosa). | 62 | Zaurus SL-C6000x models (Tosa). |
63 | 63 | ||
64 | config SND_PXA2XX_SOC_E740 | ||
65 | tristate "SoC AC97 Audio support for e740" | ||
66 | depends on SND_PXA2XX_SOC && MACH_E740 | ||
67 | select SND_SOC_WM9705 | ||
68 | select SND_PXA2XX_SOC_AC97 | ||
69 | help | ||
70 | Say Y if you want to add support for SoC audio on the | ||
71 | toshiba e740 PDA | ||
72 | |||
73 | config SND_PXA2XX_SOC_E750 | ||
74 | tristate "SoC AC97 Audio support for e750" | ||
75 | depends on SND_PXA2XX_SOC && MACH_E750 | ||
76 | select SND_SOC_WM9705 | ||
77 | select SND_PXA2XX_SOC_AC97 | ||
78 | help | ||
79 | Say Y if you want to add support for SoC audio on the | ||
80 | toshiba e750 PDA | ||
81 | |||
64 | config SND_PXA2XX_SOC_E800 | 82 | config SND_PXA2XX_SOC_E800 |
65 | tristate "SoC AC97 Audio support for e800" | 83 | tristate "SoC AC97 Audio support for e800" |
66 | depends on SND_PXA2XX_SOC && MACH_E800 | 84 | depends on SND_PXA2XX_SOC && MACH_E800 |
@@ -97,3 +115,12 @@ config SND_SOC_ZYLONITE | |||
97 | help | 115 | help |
98 | Say Y if you want to add support for SoC audio on the | 116 | Say Y if you want to add support for SoC audio on the |
99 | Marvell Zylonite reference platform. | 117 | Marvell Zylonite reference platform. |
118 | |||
119 | config SND_PXA2XX_SOC_MIOA701 | ||
120 | tristate "SoC Audio support for MIO A701" | ||
121 | depends on SND_PXA2XX_SOC && MACH_MIOA701 | ||
122 | select SND_PXA2XX_SOC_AC97 | ||
123 | select SND_SOC_WM9713 | ||
124 | help | ||
125 | Say Y if you want to add support for SoC audio on the | ||
126 | MIO A701. | ||
diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile index 08a9f2797729..8ed881c5e5cc 100644 --- a/sound/soc/pxa/Makefile +++ b/sound/soc/pxa/Makefile | |||
@@ -13,17 +13,23 @@ obj-$(CONFIG_SND_PXA_SOC_SSP) += snd-soc-pxa-ssp.o | |||
13 | snd-soc-corgi-objs := corgi.o | 13 | snd-soc-corgi-objs := corgi.o |
14 | snd-soc-poodle-objs := poodle.o | 14 | snd-soc-poodle-objs := poodle.o |
15 | snd-soc-tosa-objs := tosa.o | 15 | snd-soc-tosa-objs := tosa.o |
16 | snd-soc-e740-objs := e740_wm9705.o | ||
17 | snd-soc-e750-objs := e750_wm9705.o | ||
16 | snd-soc-e800-objs := e800_wm9712.o | 18 | snd-soc-e800-objs := e800_wm9712.o |
17 | snd-soc-spitz-objs := spitz.o | 19 | snd-soc-spitz-objs := spitz.o |
18 | snd-soc-em-x270-objs := em-x270.o | 20 | snd-soc-em-x270-objs := em-x270.o |
19 | snd-soc-palm27x-objs := palm27x.o | 21 | snd-soc-palm27x-objs := palm27x.o |
20 | snd-soc-zylonite-objs := zylonite.o | 22 | snd-soc-zylonite-objs := zylonite.o |
23 | snd-soc-mioa701-objs := mioa701_wm9713.o | ||
21 | 24 | ||
22 | obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o | 25 | obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o |
23 | obj-$(CONFIG_SND_PXA2XX_SOC_POODLE) += snd-soc-poodle.o | 26 | obj-$(CONFIG_SND_PXA2XX_SOC_POODLE) += snd-soc-poodle.o |
24 | obj-$(CONFIG_SND_PXA2XX_SOC_TOSA) += snd-soc-tosa.o | 27 | obj-$(CONFIG_SND_PXA2XX_SOC_TOSA) += snd-soc-tosa.o |
28 | obj-$(CONFIG_SND_PXA2XX_SOC_E740) += snd-soc-e740.o | ||
29 | obj-$(CONFIG_SND_PXA2XX_SOC_E750) += snd-soc-e750.o | ||
25 | obj-$(CONFIG_SND_PXA2XX_SOC_E800) += snd-soc-e800.o | 30 | obj-$(CONFIG_SND_PXA2XX_SOC_E800) += snd-soc-e800.o |
26 | obj-$(CONFIG_SND_PXA2XX_SOC_SPITZ) += snd-soc-spitz.o | 31 | obj-$(CONFIG_SND_PXA2XX_SOC_SPITZ) += snd-soc-spitz.o |
27 | obj-$(CONFIG_SND_PXA2XX_SOC_EM_X270) += snd-soc-em-x270.o | 32 | obj-$(CONFIG_SND_PXA2XX_SOC_EM_X270) += snd-soc-em-x270.o |
28 | obj-$(CONFIG_SND_PXA2XX_SOC_PALM27X) += snd-soc-palm27x.o | 33 | obj-$(CONFIG_SND_PXA2XX_SOC_PALM27X) += snd-soc-palm27x.o |
34 | obj-$(CONFIG_SND_PXA2XX_SOC_MIOA701) += snd-soc-mioa701.o | ||
29 | obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o | 35 | obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o |
diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c index ec930667feff..d5be2b30cda5 100644 --- a/sound/soc/pxa/corgi.c +++ b/sound/soc/pxa/corgi.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/moduleparam.h> | 17 | #include <linux/moduleparam.h> |
18 | #include <linux/timer.h> | 18 | #include <linux/timer.h> |
19 | #include <linux/i2c.h> | ||
19 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
20 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
21 | #include <linux/gpio.h> | 22 | #include <linux/gpio.h> |
@@ -98,7 +99,7 @@ static void corgi_ext_control(struct snd_soc_codec *codec) | |||
98 | static int corgi_startup(struct snd_pcm_substream *substream) | 99 | static int corgi_startup(struct snd_pcm_substream *substream) |
99 | { | 100 | { |
100 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 101 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
101 | struct snd_soc_codec *codec = rtd->socdev->codec; | 102 | struct snd_soc_codec *codec = rtd->socdev->card->codec; |
102 | 103 | ||
103 | /* check the jack status at stream startup */ | 104 | /* check the jack status at stream startup */ |
104 | corgi_ext_control(codec); | 105 | corgi_ext_control(codec); |
@@ -273,18 +274,16 @@ static const struct snd_kcontrol_new wm8731_corgi_controls[] = { | |||
273 | */ | 274 | */ |
274 | static int corgi_wm8731_init(struct snd_soc_codec *codec) | 275 | static int corgi_wm8731_init(struct snd_soc_codec *codec) |
275 | { | 276 | { |
276 | int i, err; | 277 | int err; |
277 | 278 | ||
278 | snd_soc_dapm_nc_pin(codec, "LLINEIN"); | 279 | snd_soc_dapm_nc_pin(codec, "LLINEIN"); |
279 | snd_soc_dapm_nc_pin(codec, "RLINEIN"); | 280 | snd_soc_dapm_nc_pin(codec, "RLINEIN"); |
280 | 281 | ||
281 | /* Add corgi specific controls */ | 282 | /* Add corgi specific controls */ |
282 | for (i = 0; i < ARRAY_SIZE(wm8731_corgi_controls); i++) { | 283 | err = snd_soc_add_controls(codec, wm8731_corgi_controls, |
283 | err = snd_ctl_add(codec->card, | 284 | ARRAY_SIZE(wm8731_corgi_controls)); |
284 | snd_soc_cnew(&wm8731_corgi_controls[i], codec, NULL)); | 285 | if (err < 0) |
285 | if (err < 0) | 286 | return err; |
286 | return err; | ||
287 | } | ||
288 | 287 | ||
289 | /* Add corgi specific widgets */ | 288 | /* Add corgi specific widgets */ |
290 | snd_soc_dapm_new_controls(codec, wm8731_dapm_widgets, | 289 | snd_soc_dapm_new_controls(codec, wm8731_dapm_widgets, |
@@ -315,19 +314,44 @@ static struct snd_soc_card snd_soc_corgi = { | |||
315 | .num_links = 1, | 314 | .num_links = 1, |
316 | }; | 315 | }; |
317 | 316 | ||
318 | /* corgi audio private data */ | ||
319 | static struct wm8731_setup_data corgi_wm8731_setup = { | ||
320 | .i2c_bus = 0, | ||
321 | .i2c_address = 0x1b, | ||
322 | }; | ||
323 | |||
324 | /* corgi audio subsystem */ | 317 | /* corgi audio subsystem */ |
325 | static struct snd_soc_device corgi_snd_devdata = { | 318 | static struct snd_soc_device corgi_snd_devdata = { |
326 | .card = &snd_soc_corgi, | 319 | .card = &snd_soc_corgi, |
327 | .codec_dev = &soc_codec_dev_wm8731, | 320 | .codec_dev = &soc_codec_dev_wm8731, |
328 | .codec_data = &corgi_wm8731_setup, | ||
329 | }; | 321 | }; |
330 | 322 | ||
323 | /* | ||
324 | * FIXME: This is a temporary bodge to avoid cross-tree merge issues. | ||
325 | * New drivers should register the wm8731 I2C device in the machine | ||
326 | * setup code (under arch/arm for ARM systems). | ||
327 | */ | ||
328 | static int wm8731_i2c_register(void) | ||
329 | { | ||
330 | struct i2c_board_info info; | ||
331 | struct i2c_adapter *adapter; | ||
332 | struct i2c_client *client; | ||
333 | |||
334 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
335 | info.addr = 0x1b; | ||
336 | strlcpy(info.type, "wm8731", I2C_NAME_SIZE); | ||
337 | |||
338 | adapter = i2c_get_adapter(0); | ||
339 | if (!adapter) { | ||
340 | printk(KERN_ERR "can't get i2c adapter 0\n"); | ||
341 | return -ENODEV; | ||
342 | } | ||
343 | |||
344 | client = i2c_new_device(adapter, &info); | ||
345 | i2c_put_adapter(adapter); | ||
346 | if (!client) { | ||
347 | printk(KERN_ERR "can't add i2c device at 0x%x\n", | ||
348 | (unsigned int)info.addr); | ||
349 | return -ENODEV; | ||
350 | } | ||
351 | |||
352 | return 0; | ||
353 | } | ||
354 | |||
331 | static struct platform_device *corgi_snd_device; | 355 | static struct platform_device *corgi_snd_device; |
332 | 356 | ||
333 | static int __init corgi_init(void) | 357 | static int __init corgi_init(void) |
@@ -338,6 +362,10 @@ static int __init corgi_init(void) | |||
338 | machine_is_husky())) | 362 | machine_is_husky())) |
339 | return -ENODEV; | 363 | return -ENODEV; |
340 | 364 | ||
365 | ret = wm8731_i2c_register(); | ||
366 | if (ret != 0) | ||
367 | return ret; | ||
368 | |||
341 | corgi_snd_device = platform_device_alloc("soc-audio", -1); | 369 | corgi_snd_device = platform_device_alloc("soc-audio", -1); |
342 | if (!corgi_snd_device) | 370 | if (!corgi_snd_device) |
343 | return -ENOMEM; | 371 | return -ENOMEM; |
diff --git a/sound/soc/pxa/e740_wm9705.c b/sound/soc/pxa/e740_wm9705.c new file mode 100644 index 000000000000..7cd2f89d7b10 --- /dev/null +++ b/sound/soc/pxa/e740_wm9705.c | |||
@@ -0,0 +1,211 @@ | |||
1 | /* | ||
2 | * e740-wm9705.c -- SoC audio for e740 | ||
3 | * | ||
4 | * Copyright 2007 (c) Ian Molton <spyro@f2s.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; version 2 ONLY. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/moduleparam.h> | ||
14 | #include <linux/gpio.h> | ||
15 | |||
16 | #include <sound/core.h> | ||
17 | #include <sound/pcm.h> | ||
18 | #include <sound/soc.h> | ||
19 | #include <sound/soc-dapm.h> | ||
20 | |||
21 | #include <mach/audio.h> | ||
22 | #include <mach/eseries-gpio.h> | ||
23 | |||
24 | #include <asm/mach-types.h> | ||
25 | |||
26 | #include "../codecs/wm9705.h" | ||
27 | #include "pxa2xx-pcm.h" | ||
28 | #include "pxa2xx-ac97.h" | ||
29 | |||
30 | |||
31 | #define E740_AUDIO_OUT 1 | ||
32 | #define E740_AUDIO_IN 2 | ||
33 | |||
34 | static int e740_audio_power; | ||
35 | |||
36 | static void e740_sync_audio_power(int status) | ||
37 | { | ||
38 | gpio_set_value(GPIO_E740_WM9705_nAVDD2, !status); | ||
39 | gpio_set_value(GPIO_E740_AMP_ON, (status & E740_AUDIO_OUT) ? 1 : 0); | ||
40 | gpio_set_value(GPIO_E740_MIC_ON, (status & E740_AUDIO_IN) ? 1 : 0); | ||
41 | } | ||
42 | |||
43 | static int e740_mic_amp_event(struct snd_soc_dapm_widget *w, | ||
44 | struct snd_kcontrol *kcontrol, int event) | ||
45 | { | ||
46 | if (event & SND_SOC_DAPM_PRE_PMU) | ||
47 | e740_audio_power |= E740_AUDIO_IN; | ||
48 | else if (event & SND_SOC_DAPM_POST_PMD) | ||
49 | e740_audio_power &= ~E740_AUDIO_IN; | ||
50 | |||
51 | e740_sync_audio_power(e740_audio_power); | ||
52 | |||
53 | return 0; | ||
54 | } | ||
55 | |||
56 | static int e740_output_amp_event(struct snd_soc_dapm_widget *w, | ||
57 | struct snd_kcontrol *kcontrol, int event) | ||
58 | { | ||
59 | if (event & SND_SOC_DAPM_PRE_PMU) | ||
60 | e740_audio_power |= E740_AUDIO_OUT; | ||
61 | else if (event & SND_SOC_DAPM_POST_PMD) | ||
62 | e740_audio_power &= ~E740_AUDIO_OUT; | ||
63 | |||
64 | e740_sync_audio_power(e740_audio_power); | ||
65 | |||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | static const struct snd_soc_dapm_widget e740_dapm_widgets[] = { | ||
70 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | ||
71 | SND_SOC_DAPM_SPK("Speaker", NULL), | ||
72 | SND_SOC_DAPM_MIC("Mic (Internal)", NULL), | ||
73 | SND_SOC_DAPM_PGA_E("Output Amp", SND_SOC_NOPM, 0, 0, NULL, 0, | ||
74 | e740_output_amp_event, SND_SOC_DAPM_PRE_PMU | | ||
75 | SND_SOC_DAPM_POST_PMD), | ||
76 | SND_SOC_DAPM_PGA_E("Mic Amp", SND_SOC_NOPM, 0, 0, NULL, 0, | ||
77 | e740_mic_amp_event, SND_SOC_DAPM_PRE_PMU | | ||
78 | SND_SOC_DAPM_POST_PMD), | ||
79 | }; | ||
80 | |||
81 | static const struct snd_soc_dapm_route audio_map[] = { | ||
82 | {"Output Amp", NULL, "LOUT"}, | ||
83 | {"Output Amp", NULL, "ROUT"}, | ||
84 | {"Output Amp", NULL, "MONOOUT"}, | ||
85 | |||
86 | {"Speaker", NULL, "Output Amp"}, | ||
87 | {"Headphone Jack", NULL, "Output Amp"}, | ||
88 | |||
89 | {"MIC1", NULL, "Mic Amp"}, | ||
90 | {"Mic Amp", NULL, "Mic (Internal)"}, | ||
91 | }; | ||
92 | |||
93 | static int e740_ac97_init(struct snd_soc_codec *codec) | ||
94 | { | ||
95 | snd_soc_dapm_nc_pin(codec, "HPOUTL"); | ||
96 | snd_soc_dapm_nc_pin(codec, "HPOUTR"); | ||
97 | snd_soc_dapm_nc_pin(codec, "PHONE"); | ||
98 | snd_soc_dapm_nc_pin(codec, "LINEINL"); | ||
99 | snd_soc_dapm_nc_pin(codec, "LINEINR"); | ||
100 | snd_soc_dapm_nc_pin(codec, "CDINL"); | ||
101 | snd_soc_dapm_nc_pin(codec, "CDINR"); | ||
102 | snd_soc_dapm_nc_pin(codec, "PCBEEP"); | ||
103 | snd_soc_dapm_nc_pin(codec, "MIC2"); | ||
104 | |||
105 | snd_soc_dapm_new_controls(codec, e740_dapm_widgets, | ||
106 | ARRAY_SIZE(e740_dapm_widgets)); | ||
107 | |||
108 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | ||
109 | |||
110 | snd_soc_dapm_sync(codec); | ||
111 | |||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | static struct snd_soc_dai_link e740_dai[] = { | ||
116 | { | ||
117 | .name = "AC97", | ||
118 | .stream_name = "AC97 HiFi", | ||
119 | .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], | ||
120 | .codec_dai = &wm9705_dai[WM9705_DAI_AC97_HIFI], | ||
121 | .init = e740_ac97_init, | ||
122 | }, | ||
123 | { | ||
124 | .name = "AC97 Aux", | ||
125 | .stream_name = "AC97 Aux", | ||
126 | .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], | ||
127 | .codec_dai = &wm9705_dai[WM9705_DAI_AC97_AUX], | ||
128 | }, | ||
129 | }; | ||
130 | |||
131 | static struct snd_soc_card e740 = { | ||
132 | .name = "Toshiba e740", | ||
133 | .platform = &pxa2xx_soc_platform, | ||
134 | .dai_link = e740_dai, | ||
135 | .num_links = ARRAY_SIZE(e740_dai), | ||
136 | }; | ||
137 | |||
138 | static struct snd_soc_device e740_snd_devdata = { | ||
139 | .card = &e740, | ||
140 | .codec_dev = &soc_codec_dev_wm9705, | ||
141 | }; | ||
142 | |||
143 | static struct platform_device *e740_snd_device; | ||
144 | |||
145 | static int __init e740_init(void) | ||
146 | { | ||
147 | int ret; | ||
148 | |||
149 | if (!machine_is_e740()) | ||
150 | return -ENODEV; | ||
151 | |||
152 | ret = gpio_request(GPIO_E740_MIC_ON, "Mic amp"); | ||
153 | if (ret) | ||
154 | return ret; | ||
155 | |||
156 | ret = gpio_request(GPIO_E740_AMP_ON, "Output amp"); | ||
157 | if (ret) | ||
158 | goto free_mic_amp_gpio; | ||
159 | |||
160 | ret = gpio_request(GPIO_E740_WM9705_nAVDD2, "Audio power"); | ||
161 | if (ret) | ||
162 | goto free_op_amp_gpio; | ||
163 | |||
164 | /* Disable audio */ | ||
165 | ret = gpio_direction_output(GPIO_E740_MIC_ON, 0); | ||
166 | if (ret) | ||
167 | goto free_apwr_gpio; | ||
168 | ret = gpio_direction_output(GPIO_E740_AMP_ON, 0); | ||
169 | if (ret) | ||
170 | goto free_apwr_gpio; | ||
171 | ret = gpio_direction_output(GPIO_E740_WM9705_nAVDD2, 1); | ||
172 | if (ret) | ||
173 | goto free_apwr_gpio; | ||
174 | |||
175 | e740_snd_device = platform_device_alloc("soc-audio", -1); | ||
176 | if (!e740_snd_device) { | ||
177 | ret = -ENOMEM; | ||
178 | goto free_apwr_gpio; | ||
179 | } | ||
180 | |||
181 | platform_set_drvdata(e740_snd_device, &e740_snd_devdata); | ||
182 | e740_snd_devdata.dev = &e740_snd_device->dev; | ||
183 | ret = platform_device_add(e740_snd_device); | ||
184 | |||
185 | if (!ret) | ||
186 | return 0; | ||
187 | |||
188 | /* Fail gracefully */ | ||
189 | platform_device_put(e740_snd_device); | ||
190 | free_apwr_gpio: | ||
191 | gpio_free(GPIO_E740_WM9705_nAVDD2); | ||
192 | free_op_amp_gpio: | ||
193 | gpio_free(GPIO_E740_AMP_ON); | ||
194 | free_mic_amp_gpio: | ||
195 | gpio_free(GPIO_E740_MIC_ON); | ||
196 | |||
197 | return ret; | ||
198 | } | ||
199 | |||
200 | static void __exit e740_exit(void) | ||
201 | { | ||
202 | platform_device_unregister(e740_snd_device); | ||
203 | } | ||
204 | |||
205 | module_init(e740_init); | ||
206 | module_exit(e740_exit); | ||
207 | |||
208 | /* Module information */ | ||
209 | MODULE_AUTHOR("Ian Molton <spyro@f2s.com>"); | ||
210 | MODULE_DESCRIPTION("ALSA SoC driver for e740"); | ||
211 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/pxa/e750_wm9705.c b/sound/soc/pxa/e750_wm9705.c new file mode 100644 index 000000000000..8dceccc5e059 --- /dev/null +++ b/sound/soc/pxa/e750_wm9705.c | |||
@@ -0,0 +1,187 @@ | |||
1 | /* | ||
2 | * e750-wm9705.c -- SoC audio for e750 | ||
3 | * | ||
4 | * Copyright 2007 (c) Ian Molton <spyro@f2s.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; version 2 ONLY. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/moduleparam.h> | ||
14 | #include <linux/gpio.h> | ||
15 | |||
16 | #include <sound/core.h> | ||
17 | #include <sound/pcm.h> | ||
18 | #include <sound/soc.h> | ||
19 | #include <sound/soc-dapm.h> | ||
20 | |||
21 | #include <mach/audio.h> | ||
22 | #include <mach/eseries-gpio.h> | ||
23 | |||
24 | #include <asm/mach-types.h> | ||
25 | |||
26 | #include "../codecs/wm9705.h" | ||
27 | #include "pxa2xx-pcm.h" | ||
28 | #include "pxa2xx-ac97.h" | ||
29 | |||
30 | static int e750_spk_amp_event(struct snd_soc_dapm_widget *w, | ||
31 | struct snd_kcontrol *kcontrol, int event) | ||
32 | { | ||
33 | if (event & SND_SOC_DAPM_PRE_PMU) | ||
34 | gpio_set_value(GPIO_E750_SPK_AMP_OFF, 0); | ||
35 | else if (event & SND_SOC_DAPM_POST_PMD) | ||
36 | gpio_set_value(GPIO_E750_SPK_AMP_OFF, 1); | ||
37 | |||
38 | return 0; | ||
39 | } | ||
40 | |||
41 | static int e750_hp_amp_event(struct snd_soc_dapm_widget *w, | ||
42 | struct snd_kcontrol *kcontrol, int event) | ||
43 | { | ||
44 | if (event & SND_SOC_DAPM_PRE_PMU) | ||
45 | gpio_set_value(GPIO_E750_HP_AMP_OFF, 0); | ||
46 | else if (event & SND_SOC_DAPM_POST_PMD) | ||
47 | gpio_set_value(GPIO_E750_HP_AMP_OFF, 1); | ||
48 | |||
49 | return 0; | ||
50 | } | ||
51 | |||
52 | static const struct snd_soc_dapm_widget e750_dapm_widgets[] = { | ||
53 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | ||
54 | SND_SOC_DAPM_SPK("Speaker", NULL), | ||
55 | SND_SOC_DAPM_MIC("Mic (Internal)", NULL), | ||
56 | SND_SOC_DAPM_PGA_E("Headphone Amp", SND_SOC_NOPM, 0, 0, NULL, 0, | ||
57 | e750_hp_amp_event, SND_SOC_DAPM_PRE_PMU | | ||
58 | SND_SOC_DAPM_POST_PMD), | ||
59 | SND_SOC_DAPM_PGA_E("Speaker Amp", SND_SOC_NOPM, 0, 0, NULL, 0, | ||
60 | e750_spk_amp_event, SND_SOC_DAPM_PRE_PMU | | ||
61 | SND_SOC_DAPM_POST_PMD), | ||
62 | }; | ||
63 | |||
64 | static const struct snd_soc_dapm_route audio_map[] = { | ||
65 | {"Headphone Amp", NULL, "HPOUTL"}, | ||
66 | {"Headphone Amp", NULL, "HPOUTR"}, | ||
67 | {"Headphone Jack", NULL, "Headphone Amp"}, | ||
68 | |||
69 | {"Speaker Amp", NULL, "MONOOUT"}, | ||
70 | {"Speaker", NULL, "Speaker Amp"}, | ||
71 | |||
72 | {"MIC1", NULL, "Mic (Internal)"}, | ||
73 | }; | ||
74 | |||
75 | static int e750_ac97_init(struct snd_soc_codec *codec) | ||
76 | { | ||
77 | snd_soc_dapm_nc_pin(codec, "LOUT"); | ||
78 | snd_soc_dapm_nc_pin(codec, "ROUT"); | ||
79 | snd_soc_dapm_nc_pin(codec, "PHONE"); | ||
80 | snd_soc_dapm_nc_pin(codec, "LINEINL"); | ||
81 | snd_soc_dapm_nc_pin(codec, "LINEINR"); | ||
82 | snd_soc_dapm_nc_pin(codec, "CDINL"); | ||
83 | snd_soc_dapm_nc_pin(codec, "CDINR"); | ||
84 | snd_soc_dapm_nc_pin(codec, "PCBEEP"); | ||
85 | snd_soc_dapm_nc_pin(codec, "MIC2"); | ||
86 | |||
87 | snd_soc_dapm_new_controls(codec, e750_dapm_widgets, | ||
88 | ARRAY_SIZE(e750_dapm_widgets)); | ||
89 | |||
90 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | ||
91 | |||
92 | snd_soc_dapm_sync(codec); | ||
93 | |||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | static struct snd_soc_dai_link e750_dai[] = { | ||
98 | { | ||
99 | .name = "AC97", | ||
100 | .stream_name = "AC97 HiFi", | ||
101 | .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], | ||
102 | .codec_dai = &wm9705_dai[WM9705_DAI_AC97_HIFI], | ||
103 | .init = e750_ac97_init, | ||
104 | /* use ops to check startup state */ | ||
105 | }, | ||
106 | { | ||
107 | .name = "AC97 Aux", | ||
108 | .stream_name = "AC97 Aux", | ||
109 | .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], | ||
110 | .codec_dai = &wm9705_dai[WM9705_DAI_AC97_AUX], | ||
111 | }, | ||
112 | }; | ||
113 | |||
114 | static struct snd_soc_card e750 = { | ||
115 | .name = "Toshiba e750", | ||
116 | .platform = &pxa2xx_soc_platform, | ||
117 | .dai_link = e750_dai, | ||
118 | .num_links = ARRAY_SIZE(e750_dai), | ||
119 | }; | ||
120 | |||
121 | static struct snd_soc_device e750_snd_devdata = { | ||
122 | .card = &e750, | ||
123 | .codec_dev = &soc_codec_dev_wm9705, | ||
124 | }; | ||
125 | |||
126 | static struct platform_device *e750_snd_device; | ||
127 | |||
128 | static int __init e750_init(void) | ||
129 | { | ||
130 | int ret; | ||
131 | |||
132 | if (!machine_is_e750()) | ||
133 | return -ENODEV; | ||
134 | |||
135 | ret = gpio_request(GPIO_E750_HP_AMP_OFF, "Headphone amp"); | ||
136 | if (ret) | ||
137 | return ret; | ||
138 | |||
139 | ret = gpio_request(GPIO_E750_SPK_AMP_OFF, "Speaker amp"); | ||
140 | if (ret) | ||
141 | goto free_hp_amp_gpio; | ||
142 | |||
143 | ret = gpio_direction_output(GPIO_E750_HP_AMP_OFF, 1); | ||
144 | if (ret) | ||
145 | goto free_spk_amp_gpio; | ||
146 | |||
147 | ret = gpio_direction_output(GPIO_E750_SPK_AMP_OFF, 1); | ||
148 | if (ret) | ||
149 | goto free_spk_amp_gpio; | ||
150 | |||
151 | e750_snd_device = platform_device_alloc("soc-audio", -1); | ||
152 | if (!e750_snd_device) { | ||
153 | ret = -ENOMEM; | ||
154 | goto free_spk_amp_gpio; | ||
155 | } | ||
156 | |||
157 | platform_set_drvdata(e750_snd_device, &e750_snd_devdata); | ||
158 | e750_snd_devdata.dev = &e750_snd_device->dev; | ||
159 | ret = platform_device_add(e750_snd_device); | ||
160 | |||
161 | if (!ret) | ||
162 | return 0; | ||
163 | |||
164 | /* Fail gracefully */ | ||
165 | platform_device_put(e750_snd_device); | ||
166 | free_spk_amp_gpio: | ||
167 | gpio_free(GPIO_E750_SPK_AMP_OFF); | ||
168 | free_hp_amp_gpio: | ||
169 | gpio_free(GPIO_E750_HP_AMP_OFF); | ||
170 | |||
171 | return ret; | ||
172 | } | ||
173 | |||
174 | static void __exit e750_exit(void) | ||
175 | { | ||
176 | platform_device_unregister(e750_snd_device); | ||
177 | gpio_free(GPIO_E750_SPK_AMP_OFF); | ||
178 | gpio_free(GPIO_E750_HP_AMP_OFF); | ||
179 | } | ||
180 | |||
181 | module_init(e750_init); | ||
182 | module_exit(e750_exit); | ||
183 | |||
184 | /* Module information */ | ||
185 | MODULE_AUTHOR("Ian Molton <spyro@f2s.com>"); | ||
186 | MODULE_DESCRIPTION("ALSA SoC driver for e750"); | ||
187 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/pxa/e800_wm9712.c b/sound/soc/pxa/e800_wm9712.c index ac294c797b7d..bc019cdce429 100644 --- a/sound/soc/pxa/e800_wm9712.c +++ b/sound/soc/pxa/e800_wm9712.c | |||
@@ -1,8 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * e800-wm9712.c -- SoC audio for e800 | 2 | * e800-wm9712.c -- SoC audio for e800 |
3 | * | 3 | * |
4 | * Based on tosa.c | ||
5 | * | ||
6 | * Copyright 2007 (c) Ian Molton <spyro@f2s.com> | 4 | * Copyright 2007 (c) Ian Molton <spyro@f2s.com> |
7 | * | 5 | * |
8 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
@@ -13,7 +11,7 @@ | |||
13 | 11 | ||
14 | #include <linux/module.h> | 12 | #include <linux/module.h> |
15 | #include <linux/moduleparam.h> | 13 | #include <linux/moduleparam.h> |
16 | #include <linux/device.h> | 14 | #include <linux/gpio.h> |
17 | 15 | ||
18 | #include <sound/core.h> | 16 | #include <sound/core.h> |
19 | #include <sound/pcm.h> | 17 | #include <sound/pcm.h> |
@@ -22,20 +20,84 @@ | |||
22 | 20 | ||
23 | #include <asm/mach-types.h> | 21 | #include <asm/mach-types.h> |
24 | #include <mach/audio.h> | 22 | #include <mach/audio.h> |
23 | #include <mach/eseries-gpio.h> | ||
25 | 24 | ||
26 | #include "../codecs/wm9712.h" | 25 | #include "../codecs/wm9712.h" |
27 | #include "pxa2xx-pcm.h" | 26 | #include "pxa2xx-pcm.h" |
28 | #include "pxa2xx-ac97.h" | 27 | #include "pxa2xx-ac97.h" |
29 | 28 | ||
30 | static struct snd_soc_card e800; | 29 | static int e800_spk_amp_event(struct snd_soc_dapm_widget *w, |
30 | struct snd_kcontrol *kcontrol, int event) | ||
31 | { | ||
32 | if (event & SND_SOC_DAPM_PRE_PMU) | ||
33 | gpio_set_value(GPIO_E800_SPK_AMP_ON, 1); | ||
34 | else if (event & SND_SOC_DAPM_POST_PMD) | ||
35 | gpio_set_value(GPIO_E800_SPK_AMP_ON, 0); | ||
31 | 36 | ||
32 | static struct snd_soc_dai_link e800_dai[] = { | 37 | return 0; |
38 | } | ||
39 | |||
40 | static int e800_hp_amp_event(struct snd_soc_dapm_widget *w, | ||
41 | struct snd_kcontrol *kcontrol, int event) | ||
42 | { | ||
43 | if (event & SND_SOC_DAPM_PRE_PMU) | ||
44 | gpio_set_value(GPIO_E800_HP_AMP_OFF, 0); | ||
45 | else if (event & SND_SOC_DAPM_POST_PMD) | ||
46 | gpio_set_value(GPIO_E800_HP_AMP_OFF, 1); | ||
47 | |||
48 | return 0; | ||
49 | } | ||
50 | |||
51 | static const struct snd_soc_dapm_widget e800_dapm_widgets[] = { | ||
52 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | ||
53 | SND_SOC_DAPM_MIC("Mic (Internal1)", NULL), | ||
54 | SND_SOC_DAPM_MIC("Mic (Internal2)", NULL), | ||
55 | SND_SOC_DAPM_SPK("Speaker", NULL), | ||
56 | SND_SOC_DAPM_PGA_E("Headphone Amp", SND_SOC_NOPM, 0, 0, NULL, 0, | ||
57 | e800_hp_amp_event, SND_SOC_DAPM_PRE_PMU | | ||
58 | SND_SOC_DAPM_POST_PMD), | ||
59 | SND_SOC_DAPM_PGA_E("Speaker Amp", SND_SOC_NOPM, 0, 0, NULL, 0, | ||
60 | e800_spk_amp_event, SND_SOC_DAPM_PRE_PMU | | ||
61 | SND_SOC_DAPM_POST_PMD), | ||
62 | }; | ||
63 | |||
64 | static const struct snd_soc_dapm_route audio_map[] = { | ||
65 | {"Headphone Jack", NULL, "HPOUTL"}, | ||
66 | {"Headphone Jack", NULL, "HPOUTR"}, | ||
67 | {"Headphone Jack", NULL, "Headphone Amp"}, | ||
68 | |||
69 | {"Speaker Amp", NULL, "MONOOUT"}, | ||
70 | {"Speaker", NULL, "Speaker Amp"}, | ||
71 | |||
72 | {"MIC1", NULL, "Mic (Internal1)"}, | ||
73 | {"MIC2", NULL, "Mic (Internal2)"}, | ||
74 | }; | ||
75 | |||
76 | static int e800_ac97_init(struct snd_soc_codec *codec) | ||
33 | { | 77 | { |
34 | .name = "AC97 Aux", | 78 | snd_soc_dapm_new_controls(codec, e800_dapm_widgets, |
35 | .stream_name = "AC97 Aux", | 79 | ARRAY_SIZE(e800_dapm_widgets)); |
36 | .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], | 80 | |
37 | .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX], | 81 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); |
38 | }, | 82 | snd_soc_dapm_sync(codec); |
83 | |||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | static struct snd_soc_dai_link e800_dai[] = { | ||
88 | { | ||
89 | .name = "AC97", | ||
90 | .stream_name = "AC97 HiFi", | ||
91 | .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], | ||
92 | .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI], | ||
93 | .init = e800_ac97_init, | ||
94 | }, | ||
95 | { | ||
96 | .name = "AC97 Aux", | ||
97 | .stream_name = "AC97 Aux", | ||
98 | .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], | ||
99 | .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX], | ||
100 | }, | ||
39 | }; | 101 | }; |
40 | 102 | ||
41 | static struct snd_soc_card e800 = { | 103 | static struct snd_soc_card e800 = { |
@@ -59,6 +121,22 @@ static int __init e800_init(void) | |||
59 | if (!machine_is_e800()) | 121 | if (!machine_is_e800()) |
60 | return -ENODEV; | 122 | return -ENODEV; |
61 | 123 | ||
124 | ret = gpio_request(GPIO_E800_HP_AMP_OFF, "Headphone amp"); | ||
125 | if (ret) | ||
126 | return ret; | ||
127 | |||
128 | ret = gpio_request(GPIO_E800_SPK_AMP_ON, "Speaker amp"); | ||
129 | if (ret) | ||
130 | goto free_hp_amp_gpio; | ||
131 | |||
132 | ret = gpio_direction_output(GPIO_E800_HP_AMP_OFF, 1); | ||
133 | if (ret) | ||
134 | goto free_spk_amp_gpio; | ||
135 | |||
136 | ret = gpio_direction_output(GPIO_E800_SPK_AMP_ON, 1); | ||
137 | if (ret) | ||
138 | goto free_spk_amp_gpio; | ||
139 | |||
62 | e800_snd_device = platform_device_alloc("soc-audio", -1); | 140 | e800_snd_device = platform_device_alloc("soc-audio", -1); |
63 | if (!e800_snd_device) | 141 | if (!e800_snd_device) |
64 | return -ENOMEM; | 142 | return -ENOMEM; |
@@ -67,8 +145,15 @@ static int __init e800_init(void) | |||
67 | e800_snd_devdata.dev = &e800_snd_device->dev; | 145 | e800_snd_devdata.dev = &e800_snd_device->dev; |
68 | ret = platform_device_add(e800_snd_device); | 146 | ret = platform_device_add(e800_snd_device); |
69 | 147 | ||
70 | if (ret) | 148 | if (!ret) |
71 | platform_device_put(e800_snd_device); | 149 | return 0; |
150 | |||
151 | /* Fail gracefully */ | ||
152 | platform_device_put(e800_snd_device); | ||
153 | free_spk_amp_gpio: | ||
154 | gpio_free(GPIO_E800_SPK_AMP_ON); | ||
155 | free_hp_amp_gpio: | ||
156 | gpio_free(GPIO_E800_HP_AMP_OFF); | ||
72 | 157 | ||
73 | return ret; | 158 | return ret; |
74 | } | 159 | } |
@@ -76,6 +161,8 @@ static int __init e800_init(void) | |||
76 | static void __exit e800_exit(void) | 161 | static void __exit e800_exit(void) |
77 | { | 162 | { |
78 | platform_device_unregister(e800_snd_device); | 163 | platform_device_unregister(e800_snd_device); |
164 | gpio_free(GPIO_E800_SPK_AMP_ON); | ||
165 | gpio_free(GPIO_E800_HP_AMP_OFF); | ||
79 | } | 166 | } |
80 | 167 | ||
81 | module_init(e800_init); | 168 | module_init(e800_init); |
@@ -84,4 +171,4 @@ module_exit(e800_exit); | |||
84 | /* Module information */ | 171 | /* Module information */ |
85 | MODULE_AUTHOR("Ian Molton <spyro@f2s.com>"); | 172 | MODULE_AUTHOR("Ian Molton <spyro@f2s.com>"); |
86 | MODULE_DESCRIPTION("ALSA SoC driver for e800"); | 173 | MODULE_DESCRIPTION("ALSA SoC driver for e800"); |
87 | MODULE_LICENSE("GPL"); | 174 | MODULE_LICENSE("GPL v2"); |
diff --git a/sound/soc/pxa/mioa701_wm9713.c b/sound/soc/pxa/mioa701_wm9713.c new file mode 100644 index 000000000000..19eda8bbfdaf --- /dev/null +++ b/sound/soc/pxa/mioa701_wm9713.c | |||
@@ -0,0 +1,250 @@ | |||
1 | /* | ||
2 | * Handles the Mitac mioa701 SoC system | ||
3 | * | ||
4 | * Copyright (C) 2008 Robert Jarzmik | ||
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 in version 2 of the License. | ||
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 | * This is a little schema of the sound interconnections : | ||
20 | * | ||
21 | * Sagem X200 Wolfson WM9713 | ||
22 | * +--------+ +-------------------+ Rear Speaker | ||
23 | * | | | | /-+ | ||
24 | * | +--->----->---+MONOIN SPKL+--->----+-+ | | ||
25 | * | GSM | | | | | | | ||
26 | * | +--->----->---+PCBEEP SPKR+--->----+-+ | | ||
27 | * | CHIP | | | \-+ | ||
28 | * | +---<-----<---+MONO | | ||
29 | * | | | | Front Speaker | ||
30 | * +--------+ | | /-+ | ||
31 | * | HPL+--->----+-+ | | ||
32 | * | | | | | | ||
33 | * | OUT3+--->----+-+ | | ||
34 | * | | \-+ | ||
35 | * | | | ||
36 | * | | Front Micro | ||
37 | * | | + | ||
38 | * | MIC1+-----<--+o+ | ||
39 | * | | + | ||
40 | * +-------------------+ --- | ||
41 | */ | ||
42 | |||
43 | #include <linux/module.h> | ||
44 | #include <linux/moduleparam.h> | ||
45 | #include <linux/platform_device.h> | ||
46 | |||
47 | #include <asm/mach-types.h> | ||
48 | #include <mach/audio.h> | ||
49 | |||
50 | #include <sound/core.h> | ||
51 | #include <sound/pcm.h> | ||
52 | #include <sound/soc.h> | ||
53 | #include <sound/soc-dapm.h> | ||
54 | #include <sound/initval.h> | ||
55 | #include <sound/ac97_codec.h> | ||
56 | |||
57 | #include "pxa2xx-pcm.h" | ||
58 | #include "pxa2xx-ac97.h" | ||
59 | #include "../codecs/wm9713.h" | ||
60 | |||
61 | #define ARRAY_AND_SIZE(x) (x), ARRAY_SIZE(x) | ||
62 | |||
63 | #define AC97_GPIO_PULL 0x58 | ||
64 | |||
65 | /* Use GPIO8 for rear speaker amplifier */ | ||
66 | static int rear_amp_power(struct snd_soc_codec *codec, int power) | ||
67 | { | ||
68 | unsigned short reg; | ||
69 | |||
70 | if (power) { | ||
71 | reg = snd_soc_read(codec, AC97_GPIO_CFG); | ||
72 | snd_soc_write(codec, AC97_GPIO_CFG, reg | 0x0100); | ||
73 | reg = snd_soc_read(codec, AC97_GPIO_PULL); | ||
74 | snd_soc_write(codec, AC97_GPIO_PULL, reg | (1<<15)); | ||
75 | } else { | ||
76 | reg = snd_soc_read(codec, AC97_GPIO_CFG); | ||
77 | snd_soc_write(codec, AC97_GPIO_CFG, reg & ~0x0100); | ||
78 | reg = snd_soc_read(codec, AC97_GPIO_PULL); | ||
79 | snd_soc_write(codec, AC97_GPIO_PULL, reg & ~(1<<15)); | ||
80 | } | ||
81 | |||
82 | return 0; | ||
83 | } | ||
84 | |||
85 | static int rear_amp_event(struct snd_soc_dapm_widget *widget, | ||
86 | struct snd_kcontrol *kctl, int event) | ||
87 | { | ||
88 | struct snd_soc_codec *codec = widget->codec; | ||
89 | |||
90 | return rear_amp_power(codec, SND_SOC_DAPM_EVENT_ON(event)); | ||
91 | } | ||
92 | |||
93 | /* mioa701 machine dapm widgets */ | ||
94 | static const struct snd_soc_dapm_widget mioa701_dapm_widgets[] = { | ||
95 | SND_SOC_DAPM_SPK("Front Speaker", NULL), | ||
96 | SND_SOC_DAPM_SPK("Rear Speaker", rear_amp_event), | ||
97 | SND_SOC_DAPM_MIC("Headset", NULL), | ||
98 | SND_SOC_DAPM_LINE("GSM Line Out", NULL), | ||
99 | SND_SOC_DAPM_LINE("GSM Line In", NULL), | ||
100 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | ||
101 | SND_SOC_DAPM_MIC("Front Mic", NULL), | ||
102 | }; | ||
103 | |||
104 | static const struct snd_soc_dapm_route audio_map[] = { | ||
105 | /* Call Mic */ | ||
106 | {"Mic Bias", NULL, "Front Mic"}, | ||
107 | {"MIC1", NULL, "Mic Bias"}, | ||
108 | |||
109 | /* Headset Mic */ | ||
110 | {"LINEL", NULL, "Headset Mic"}, | ||
111 | {"LINER", NULL, "Headset Mic"}, | ||
112 | |||
113 | /* GSM Module */ | ||
114 | {"MONOIN", NULL, "GSM Line Out"}, | ||
115 | {"PCBEEP", NULL, "GSM Line Out"}, | ||
116 | {"GSM Line In", NULL, "MONO"}, | ||
117 | |||
118 | /* headphone connected to HPL, HPR */ | ||
119 | {"Headset", NULL, "HPL"}, | ||
120 | {"Headset", NULL, "HPR"}, | ||
121 | |||
122 | /* front speaker connected to HPL, OUT3 */ | ||
123 | {"Front Speaker", NULL, "HPL"}, | ||
124 | {"Front Speaker", NULL, "OUT3"}, | ||
125 | |||
126 | /* rear speaker connected to SPKL, SPKR */ | ||
127 | {"Rear Speaker", NULL, "SPKL"}, | ||
128 | {"Rear Speaker", NULL, "SPKR"}, | ||
129 | }; | ||
130 | |||
131 | static int mioa701_wm9713_init(struct snd_soc_codec *codec) | ||
132 | { | ||
133 | unsigned short reg; | ||
134 | |||
135 | /* Add mioa701 specific widgets */ | ||
136 | snd_soc_dapm_new_controls(codec, ARRAY_AND_SIZE(mioa701_dapm_widgets)); | ||
137 | |||
138 | /* Set up mioa701 specific audio path audio_mapnects */ | ||
139 | snd_soc_dapm_add_routes(codec, ARRAY_AND_SIZE(audio_map)); | ||
140 | |||
141 | /* Prepare GPIO8 for rear speaker amplifier */ | ||
142 | reg = codec->read(codec, AC97_GPIO_CFG); | ||
143 | codec->write(codec, AC97_GPIO_CFG, reg | 0x0100); | ||
144 | |||
145 | /* Prepare MIC input */ | ||
146 | reg = codec->read(codec, AC97_3D_CONTROL); | ||
147 | codec->write(codec, AC97_3D_CONTROL, reg | 0xc000); | ||
148 | |||
149 | snd_soc_dapm_enable_pin(codec, "Front Speaker"); | ||
150 | snd_soc_dapm_enable_pin(codec, "Rear Speaker"); | ||
151 | snd_soc_dapm_enable_pin(codec, "Front Mic"); | ||
152 | snd_soc_dapm_enable_pin(codec, "GSM Line In"); | ||
153 | snd_soc_dapm_enable_pin(codec, "GSM Line Out"); | ||
154 | snd_soc_dapm_sync(codec); | ||
155 | |||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | static struct snd_soc_ops mioa701_ops; | ||
160 | |||
161 | static struct snd_soc_dai_link mioa701_dai[] = { | ||
162 | { | ||
163 | .name = "AC97", | ||
164 | .stream_name = "AC97 HiFi", | ||
165 | .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], | ||
166 | .codec_dai = &wm9713_dai[WM9713_DAI_AC97_HIFI], | ||
167 | .init = mioa701_wm9713_init, | ||
168 | .ops = &mioa701_ops, | ||
169 | }, | ||
170 | { | ||
171 | .name = "AC97 Aux", | ||
172 | .stream_name = "AC97 Aux", | ||
173 | .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], | ||
174 | .codec_dai = &wm9713_dai[WM9713_DAI_AC97_AUX], | ||
175 | .ops = &mioa701_ops, | ||
176 | }, | ||
177 | }; | ||
178 | |||
179 | static struct snd_soc_card mioa701 = { | ||
180 | .name = "MioA701", | ||
181 | .platform = &pxa2xx_soc_platform, | ||
182 | .dai_link = mioa701_dai, | ||
183 | .num_links = ARRAY_SIZE(mioa701_dai), | ||
184 | }; | ||
185 | |||
186 | static struct snd_soc_device mioa701_snd_devdata = { | ||
187 | .card = &mioa701, | ||
188 | .codec_dev = &soc_codec_dev_wm9713, | ||
189 | }; | ||
190 | |||
191 | static struct platform_device *mioa701_snd_device; | ||
192 | |||
193 | static int mioa701_wm9713_probe(struct platform_device *pdev) | ||
194 | { | ||
195 | int ret; | ||
196 | |||
197 | if (!machine_is_mioa701()) | ||
198 | return -ENODEV; | ||
199 | |||
200 | dev_warn(&pdev->dev, "Be warned that incorrect mixers/muxes setup will" | ||
201 | "lead to overheating and possible destruction of your device." | ||
202 | "Do not use without a good knowledge of mio's board design!\n"); | ||
203 | |||
204 | mioa701_snd_device = platform_device_alloc("soc-audio", -1); | ||
205 | if (!mioa701_snd_device) | ||
206 | return -ENOMEM; | ||
207 | |||
208 | platform_set_drvdata(mioa701_snd_device, &mioa701_snd_devdata); | ||
209 | mioa701_snd_devdata.dev = &mioa701_snd_device->dev; | ||
210 | |||
211 | ret = platform_device_add(mioa701_snd_device); | ||
212 | if (!ret) | ||
213 | return 0; | ||
214 | |||
215 | platform_device_put(mioa701_snd_device); | ||
216 | return ret; | ||
217 | } | ||
218 | |||
219 | static int __devexit mioa701_wm9713_remove(struct platform_device *pdev) | ||
220 | { | ||
221 | platform_device_unregister(mioa701_snd_device); | ||
222 | return 0; | ||
223 | } | ||
224 | |||
225 | static struct platform_driver mioa701_wm9713_driver = { | ||
226 | .probe = mioa701_wm9713_probe, | ||
227 | .remove = __devexit_p(mioa701_wm9713_remove), | ||
228 | .driver = { | ||
229 | .name = "mioa701-wm9713", | ||
230 | .owner = THIS_MODULE, | ||
231 | }, | ||
232 | }; | ||
233 | |||
234 | static int __init mioa701_asoc_init(void) | ||
235 | { | ||
236 | return platform_driver_register(&mioa701_wm9713_driver); | ||
237 | } | ||
238 | |||
239 | static void __exit mioa701_asoc_exit(void) | ||
240 | { | ||
241 | platform_driver_unregister(&mioa701_wm9713_driver); | ||
242 | } | ||
243 | |||
244 | module_init(mioa701_asoc_init); | ||
245 | module_exit(mioa701_asoc_exit); | ||
246 | |||
247 | /* Module information */ | ||
248 | MODULE_AUTHOR("Robert Jarzmik (rjarzmik@free.fr)"); | ||
249 | MODULE_DESCRIPTION("ALSA SoC WM9713 MIO A701"); | ||
250 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/pxa/palm27x.c b/sound/soc/pxa/palm27x.c index 4a9cf3083af0..48a73f64500b 100644 --- a/sound/soc/pxa/palm27x.c +++ b/sound/soc/pxa/palm27x.c | |||
@@ -55,7 +55,7 @@ static void palm27x_ext_control(struct snd_soc_codec *codec) | |||
55 | static int palm27x_startup(struct snd_pcm_substream *substream) | 55 | static int palm27x_startup(struct snd_pcm_substream *substream) |
56 | { | 56 | { |
57 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 57 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
58 | struct snd_soc_codec *codec = rtd->socdev->codec; | 58 | struct snd_soc_codec *codec = rtd->socdev->card->codec; |
59 | 59 | ||
60 | /* check the jack status at stream startup */ | 60 | /* check the jack status at stream startup */ |
61 | palm27x_ext_control(codec); | 61 | palm27x_ext_control(codec); |
@@ -146,19 +146,16 @@ static const struct snd_kcontrol_new palm27x_controls[] = { | |||
146 | 146 | ||
147 | static int palm27x_ac97_init(struct snd_soc_codec *codec) | 147 | static int palm27x_ac97_init(struct snd_soc_codec *codec) |
148 | { | 148 | { |
149 | int i, err; | 149 | int err; |
150 | 150 | ||
151 | snd_soc_dapm_nc_pin(codec, "OUT3"); | 151 | snd_soc_dapm_nc_pin(codec, "OUT3"); |
152 | snd_soc_dapm_nc_pin(codec, "MONOOUT"); | 152 | snd_soc_dapm_nc_pin(codec, "MONOOUT"); |
153 | 153 | ||
154 | /* add palm27x specific controls */ | 154 | /* add palm27x specific controls */ |
155 | for (i = 0; i < ARRAY_SIZE(palm27x_controls); i++) { | 155 | err = snd_soc_add_controls(codec, palm27x_controls, |
156 | err = snd_ctl_add(codec->card, | 156 | ARRAY_SIZE(palm27x_controls)); |
157 | snd_soc_cnew(&palm27x_controls[i], | 157 | if (err < 0) |
158 | codec, NULL)); | 158 | return err; |
159 | if (err < 0) | ||
160 | return err; | ||
161 | } | ||
162 | 159 | ||
163 | /* add palm27x specific widgets */ | 160 | /* add palm27x specific widgets */ |
164 | snd_soc_dapm_new_controls(codec, palm27x_dapm_widgets, | 161 | snd_soc_dapm_new_controls(codec, palm27x_dapm_widgets, |
diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c index cad2c4c0ac95..a51058f66747 100644 --- a/sound/soc/pxa/poodle.c +++ b/sound/soc/pxa/poodle.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/moduleparam.h> | 18 | #include <linux/moduleparam.h> |
19 | #include <linux/timer.h> | 19 | #include <linux/timer.h> |
20 | #include <linux/i2c.h> | ||
20 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
21 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
22 | #include <sound/core.h> | 23 | #include <sound/core.h> |
@@ -75,7 +76,7 @@ static void poodle_ext_control(struct snd_soc_codec *codec) | |||
75 | static int poodle_startup(struct snd_pcm_substream *substream) | 76 | static int poodle_startup(struct snd_pcm_substream *substream) |
76 | { | 77 | { |
77 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 78 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
78 | struct snd_soc_codec *codec = rtd->socdev->codec; | 79 | struct snd_soc_codec *codec = rtd->socdev->card->codec; |
79 | 80 | ||
80 | /* check the jack status at stream startup */ | 81 | /* check the jack status at stream startup */ |
81 | poodle_ext_control(codec); | 82 | poodle_ext_control(codec); |
@@ -238,19 +239,17 @@ static const struct snd_kcontrol_new wm8731_poodle_controls[] = { | |||
238 | */ | 239 | */ |
239 | static int poodle_wm8731_init(struct snd_soc_codec *codec) | 240 | static int poodle_wm8731_init(struct snd_soc_codec *codec) |
240 | { | 241 | { |
241 | int i, err; | 242 | int err; |
242 | 243 | ||
243 | snd_soc_dapm_nc_pin(codec, "LLINEIN"); | 244 | snd_soc_dapm_nc_pin(codec, "LLINEIN"); |
244 | snd_soc_dapm_nc_pin(codec, "RLINEIN"); | 245 | snd_soc_dapm_nc_pin(codec, "RLINEIN"); |
245 | snd_soc_dapm_enable_pin(codec, "MICIN"); | 246 | snd_soc_dapm_enable_pin(codec, "MICIN"); |
246 | 247 | ||
247 | /* Add poodle specific controls */ | 248 | /* Add poodle specific controls */ |
248 | for (i = 0; i < ARRAY_SIZE(wm8731_poodle_controls); i++) { | 249 | err = snd_soc_add_controls(codec, wm8731_poodle_controls, |
249 | err = snd_ctl_add(codec->card, | 250 | ARRAY_SIZE(wm8731_poodle_controls)); |
250 | snd_soc_cnew(&wm8731_poodle_controls[i], codec, NULL)); | 251 | if (err < 0) |
251 | if (err < 0) | 252 | return err; |
252 | return err; | ||
253 | } | ||
254 | 253 | ||
255 | /* Add poodle specific widgets */ | 254 | /* Add poodle specific widgets */ |
256 | snd_soc_dapm_new_controls(codec, wm8731_dapm_widgets, | 255 | snd_soc_dapm_new_controls(codec, wm8731_dapm_widgets, |
@@ -281,17 +280,42 @@ static struct snd_soc_card snd_soc_poodle = { | |||
281 | .num_links = 1, | 280 | .num_links = 1, |
282 | }; | 281 | }; |
283 | 282 | ||
284 | /* poodle audio private data */ | 283 | /* |
285 | static struct wm8731_setup_data poodle_wm8731_setup = { | 284 | * FIXME: This is a temporary bodge to avoid cross-tree merge issues. |
286 | .i2c_bus = 0, | 285 | * New drivers should register the wm8731 I2C device in the machine |
287 | .i2c_address = 0x1b, | 286 | * setup code (under arch/arm for ARM systems). |
288 | }; | 287 | */ |
288 | static int wm8731_i2c_register(void) | ||
289 | { | ||
290 | struct i2c_board_info info; | ||
291 | struct i2c_adapter *adapter; | ||
292 | struct i2c_client *client; | ||
293 | |||
294 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
295 | info.addr = 0x1b; | ||
296 | strlcpy(info.type, "wm8731", I2C_NAME_SIZE); | ||
297 | |||
298 | adapter = i2c_get_adapter(0); | ||
299 | if (!adapter) { | ||
300 | printk(KERN_ERR "can't get i2c adapter 0\n"); | ||
301 | return -ENODEV; | ||
302 | } | ||
303 | |||
304 | client = i2c_new_device(adapter, &info); | ||
305 | i2c_put_adapter(adapter); | ||
306 | if (!client) { | ||
307 | printk(KERN_ERR "can't add i2c device at 0x%x\n", | ||
308 | (unsigned int)info.addr); | ||
309 | return -ENODEV; | ||
310 | } | ||
311 | |||
312 | return 0; | ||
313 | } | ||
289 | 314 | ||
290 | /* poodle audio subsystem */ | 315 | /* poodle audio subsystem */ |
291 | static struct snd_soc_device poodle_snd_devdata = { | 316 | static struct snd_soc_device poodle_snd_devdata = { |
292 | .card = &snd_soc_poodle, | 317 | .card = &snd_soc_poodle, |
293 | .codec_dev = &soc_codec_dev_wm8731, | 318 | .codec_dev = &soc_codec_dev_wm8731, |
294 | .codec_data = &poodle_wm8731_setup, | ||
295 | }; | 319 | }; |
296 | 320 | ||
297 | static struct platform_device *poodle_snd_device; | 321 | static struct platform_device *poodle_snd_device; |
@@ -303,6 +327,10 @@ static int __init poodle_init(void) | |||
303 | if (!machine_is_poodle()) | 327 | if (!machine_is_poodle()) |
304 | return -ENODEV; | 328 | return -ENODEV; |
305 | 329 | ||
330 | ret = wm8731_i2c_register(); | ||
331 | if (ret != 0) | ||
332 | return ret; | ||
333 | |||
306 | locomo_gpio_set_dir(&poodle_locomo_device.dev, | 334 | locomo_gpio_set_dir(&poodle_locomo_device.dev, |
307 | POODLE_LOCOMO_GPIO_AMP_ON, 0); | 335 | POODLE_LOCOMO_GPIO_AMP_ON, 0); |
308 | /* should we mute HP at startup - burning power ?*/ | 336 | /* should we mute HP at startup - burning power ?*/ |
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index 1dfdf66fb1f3..7acd3febf8b0 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c | |||
@@ -1,4 +1,3 @@ | |||
1 | #define DEBUG | ||
2 | /* | 1 | /* |
3 | * pxa-ssp.c -- ALSA Soc Audio Layer | 2 | * pxa-ssp.c -- ALSA Soc Audio Layer |
4 | * | 3 | * |
@@ -21,6 +20,8 @@ | |||
21 | #include <linux/clk.h> | 20 | #include <linux/clk.h> |
22 | #include <linux/io.h> | 21 | #include <linux/io.h> |
23 | 22 | ||
23 | #include <asm/irq.h> | ||
24 | |||
24 | #include <sound/core.h> | 25 | #include <sound/core.h> |
25 | #include <sound/pcm.h> | 26 | #include <sound/pcm.h> |
26 | #include <sound/initval.h> | 27 | #include <sound/initval.h> |
@@ -221,9 +222,9 @@ static int pxa_ssp_startup(struct snd_pcm_substream *substream, | |||
221 | int ret = 0; | 222 | int ret = 0; |
222 | 223 | ||
223 | if (!cpu_dai->active) { | 224 | if (!cpu_dai->active) { |
224 | ret = ssp_init(&priv->dev, cpu_dai->id + 1, SSP_NO_IRQ); | 225 | priv->dev.port = cpu_dai->id + 1; |
225 | if (ret < 0) | 226 | priv->dev.irq = NO_IRQ; |
226 | return ret; | 227 | clk_enable(priv->dev.ssp->clk); |
227 | ssp_disable(&priv->dev); | 228 | ssp_disable(&priv->dev); |
228 | } | 229 | } |
229 | return ret; | 230 | return ret; |
@@ -238,7 +239,7 @@ static void pxa_ssp_shutdown(struct snd_pcm_substream *substream, | |||
238 | 239 | ||
239 | if (!cpu_dai->active) { | 240 | if (!cpu_dai->active) { |
240 | ssp_disable(&priv->dev); | 241 | ssp_disable(&priv->dev); |
241 | ssp_exit(&priv->dev); | 242 | clk_disable(priv->dev.ssp->clk); |
242 | } | 243 | } |
243 | } | 244 | } |
244 | 245 | ||
@@ -298,7 +299,7 @@ static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai, | |||
298 | int val; | 299 | int val; |
299 | 300 | ||
300 | u32 sscr0 = ssp_read_reg(ssp, SSCR0) & | 301 | u32 sscr0 = ssp_read_reg(ssp, SSCR0) & |
301 | ~(SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ADC); | 302 | ~(SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ACS); |
302 | 303 | ||
303 | dev_dbg(&ssp->pdev->dev, | 304 | dev_dbg(&ssp->pdev->dev, |
304 | "pxa_ssp_set_dai_sysclk id: %d, clk_id %d, freq %d\n", | 305 | "pxa_ssp_set_dai_sysclk id: %d, clk_id %d, freq %d\n", |
@@ -326,7 +327,7 @@ static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai, | |||
326 | case PXA_SSP_CLK_AUDIO: | 327 | case PXA_SSP_CLK_AUDIO: |
327 | priv->sysclk = 0; | 328 | priv->sysclk = 0; |
328 | ssp_set_scr(&priv->dev, 1); | 329 | ssp_set_scr(&priv->dev, 1); |
329 | sscr0 |= SSCR0_ADC; | 330 | sscr0 |= SSCR0_ACS; |
330 | break; | 331 | break; |
331 | default: | 332 | default: |
332 | return -ENODEV; | 333 | return -ENODEV; |
@@ -520,9 +521,20 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai, | |||
520 | u32 sscr1; | 521 | u32 sscr1; |
521 | u32 sspsp; | 522 | u32 sspsp; |
522 | 523 | ||
524 | /* check if we need to change anything at all */ | ||
525 | if (priv->dai_fmt == fmt) | ||
526 | return 0; | ||
527 | |||
528 | /* we can only change the settings if the port is not in use */ | ||
529 | if (ssp_read_reg(ssp, SSCR0) & SSCR0_SSE) { | ||
530 | dev_err(&ssp->pdev->dev, | ||
531 | "can't change hardware dai format: stream is in use"); | ||
532 | return -EINVAL; | ||
533 | } | ||
534 | |||
523 | /* reset port settings */ | 535 | /* reset port settings */ |
524 | sscr0 = ssp_read_reg(ssp, SSCR0) & | 536 | sscr0 = ssp_read_reg(ssp, SSCR0) & |
525 | (SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ADC); | 537 | (SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ACS); |
526 | sscr1 = SSCR1_RxTresh(8) | SSCR1_TxTresh(7); | 538 | sscr1 = SSCR1_RxTresh(8) | SSCR1_TxTresh(7); |
527 | sspsp = 0; | 539 | sspsp = 0; |
528 | 540 | ||
@@ -545,18 +557,18 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai, | |||
545 | 557 | ||
546 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | 558 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
547 | case SND_SOC_DAIFMT_I2S: | 559 | case SND_SOC_DAIFMT_I2S: |
548 | sscr0 |= SSCR0_MOD | SSCR0_PSP; | 560 | sscr0 |= SSCR0_PSP; |
549 | sscr1 |= SSCR1_RWOT | SSCR1_TRAIL; | 561 | sscr1 |= SSCR1_RWOT | SSCR1_TRAIL; |
550 | 562 | ||
563 | /* See hw_params() */ | ||
551 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | 564 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { |
552 | case SND_SOC_DAIFMT_NB_NF: | 565 | case SND_SOC_DAIFMT_NB_NF: |
553 | sspsp |= SSPSP_FSRT; | 566 | sspsp |= SSPSP_SFRMP; |
554 | break; | 567 | break; |
555 | case SND_SOC_DAIFMT_NB_IF: | 568 | case SND_SOC_DAIFMT_NB_IF: |
556 | sspsp |= SSPSP_SFRMP | SSPSP_FSRT; | ||
557 | break; | 569 | break; |
558 | case SND_SOC_DAIFMT_IB_IF: | 570 | case SND_SOC_DAIFMT_IB_IF: |
559 | sspsp |= SSPSP_SFRMP; | 571 | sspsp |= SSPSP_SCMODE(3); |
560 | break; | 572 | break; |
561 | default: | 573 | default: |
562 | return -EINVAL; | 574 | return -EINVAL; |
@@ -642,34 +654,65 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream, | |||
642 | sscr0 |= SSCR0_FPCKE; | 654 | sscr0 |= SSCR0_FPCKE; |
643 | #endif | 655 | #endif |
644 | sscr0 |= SSCR0_DataSize(16); | 656 | sscr0 |= SSCR0_DataSize(16); |
645 | if (params_channels(params) > 1) | ||
646 | sscr0 |= SSCR0_EDSS; | ||
647 | break; | 657 | break; |
648 | case SNDRV_PCM_FORMAT_S24_LE: | 658 | case SNDRV_PCM_FORMAT_S24_LE: |
649 | sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(8)); | 659 | sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(8)); |
650 | /* we must be in network mode (2 slots) for 24 bit stereo */ | ||
651 | break; | 660 | break; |
652 | case SNDRV_PCM_FORMAT_S32_LE: | 661 | case SNDRV_PCM_FORMAT_S32_LE: |
653 | sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(16)); | 662 | sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(16)); |
654 | /* we must be in network mode (2 slots) for 32 bit stereo */ | ||
655 | break; | 663 | break; |
656 | } | 664 | } |
657 | ssp_write_reg(ssp, SSCR0, sscr0); | 665 | ssp_write_reg(ssp, SSCR0, sscr0); |
658 | 666 | ||
659 | switch (priv->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | 667 | switch (priv->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
660 | case SND_SOC_DAIFMT_I2S: | 668 | case SND_SOC_DAIFMT_I2S: |
661 | /* Cleared when the DAI format is set */ | 669 | sspsp = ssp_read_reg(ssp, SSPSP); |
662 | sspsp = ssp_read_reg(ssp, SSPSP) | SSPSP_SFRMWDTH(width); | 670 | |
671 | if (((sscr0 & SSCR0_SCR) == SSCR0_SerClkDiv(4)) && | ||
672 | (width == 16)) { | ||
673 | /* This is a special case where the bitclk is 64fs | ||
674 | * and we're not dealing with 2*32 bits of audio | ||
675 | * samples. | ||
676 | * | ||
677 | * The SSP values used for that are all found out by | ||
678 | * trying and failing a lot; some of the registers | ||
679 | * needed for that mode are only available on PXA3xx. | ||
680 | */ | ||
681 | |||
682 | #ifdef CONFIG_PXA3xx | ||
683 | if (!cpu_is_pxa3xx()) | ||
684 | return -EINVAL; | ||
685 | |||
686 | sspsp |= SSPSP_SFRMWDTH(width * 2); | ||
687 | sspsp |= SSPSP_SFRMDLY(width * 4); | ||
688 | sspsp |= SSPSP_EDMYSTOP(3); | ||
689 | sspsp |= SSPSP_DMYSTOP(3); | ||
690 | sspsp |= SSPSP_DMYSTRT(1); | ||
691 | #else | ||
692 | return -EINVAL; | ||
693 | #endif | ||
694 | } else { | ||
695 | /* The frame width is the width the LRCLK is | ||
696 | * asserted for; the delay is expressed in | ||
697 | * half cycle units. We need the extra cycle | ||
698 | * because the data starts clocking out one BCLK | ||
699 | * after LRCLK changes polarity. | ||
700 | */ | ||
701 | sspsp |= SSPSP_SFRMWDTH(width + 1); | ||
702 | sspsp |= SSPSP_SFRMDLY((width + 1) * 2); | ||
703 | sspsp |= SSPSP_DMYSTRT(1); | ||
704 | } | ||
705 | |||
663 | ssp_write_reg(ssp, SSPSP, sspsp); | 706 | ssp_write_reg(ssp, SSPSP, sspsp); |
664 | break; | 707 | break; |
665 | default: | 708 | default: |
666 | break; | 709 | break; |
667 | } | 710 | } |
668 | 711 | ||
669 | /* We always use a network mode so we always require TDM slots | 712 | /* When we use a network mode, we always require TDM slots |
670 | * - complain loudly and fail if they've not been set up yet. | 713 | * - complain loudly and fail if they've not been set up yet. |
671 | */ | 714 | */ |
672 | if (!(ssp_read_reg(ssp, SSTSA) & 0xf)) { | 715 | if ((sscr0 & SSCR0_MOD) && !(ssp_read_reg(ssp, SSTSA) & 0xf)) { |
673 | dev_err(&ssp->pdev->dev, "No TDM timeslot configured\n"); | 716 | dev_err(&ssp->pdev->dev, "No TDM timeslot configured\n"); |
674 | return -EINVAL; | 717 | return -EINVAL; |
675 | } | 718 | } |
@@ -751,7 +794,7 @@ static int pxa_ssp_probe(struct platform_device *pdev, | |||
751 | if (!priv) | 794 | if (!priv) |
752 | return -ENOMEM; | 795 | return -ENOMEM; |
753 | 796 | ||
754 | priv->dev.ssp = ssp_request(dai->id, "SoC audio"); | 797 | priv->dev.ssp = ssp_request(dai->id + 1, "SoC audio"); |
755 | if (priv->dev.ssp == NULL) { | 798 | if (priv->dev.ssp == NULL) { |
756 | ret = -ENODEV; | 799 | ret = -ENODEV; |
757 | goto err_priv; | 800 | goto err_priv; |
@@ -782,6 +825,19 @@ static void pxa_ssp_remove(struct platform_device *pdev, | |||
782 | SNDRV_PCM_FMTBIT_S24_LE | \ | 825 | SNDRV_PCM_FMTBIT_S24_LE | \ |
783 | SNDRV_PCM_FMTBIT_S32_LE) | 826 | SNDRV_PCM_FMTBIT_S32_LE) |
784 | 827 | ||
828 | static struct snd_soc_dai_ops pxa_ssp_dai_ops = { | ||
829 | .startup = pxa_ssp_startup, | ||
830 | .shutdown = pxa_ssp_shutdown, | ||
831 | .trigger = pxa_ssp_trigger, | ||
832 | .hw_params = pxa_ssp_hw_params, | ||
833 | .set_sysclk = pxa_ssp_set_dai_sysclk, | ||
834 | .set_clkdiv = pxa_ssp_set_dai_clkdiv, | ||
835 | .set_pll = pxa_ssp_set_dai_pll, | ||
836 | .set_fmt = pxa_ssp_set_dai_fmt, | ||
837 | .set_tdm_slot = pxa_ssp_set_dai_tdm_slot, | ||
838 | .set_tristate = pxa_ssp_set_dai_tristate, | ||
839 | }; | ||
840 | |||
785 | struct snd_soc_dai pxa_ssp_dai[] = { | 841 | struct snd_soc_dai pxa_ssp_dai[] = { |
786 | { | 842 | { |
787 | .name = "pxa2xx-ssp1", | 843 | .name = "pxa2xx-ssp1", |
@@ -802,18 +858,7 @@ struct snd_soc_dai pxa_ssp_dai[] = { | |||
802 | .rates = PXA_SSP_RATES, | 858 | .rates = PXA_SSP_RATES, |
803 | .formats = PXA_SSP_FORMATS, | 859 | .formats = PXA_SSP_FORMATS, |
804 | }, | 860 | }, |
805 | .ops = { | 861 | .ops = &pxa_ssp_dai_ops, |
806 | .startup = pxa_ssp_startup, | ||
807 | .shutdown = pxa_ssp_shutdown, | ||
808 | .trigger = pxa_ssp_trigger, | ||
809 | .hw_params = pxa_ssp_hw_params, | ||
810 | .set_sysclk = pxa_ssp_set_dai_sysclk, | ||
811 | .set_clkdiv = pxa_ssp_set_dai_clkdiv, | ||
812 | .set_pll = pxa_ssp_set_dai_pll, | ||
813 | .set_fmt = pxa_ssp_set_dai_fmt, | ||
814 | .set_tdm_slot = pxa_ssp_set_dai_tdm_slot, | ||
815 | .set_tristate = pxa_ssp_set_dai_tristate, | ||
816 | }, | ||
817 | }, | 862 | }, |
818 | { .name = "pxa2xx-ssp2", | 863 | { .name = "pxa2xx-ssp2", |
819 | .id = 1, | 864 | .id = 1, |
@@ -833,18 +878,7 @@ struct snd_soc_dai pxa_ssp_dai[] = { | |||
833 | .rates = PXA_SSP_RATES, | 878 | .rates = PXA_SSP_RATES, |
834 | .formats = PXA_SSP_FORMATS, | 879 | .formats = PXA_SSP_FORMATS, |
835 | }, | 880 | }, |
836 | .ops = { | 881 | .ops = &pxa_ssp_dai_ops, |
837 | .startup = pxa_ssp_startup, | ||
838 | .shutdown = pxa_ssp_shutdown, | ||
839 | .trigger = pxa_ssp_trigger, | ||
840 | .hw_params = pxa_ssp_hw_params, | ||
841 | .set_sysclk = pxa_ssp_set_dai_sysclk, | ||
842 | .set_clkdiv = pxa_ssp_set_dai_clkdiv, | ||
843 | .set_pll = pxa_ssp_set_dai_pll, | ||
844 | .set_fmt = pxa_ssp_set_dai_fmt, | ||
845 | .set_tdm_slot = pxa_ssp_set_dai_tdm_slot, | ||
846 | .set_tristate = pxa_ssp_set_dai_tristate, | ||
847 | }, | ||
848 | }, | 882 | }, |
849 | { | 883 | { |
850 | .name = "pxa2xx-ssp3", | 884 | .name = "pxa2xx-ssp3", |
@@ -865,18 +899,7 @@ struct snd_soc_dai pxa_ssp_dai[] = { | |||
865 | .rates = PXA_SSP_RATES, | 899 | .rates = PXA_SSP_RATES, |
866 | .formats = PXA_SSP_FORMATS, | 900 | .formats = PXA_SSP_FORMATS, |
867 | }, | 901 | }, |
868 | .ops = { | 902 | .ops = &pxa_ssp_dai_ops, |
869 | .startup = pxa_ssp_startup, | ||
870 | .shutdown = pxa_ssp_shutdown, | ||
871 | .trigger = pxa_ssp_trigger, | ||
872 | .hw_params = pxa_ssp_hw_params, | ||
873 | .set_sysclk = pxa_ssp_set_dai_sysclk, | ||
874 | .set_clkdiv = pxa_ssp_set_dai_clkdiv, | ||
875 | .set_pll = pxa_ssp_set_dai_pll, | ||
876 | .set_fmt = pxa_ssp_set_dai_fmt, | ||
877 | .set_tdm_slot = pxa_ssp_set_dai_tdm_slot, | ||
878 | .set_tristate = pxa_ssp_set_dai_tristate, | ||
879 | }, | ||
880 | }, | 903 | }, |
881 | { | 904 | { |
882 | .name = "pxa2xx-ssp4", | 905 | .name = "pxa2xx-ssp4", |
@@ -897,18 +920,7 @@ struct snd_soc_dai pxa_ssp_dai[] = { | |||
897 | .rates = PXA_SSP_RATES, | 920 | .rates = PXA_SSP_RATES, |
898 | .formats = PXA_SSP_FORMATS, | 921 | .formats = PXA_SSP_FORMATS, |
899 | }, | 922 | }, |
900 | .ops = { | 923 | .ops = &pxa_ssp_dai_ops, |
901 | .startup = pxa_ssp_startup, | ||
902 | .shutdown = pxa_ssp_shutdown, | ||
903 | .trigger = pxa_ssp_trigger, | ||
904 | .hw_params = pxa_ssp_hw_params, | ||
905 | .set_sysclk = pxa_ssp_set_dai_sysclk, | ||
906 | .set_clkdiv = pxa_ssp_set_dai_clkdiv, | ||
907 | .set_pll = pxa_ssp_set_dai_pll, | ||
908 | .set_fmt = pxa_ssp_set_dai_fmt, | ||
909 | .set_tdm_slot = pxa_ssp_set_dai_tdm_slot, | ||
910 | .set_tristate = pxa_ssp_set_dai_tristate, | ||
911 | }, | ||
912 | }, | 924 | }, |
913 | }; | 925 | }; |
914 | EXPORT_SYMBOL_GPL(pxa_ssp_dai); | 926 | EXPORT_SYMBOL_GPL(pxa_ssp_dai); |
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c index a4a655f7e304..d9c94d71fa61 100644 --- a/sound/soc/pxa/pxa2xx-ac97.c +++ b/sound/soc/pxa/pxa2xx-ac97.c | |||
@@ -106,13 +106,13 @@ static int pxa2xx_ac97_resume(struct snd_soc_dai *dai) | |||
106 | static int pxa2xx_ac97_probe(struct platform_device *pdev, | 106 | static int pxa2xx_ac97_probe(struct platform_device *pdev, |
107 | struct snd_soc_dai *dai) | 107 | struct snd_soc_dai *dai) |
108 | { | 108 | { |
109 | return pxa2xx_ac97_hw_probe(pdev); | 109 | return pxa2xx_ac97_hw_probe(to_platform_device(dai->dev)); |
110 | } | 110 | } |
111 | 111 | ||
112 | static void pxa2xx_ac97_remove(struct platform_device *pdev, | 112 | static void pxa2xx_ac97_remove(struct platform_device *pdev, |
113 | struct snd_soc_dai *dai) | 113 | struct snd_soc_dai *dai) |
114 | { | 114 | { |
115 | pxa2xx_ac97_hw_remove(pdev); | 115 | pxa2xx_ac97_hw_remove(to_platform_device(dai->dev)); |
116 | } | 116 | } |
117 | 117 | ||
118 | static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream, | 118 | static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream, |
@@ -164,6 +164,18 @@ static int pxa2xx_ac97_hw_mic_params(struct snd_pcm_substream *substream, | |||
164 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \ | 164 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \ |
165 | SNDRV_PCM_RATE_48000) | 165 | SNDRV_PCM_RATE_48000) |
166 | 166 | ||
167 | static struct snd_soc_dai_ops pxa_ac97_hifi_dai_ops = { | ||
168 | .hw_params = pxa2xx_ac97_hw_params, | ||
169 | }; | ||
170 | |||
171 | static struct snd_soc_dai_ops pxa_ac97_aux_dai_ops = { | ||
172 | .hw_params = pxa2xx_ac97_hw_aux_params, | ||
173 | }; | ||
174 | |||
175 | static struct snd_soc_dai_ops pxa_ac97_mic_dai_ops = { | ||
176 | .hw_params = pxa2xx_ac97_hw_mic_params, | ||
177 | }; | ||
178 | |||
167 | /* | 179 | /* |
168 | * There is only 1 physical AC97 interface for pxa2xx, but it | 180 | * There is only 1 physical AC97 interface for pxa2xx, but it |
169 | * has extra fifo's that can be used for aux DACs and ADCs. | 181 | * has extra fifo's that can be used for aux DACs and ADCs. |
@@ -189,8 +201,7 @@ struct snd_soc_dai pxa_ac97_dai[] = { | |||
189 | .channels_max = 2, | 201 | .channels_max = 2, |
190 | .rates = PXA2XX_AC97_RATES, | 202 | .rates = PXA2XX_AC97_RATES, |
191 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | 203 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, |
192 | .ops = { | 204 | .ops = &pxa_ac97_hifi_dai_ops, |
193 | .hw_params = pxa2xx_ac97_hw_params,}, | ||
194 | }, | 205 | }, |
195 | { | 206 | { |
196 | .name = "pxa2xx-ac97-aux", | 207 | .name = "pxa2xx-ac97-aux", |
@@ -208,8 +219,7 @@ struct snd_soc_dai pxa_ac97_dai[] = { | |||
208 | .channels_max = 1, | 219 | .channels_max = 1, |
209 | .rates = PXA2XX_AC97_RATES, | 220 | .rates = PXA2XX_AC97_RATES, |
210 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | 221 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, |
211 | .ops = { | 222 | .ops = &pxa_ac97_aux_dai_ops, |
212 | .hw_params = pxa2xx_ac97_hw_aux_params,}, | ||
213 | }, | 223 | }, |
214 | { | 224 | { |
215 | .name = "pxa2xx-ac97-mic", | 225 | .name = "pxa2xx-ac97-mic", |
@@ -221,23 +231,52 @@ struct snd_soc_dai pxa_ac97_dai[] = { | |||
221 | .channels_max = 1, | 231 | .channels_max = 1, |
222 | .rates = PXA2XX_AC97_RATES, | 232 | .rates = PXA2XX_AC97_RATES, |
223 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | 233 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, |
224 | .ops = { | 234 | .ops = &pxa_ac97_mic_dai_ops, |
225 | .hw_params = pxa2xx_ac97_hw_mic_params,}, | ||
226 | }, | 235 | }, |
227 | }; | 236 | }; |
228 | 237 | ||
229 | EXPORT_SYMBOL_GPL(pxa_ac97_dai); | 238 | EXPORT_SYMBOL_GPL(pxa_ac97_dai); |
230 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | 239 | EXPORT_SYMBOL_GPL(soc_ac97_ops); |
231 | 240 | ||
232 | static int __init pxa_ac97_init(void) | 241 | static int __devinit pxa2xx_ac97_dev_probe(struct platform_device *pdev) |
233 | { | 242 | { |
243 | int i; | ||
244 | |||
245 | for (i = 0; i < ARRAY_SIZE(pxa_ac97_dai); i++) | ||
246 | pxa_ac97_dai[i].dev = &pdev->dev; | ||
247 | |||
248 | /* Punt most of the init to the SoC probe; we may need the machine | ||
249 | * driver to do interesting things with the clocking to get us up | ||
250 | * and running. | ||
251 | */ | ||
234 | return snd_soc_register_dais(pxa_ac97_dai, ARRAY_SIZE(pxa_ac97_dai)); | 252 | return snd_soc_register_dais(pxa_ac97_dai, ARRAY_SIZE(pxa_ac97_dai)); |
235 | } | 253 | } |
254 | |||
255 | static int __devexit pxa2xx_ac97_dev_remove(struct platform_device *pdev) | ||
256 | { | ||
257 | snd_soc_unregister_dais(pxa_ac97_dai, ARRAY_SIZE(pxa_ac97_dai)); | ||
258 | |||
259 | return 0; | ||
260 | } | ||
261 | |||
262 | static struct platform_driver pxa2xx_ac97_driver = { | ||
263 | .probe = pxa2xx_ac97_dev_probe, | ||
264 | .remove = __devexit_p(pxa2xx_ac97_dev_remove), | ||
265 | .driver = { | ||
266 | .name = "pxa2xx-ac97", | ||
267 | .owner = THIS_MODULE, | ||
268 | }, | ||
269 | }; | ||
270 | |||
271 | static int __init pxa_ac97_init(void) | ||
272 | { | ||
273 | return platform_driver_register(&pxa2xx_ac97_driver); | ||
274 | } | ||
236 | module_init(pxa_ac97_init); | 275 | module_init(pxa_ac97_init); |
237 | 276 | ||
238 | static void __exit pxa_ac97_exit(void) | 277 | static void __exit pxa_ac97_exit(void) |
239 | { | 278 | { |
240 | snd_soc_unregister_dais(pxa_ac97_dai, ARRAY_SIZE(pxa_ac97_dai)); | 279 | platform_driver_unregister(&pxa2xx_ac97_driver); |
241 | } | 280 | } |
242 | module_exit(pxa_ac97_exit); | 281 | module_exit(pxa_ac97_exit); |
243 | 282 | ||
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c index 223de890259e..2f4b6e489b78 100644 --- a/sound/soc/pxa/pxa2xx-i2s.c +++ b/sound/soc/pxa/pxa2xx-i2s.c | |||
@@ -25,20 +25,11 @@ | |||
25 | 25 | ||
26 | #include <mach/hardware.h> | 26 | #include <mach/hardware.h> |
27 | #include <mach/dma.h> | 27 | #include <mach/dma.h> |
28 | #include <mach/pxa2xx-gpio.h> | ||
29 | #include <mach/audio.h> | 28 | #include <mach/audio.h> |
30 | 29 | ||
31 | #include "pxa2xx-pcm.h" | 30 | #include "pxa2xx-pcm.h" |
32 | #include "pxa2xx-i2s.h" | 31 | #include "pxa2xx-i2s.h" |
33 | 32 | ||
34 | struct pxa2xx_gpio { | ||
35 | u32 sys; | ||
36 | u32 rx; | ||
37 | u32 tx; | ||
38 | u32 clk; | ||
39 | u32 frm; | ||
40 | }; | ||
41 | |||
42 | /* | 33 | /* |
43 | * I2S Controller Register and Bit Definitions | 34 | * I2S Controller Register and Bit Definitions |
44 | */ | 35 | */ |
@@ -106,21 +97,6 @@ static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_in = { | |||
106 | DCMD_BURST32 | DCMD_WIDTH4, | 97 | DCMD_BURST32 | DCMD_WIDTH4, |
107 | }; | 98 | }; |
108 | 99 | ||
109 | static struct pxa2xx_gpio gpio_bus[] = { | ||
110 | { /* I2S SoC Slave */ | ||
111 | .rx = GPIO29_SDATA_IN_I2S_MD, | ||
112 | .tx = GPIO30_SDATA_OUT_I2S_MD, | ||
113 | .clk = GPIO28_BITCLK_IN_I2S_MD, | ||
114 | .frm = GPIO31_SYNC_I2S_MD, | ||
115 | }, | ||
116 | { /* I2S SoC Master */ | ||
117 | .rx = GPIO29_SDATA_IN_I2S_MD, | ||
118 | .tx = GPIO30_SDATA_OUT_I2S_MD, | ||
119 | .clk = GPIO28_BITCLK_OUT_I2S_MD, | ||
120 | .frm = GPIO31_SYNC_I2S_MD, | ||
121 | }, | ||
122 | }; | ||
123 | |||
124 | static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream, | 100 | static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream, |
125 | struct snd_soc_dai *dai) | 101 | struct snd_soc_dai *dai) |
126 | { | 102 | { |
@@ -181,9 +157,6 @@ static int pxa2xx_i2s_set_dai_sysclk(struct snd_soc_dai *cpu_dai, | |||
181 | if (clk_id != PXA2XX_I2S_SYSCLK) | 157 | if (clk_id != PXA2XX_I2S_SYSCLK) |
182 | return -ENODEV; | 158 | return -ENODEV; |
183 | 159 | ||
184 | if (pxa_i2s.master && dir == SND_SOC_CLOCK_OUT) | ||
185 | pxa_gpio_mode(gpio_bus[pxa_i2s.master].sys); | ||
186 | |||
187 | return 0; | 160 | return 0; |
188 | } | 161 | } |
189 | 162 | ||
@@ -194,10 +167,6 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
194 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 167 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
195 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 168 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; |
196 | 169 | ||
197 | pxa_gpio_mode(gpio_bus[pxa_i2s.master].rx); | ||
198 | pxa_gpio_mode(gpio_bus[pxa_i2s.master].tx); | ||
199 | pxa_gpio_mode(gpio_bus[pxa_i2s.master].frm); | ||
200 | pxa_gpio_mode(gpio_bus[pxa_i2s.master].clk); | ||
201 | BUG_ON(IS_ERR(clk_i2s)); | 170 | BUG_ON(IS_ERR(clk_i2s)); |
202 | clk_enable(clk_i2s); | 171 | clk_enable(clk_i2s); |
203 | pxa_i2s_wait(); | 172 | pxa_i2s_wait(); |
@@ -335,6 +304,15 @@ static int pxa2xx_i2s_resume(struct snd_soc_dai *dai) | |||
335 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \ | 304 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \ |
336 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000) | 305 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000) |
337 | 306 | ||
307 | static struct snd_soc_dai_ops pxa_i2s_dai_ops = { | ||
308 | .startup = pxa2xx_i2s_startup, | ||
309 | .shutdown = pxa2xx_i2s_shutdown, | ||
310 | .trigger = pxa2xx_i2s_trigger, | ||
311 | .hw_params = pxa2xx_i2s_hw_params, | ||
312 | .set_fmt = pxa2xx_i2s_set_dai_fmt, | ||
313 | .set_sysclk = pxa2xx_i2s_set_dai_sysclk, | ||
314 | }; | ||
315 | |||
338 | struct snd_soc_dai pxa_i2s_dai = { | 316 | struct snd_soc_dai pxa_i2s_dai = { |
339 | .name = "pxa2xx-i2s", | 317 | .name = "pxa2xx-i2s", |
340 | .id = 0, | 318 | .id = 0, |
@@ -350,14 +328,7 @@ struct snd_soc_dai pxa_i2s_dai = { | |||
350 | .channels_max = 2, | 328 | .channels_max = 2, |
351 | .rates = PXA2XX_I2S_RATES, | 329 | .rates = PXA2XX_I2S_RATES, |
352 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | 330 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, |
353 | .ops = { | 331 | .ops = &pxa_i2s_dai_ops, |
354 | .startup = pxa2xx_i2s_startup, | ||
355 | .shutdown = pxa2xx_i2s_shutdown, | ||
356 | .trigger = pxa2xx_i2s_trigger, | ||
357 | .hw_params = pxa2xx_i2s_hw_params, | ||
358 | .set_fmt = pxa2xx_i2s_set_dai_fmt, | ||
359 | .set_sysclk = pxa2xx_i2s_set_dai_sysclk, | ||
360 | }, | ||
361 | }; | 332 | }; |
362 | 333 | ||
363 | EXPORT_SYMBOL_GPL(pxa_i2s_dai); | 334 | EXPORT_SYMBOL_GPL(pxa_i2s_dai); |
@@ -398,11 +369,6 @@ static struct platform_driver pxa2xx_i2s_driver = { | |||
398 | 369 | ||
399 | static int __init pxa2xx_i2s_init(void) | 370 | static int __init pxa2xx_i2s_init(void) |
400 | { | 371 | { |
401 | if (cpu_is_pxa27x()) | ||
402 | gpio_bus[1].sys = GPIO113_I2S_SYSCLK_MD; | ||
403 | else | ||
404 | gpio_bus[1].sys = GPIO32_SYSCLK_I2S_MD; | ||
405 | |||
406 | clk_i2s = ERR_PTR(-ENOENT); | 372 | clk_i2s = ERR_PTR(-ENOENT); |
407 | return platform_driver_register(&pxa2xx_i2s_driver); | 373 | return platform_driver_register(&pxa2xx_i2s_driver); |
408 | } | 374 | } |
diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c index de8778fa8729..c4cd2acaacb4 100644 --- a/sound/soc/pxa/spitz.c +++ b/sound/soc/pxa/spitz.c | |||
@@ -107,7 +107,7 @@ static void spitz_ext_control(struct snd_soc_codec *codec) | |||
107 | static int spitz_startup(struct snd_pcm_substream *substream) | 107 | static int spitz_startup(struct snd_pcm_substream *substream) |
108 | { | 108 | { |
109 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 109 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
110 | struct snd_soc_codec *codec = rtd->socdev->codec; | 110 | struct snd_soc_codec *codec = rtd->socdev->card->codec; |
111 | 111 | ||
112 | /* check the jack status at stream startup */ | 112 | /* check the jack status at stream startup */ |
113 | spitz_ext_control(codec); | 113 | spitz_ext_control(codec); |
@@ -276,7 +276,7 @@ static const struct snd_kcontrol_new wm8750_spitz_controls[] = { | |||
276 | */ | 276 | */ |
277 | static int spitz_wm8750_init(struct snd_soc_codec *codec) | 277 | static int spitz_wm8750_init(struct snd_soc_codec *codec) |
278 | { | 278 | { |
279 | int i, err; | 279 | int err; |
280 | 280 | ||
281 | /* NC codec pins */ | 281 | /* NC codec pins */ |
282 | snd_soc_dapm_nc_pin(codec, "RINPUT1"); | 282 | snd_soc_dapm_nc_pin(codec, "RINPUT1"); |
@@ -288,12 +288,10 @@ static int spitz_wm8750_init(struct snd_soc_codec *codec) | |||
288 | snd_soc_dapm_nc_pin(codec, "MONO1"); | 288 | snd_soc_dapm_nc_pin(codec, "MONO1"); |
289 | 289 | ||
290 | /* Add spitz specific controls */ | 290 | /* Add spitz specific controls */ |
291 | for (i = 0; i < ARRAY_SIZE(wm8750_spitz_controls); i++) { | 291 | err = snd_soc_add_controls(codec, wm8750_spitz_controls, |
292 | err = snd_ctl_add(codec->card, | 292 | ARRAY_SIZE(wm8750_spitz_controls)); |
293 | snd_soc_cnew(&wm8750_spitz_controls[i], codec, NULL)); | 293 | if (err < 0) |
294 | if (err < 0) | 294 | return err; |
295 | return err; | ||
296 | } | ||
297 | 295 | ||
298 | /* Add spitz specific widgets */ | 296 | /* Add spitz specific widgets */ |
299 | snd_soc_dapm_new_controls(codec, wm8750_dapm_widgets, | 297 | snd_soc_dapm_new_controls(codec, wm8750_dapm_widgets, |
diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c index 050223d04e54..dbbd3e9d1637 100644 --- a/sound/soc/pxa/tosa.c +++ b/sound/soc/pxa/tosa.c | |||
@@ -80,7 +80,7 @@ static void tosa_ext_control(struct snd_soc_codec *codec) | |||
80 | static int tosa_startup(struct snd_pcm_substream *substream) | 80 | static int tosa_startup(struct snd_pcm_substream *substream) |
81 | { | 81 | { |
82 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 82 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
83 | struct snd_soc_codec *codec = rtd->socdev->codec; | 83 | struct snd_soc_codec *codec = rtd->socdev->card->codec; |
84 | 84 | ||
85 | /* check the jack status at stream startup */ | 85 | /* check the jack status at stream startup */ |
86 | tosa_ext_control(codec); | 86 | tosa_ext_control(codec); |
@@ -186,18 +186,16 @@ static const struct snd_kcontrol_new tosa_controls[] = { | |||
186 | 186 | ||
187 | static int tosa_ac97_init(struct snd_soc_codec *codec) | 187 | static int tosa_ac97_init(struct snd_soc_codec *codec) |
188 | { | 188 | { |
189 | int i, err; | 189 | int err; |
190 | 190 | ||
191 | snd_soc_dapm_nc_pin(codec, "OUT3"); | 191 | snd_soc_dapm_nc_pin(codec, "OUT3"); |
192 | snd_soc_dapm_nc_pin(codec, "MONOOUT"); | 192 | snd_soc_dapm_nc_pin(codec, "MONOOUT"); |
193 | 193 | ||
194 | /* add tosa specific controls */ | 194 | /* add tosa specific controls */ |
195 | for (i = 0; i < ARRAY_SIZE(tosa_controls); i++) { | 195 | err = snd_soc_add_controls(codec, tosa_controls, |
196 | err = snd_ctl_add(codec->card, | 196 | ARRAY_SIZE(tosa_controls)); |
197 | snd_soc_cnew(&tosa_controls[i],codec, NULL)); | 197 | if (err < 0) |
198 | if (err < 0) | 198 | return err; |
199 | return err; | ||
200 | } | ||
201 | 199 | ||
202 | /* add tosa specific widgets */ | 200 | /* add tosa specific widgets */ |
203 | snd_soc_dapm_new_controls(codec, tosa_dapm_widgets, | 201 | snd_soc_dapm_new_controls(codec, tosa_dapm_widgets, |
diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c index f8e9ecd589d3..9a386b4c4ed1 100644 --- a/sound/soc/pxa/zylonite.c +++ b/sound/soc/pxa/zylonite.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/moduleparam.h> | 15 | #include <linux/moduleparam.h> |
16 | #include <linux/device.h> | 16 | #include <linux/device.h> |
17 | #include <linux/clk.h> | ||
17 | #include <linux/i2c.h> | 18 | #include <linux/i2c.h> |
18 | #include <sound/core.h> | 19 | #include <sound/core.h> |
19 | #include <sound/pcm.h> | 20 | #include <sound/pcm.h> |
@@ -26,6 +27,17 @@ | |||
26 | #include "pxa2xx-ac97.h" | 27 | #include "pxa2xx-ac97.h" |
27 | #include "pxa-ssp.h" | 28 | #include "pxa-ssp.h" |
28 | 29 | ||
30 | /* | ||
31 | * There is a physical switch SW15 on the board which changes the MCLK | ||
32 | * for the WM9713 between the standard AC97 master clock and the | ||
33 | * output of the CLK_POUT signal from the PXA. | ||
34 | */ | ||
35 | static int clk_pout; | ||
36 | module_param(clk_pout, int, 0); | ||
37 | MODULE_PARM_DESC(clk_pout, "Use CLK_POUT as WM9713 MCLK (SW15 on board)."); | ||
38 | |||
39 | static struct clk *pout; | ||
40 | |||
29 | static struct snd_soc_card zylonite; | 41 | static struct snd_soc_card zylonite; |
30 | 42 | ||
31 | static const struct snd_soc_dapm_widget zylonite_dapm_widgets[] = { | 43 | static const struct snd_soc_dapm_widget zylonite_dapm_widgets[] = { |
@@ -61,10 +73,8 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
61 | 73 | ||
62 | static int zylonite_wm9713_init(struct snd_soc_codec *codec) | 74 | static int zylonite_wm9713_init(struct snd_soc_codec *codec) |
63 | { | 75 | { |
64 | /* Currently we only support use of the AC97 clock here. If | 76 | if (clk_pout) |
65 | * CLK_POUT is selected by SW15 then the clock API will need | 77 | snd_soc_dai_set_pll(&codec->dai[0], 0, clk_get_rate(pout), 0); |
66 | * to be used to request and enable it here. | ||
67 | */ | ||
68 | 78 | ||
69 | snd_soc_dapm_new_controls(codec, zylonite_dapm_widgets, | 79 | snd_soc_dapm_new_controls(codec, zylonite_dapm_widgets, |
70 | ARRAY_SIZE(zylonite_dapm_widgets)); | 80 | ARRAY_SIZE(zylonite_dapm_widgets)); |
@@ -86,40 +96,35 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, | |||
86 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 96 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; |
87 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 97 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; |
88 | unsigned int pll_out = 0; | 98 | unsigned int pll_out = 0; |
89 | unsigned int acds = 0; | ||
90 | unsigned int wm9713_div = 0; | 99 | unsigned int wm9713_div = 0; |
91 | int ret = 0; | 100 | int ret = 0; |
101 | int rate = params_rate(params); | ||
102 | int width = snd_pcm_format_physical_width(params_format(params)); | ||
92 | 103 | ||
93 | switch (params_rate(params)) { | 104 | /* Only support ratios that we can generate neatly from the AC97 |
105 | * based master clock - in particular, this excludes 44.1kHz. | ||
106 | * In most applications the voice DAC will be used for telephony | ||
107 | * data so multiples of 8kHz will be the common case. | ||
108 | */ | ||
109 | switch (rate) { | ||
94 | case 8000: | 110 | case 8000: |
95 | wm9713_div = 12; | 111 | wm9713_div = 12; |
96 | pll_out = 2048000; | ||
97 | break; | 112 | break; |
98 | case 16000: | 113 | case 16000: |
99 | wm9713_div = 6; | 114 | wm9713_div = 6; |
100 | pll_out = 4096000; | ||
101 | break; | 115 | break; |
102 | case 48000: | 116 | case 48000: |
103 | default: | ||
104 | wm9713_div = 2; | 117 | wm9713_div = 2; |
105 | pll_out = 12288000; | ||
106 | acds = 1; | ||
107 | break; | 118 | break; |
119 | default: | ||
120 | /* Don't support OSS emulation */ | ||
121 | return -EINVAL; | ||
108 | } | 122 | } |
109 | 123 | ||
110 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | | 124 | /* Add 1 to the width for the leading clock cycle */ |
111 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); | 125 | pll_out = rate * (width + 1) * 8; |
112 | if (ret < 0) | ||
113 | return ret; | ||
114 | |||
115 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | | ||
116 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); | ||
117 | if (ret < 0) | ||
118 | return ret; | ||
119 | 126 | ||
120 | ret = snd_soc_dai_set_tdm_slot(cpu_dai, | 127 | ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_AUDIO, 0, 1); |
121 | params_channels(params), | ||
122 | params_channels(params)); | ||
123 | if (ret < 0) | 128 | if (ret < 0) |
124 | return ret; | 129 | return ret; |
125 | 130 | ||
@@ -127,19 +132,22 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, | |||
127 | if (ret < 0) | 132 | if (ret < 0) |
128 | return ret; | 133 | return ret; |
129 | 134 | ||
130 | ret = snd_soc_dai_set_clkdiv(cpu_dai, PXA_SSP_AUDIO_DIV_ACDS, acds); | 135 | if (clk_pout) |
136 | ret = snd_soc_dai_set_clkdiv(codec_dai, WM9713_PCMCLK_PLL_DIV, | ||
137 | WM9713_PCMDIV(wm9713_div)); | ||
138 | else | ||
139 | ret = snd_soc_dai_set_clkdiv(codec_dai, WM9713_PCMCLK_DIV, | ||
140 | WM9713_PCMDIV(wm9713_div)); | ||
131 | if (ret < 0) | 141 | if (ret < 0) |
132 | return ret; | 142 | return ret; |
133 | 143 | ||
134 | ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_AUDIO, 0, 1); | 144 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | |
145 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); | ||
135 | if (ret < 0) | 146 | if (ret < 0) |
136 | return ret; | 147 | return ret; |
137 | 148 | ||
138 | /* Note that if the PLL is in use the WM9713_PCMCLK_PLL_DIV needs | 149 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | |
139 | * to be set instead. | 150 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); |
140 | */ | ||
141 | ret = snd_soc_dai_set_clkdiv(codec_dai, WM9713_PCMCLK_DIV, | ||
142 | WM9713_PCMDIV(wm9713_div)); | ||
143 | if (ret < 0) | 151 | if (ret < 0) |
144 | return ret; | 152 | return ret; |
145 | 153 | ||
@@ -173,8 +181,72 @@ static struct snd_soc_dai_link zylonite_dai[] = { | |||
173 | }, | 181 | }, |
174 | }; | 182 | }; |
175 | 183 | ||
184 | static int zylonite_probe(struct platform_device *pdev) | ||
185 | { | ||
186 | int ret; | ||
187 | |||
188 | if (clk_pout) { | ||
189 | pout = clk_get(NULL, "CLK_POUT"); | ||
190 | if (IS_ERR(pout)) { | ||
191 | dev_err(&pdev->dev, "Unable to obtain CLK_POUT: %ld\n", | ||
192 | PTR_ERR(pout)); | ||
193 | return PTR_ERR(pout); | ||
194 | } | ||
195 | |||
196 | ret = clk_enable(pout); | ||
197 | if (ret != 0) { | ||
198 | dev_err(&pdev->dev, "Unable to enable CLK_POUT: %d\n", | ||
199 | ret); | ||
200 | clk_put(pout); | ||
201 | return ret; | ||
202 | } | ||
203 | |||
204 | dev_dbg(&pdev->dev, "MCLK enabled at %luHz\n", | ||
205 | clk_get_rate(pout)); | ||
206 | } | ||
207 | |||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | static int zylonite_remove(struct platform_device *pdev) | ||
212 | { | ||
213 | if (clk_pout) { | ||
214 | clk_disable(pout); | ||
215 | clk_put(pout); | ||
216 | } | ||
217 | |||
218 | return 0; | ||
219 | } | ||
220 | |||
221 | static int zylonite_suspend_post(struct platform_device *pdev, | ||
222 | pm_message_t state) | ||
223 | { | ||
224 | if (clk_pout) | ||
225 | clk_disable(pout); | ||
226 | |||
227 | return 0; | ||
228 | } | ||
229 | |||
230 | static int zylonite_resume_pre(struct platform_device *pdev) | ||
231 | { | ||
232 | int ret = 0; | ||
233 | |||
234 | if (clk_pout) { | ||
235 | ret = clk_enable(pout); | ||
236 | if (ret != 0) | ||
237 | dev_err(&pdev->dev, "Unable to enable CLK_POUT: %d\n", | ||
238 | ret); | ||
239 | } | ||
240 | |||
241 | return ret; | ||
242 | } | ||
243 | |||
176 | static struct snd_soc_card zylonite = { | 244 | static struct snd_soc_card zylonite = { |
177 | .name = "Zylonite", | 245 | .name = "Zylonite", |
246 | .probe = &zylonite_probe, | ||
247 | .remove = &zylonite_remove, | ||
248 | .suspend_post = &zylonite_suspend_post, | ||
249 | .resume_pre = &zylonite_resume_pre, | ||
178 | .platform = &pxa2xx_soc_platform, | 250 | .platform = &pxa2xx_soc_platform, |
179 | .dai_link = zylonite_dai, | 251 | .dai_link = zylonite_dai, |
180 | .num_links = ARRAY_SIZE(zylonite_dai), | 252 | .num_links = ARRAY_SIZE(zylonite_dai), |
diff --git a/sound/soc/s3c24xx/Kconfig b/sound/soc/s3c24xx/Kconfig index fcd03acf10f6..2f3a21eee051 100644 --- a/sound/soc/s3c24xx/Kconfig +++ b/sound/soc/s3c24xx/Kconfig | |||
@@ -1,19 +1,31 @@ | |||
1 | config SND_S3C24XX_SOC | 1 | config SND_S3C24XX_SOC |
2 | tristate "SoC Audio for the Samsung S3C24XX chips" | 2 | tristate "SoC Audio for the Samsung S3CXXXX chips" |
3 | depends on ARCH_S3C2410 | 3 | depends on ARCH_S3C2410 || ARCH_S3C64XX |
4 | help | 4 | help |
5 | Say Y or M if you want to add support for codecs attached to | 5 | Say Y or M if you want to add support for codecs attached to |
6 | the S3C24XX AC97, I2S or SSP interface. You will also need | 6 | the S3C24XX and S3C64XX AC97, I2S or SSP interface. You will |
7 | to select the audio interfaces to support below. | 7 | also need to select the audio interfaces to support below. |
8 | 8 | ||
9 | config SND_S3C24XX_SOC_I2S | 9 | config SND_S3C24XX_SOC_I2S |
10 | tristate | 10 | tristate |
11 | select S3C2410_DMA | ||
12 | |||
13 | config SND_S3C_I2SV2_SOC | ||
14 | tristate | ||
11 | 15 | ||
12 | config SND_S3C2412_SOC_I2S | 16 | config SND_S3C2412_SOC_I2S |
13 | tristate | 17 | tristate |
18 | select SND_S3C_I2SV2_SOC | ||
19 | select S3C2410_DMA | ||
20 | |||
21 | config SND_S3C64XX_SOC_I2S | ||
22 | tristate | ||
23 | select SND_S3C_I2SV2_SOC | ||
24 | select S3C64XX_DMA | ||
14 | 25 | ||
15 | config SND_S3C2443_SOC_AC97 | 26 | config SND_S3C2443_SOC_AC97 |
16 | tristate | 27 | tristate |
28 | select S3C2410_DMA | ||
17 | select AC97_BUS | 29 | select AC97_BUS |
18 | select SND_SOC_AC97_BUS | 30 | select SND_SOC_AC97_BUS |
19 | 31 | ||
@@ -26,6 +38,14 @@ config SND_S3C24XX_SOC_NEO1973_WM8753 | |||
26 | Say Y if you want to add support for SoC audio on smdk2440 | 38 | Say Y if you want to add support for SoC audio on smdk2440 |
27 | with the WM8753. | 39 | with the WM8753. |
28 | 40 | ||
41 | config SND_S3C24XX_SOC_JIVE_WM8750 | ||
42 | tristate "SoC I2S Audio support for Jive" | ||
43 | depends on SND_S3C24XX_SOC && MACH_JIVE | ||
44 | select SND_SOC_WM8750 | ||
45 | select SND_S3C2412_SOC_I2S | ||
46 | help | ||
47 | Sat Y if you want to add support for SoC audio on the Jive. | ||
48 | |||
29 | config SND_S3C24XX_SOC_SMDK2443_WM9710 | 49 | config SND_S3C24XX_SOC_SMDK2443_WM9710 |
30 | tristate "SoC AC97 Audio support for SMDK2443 - WM9710" | 50 | tristate "SoC AC97 Audio support for SMDK2443 - WM9710" |
31 | depends on SND_S3C24XX_SOC && MACH_SMDK2443 | 51 | depends on SND_S3C24XX_SOC && MACH_SMDK2443 |
@@ -48,4 +68,5 @@ config SND_S3C24XX_SOC_S3C24XX_UDA134X | |||
48 | tristate "SoC I2S Audio support UDA134X wired to a S3C24XX" | 68 | tristate "SoC I2S Audio support UDA134X wired to a S3C24XX" |
49 | depends on SND_S3C24XX_SOC | 69 | depends on SND_S3C24XX_SOC |
50 | select SND_S3C24XX_SOC_I2S | 70 | select SND_S3C24XX_SOC_I2S |
71 | select SND_SOC_L3 | ||
51 | select SND_SOC_UDA134X | 72 | select SND_SOC_UDA134X |
diff --git a/sound/soc/s3c24xx/Makefile b/sound/soc/s3c24xx/Makefile index 96b3f3f617d4..07a93a2ebe5f 100644 --- a/sound/soc/s3c24xx/Makefile +++ b/sound/soc/s3c24xx/Makefile | |||
@@ -2,19 +2,25 @@ | |||
2 | snd-soc-s3c24xx-objs := s3c24xx-pcm.o | 2 | snd-soc-s3c24xx-objs := s3c24xx-pcm.o |
3 | snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o | 3 | snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o |
4 | snd-soc-s3c2412-i2s-objs := s3c2412-i2s.o | 4 | snd-soc-s3c2412-i2s-objs := s3c2412-i2s.o |
5 | snd-soc-s3c64xx-i2s-objs := s3c64xx-i2s.o | ||
5 | snd-soc-s3c2443-ac97-objs := s3c2443-ac97.o | 6 | snd-soc-s3c2443-ac97-objs := s3c2443-ac97.o |
7 | snd-soc-s3c-i2s-v2-objs := s3c-i2s-v2.o | ||
6 | 8 | ||
7 | obj-$(CONFIG_SND_S3C24XX_SOC) += snd-soc-s3c24xx.o | 9 | obj-$(CONFIG_SND_S3C24XX_SOC) += snd-soc-s3c24xx.o |
8 | obj-$(CONFIG_SND_S3C24XX_SOC_I2S) += snd-soc-s3c24xx-i2s.o | 10 | obj-$(CONFIG_SND_S3C24XX_SOC_I2S) += snd-soc-s3c24xx-i2s.o |
9 | obj-$(CONFIG_SND_S3C2443_SOC_AC97) += snd-soc-s3c2443-ac97.o | 11 | obj-$(CONFIG_SND_S3C2443_SOC_AC97) += snd-soc-s3c2443-ac97.o |
10 | obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd-soc-s3c2412-i2s.o | 12 | obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd-soc-s3c2412-i2s.o |
13 | obj-$(CONFIG_SND_S3C64XX_SOC_I2S) += snd-soc-s3c64xx-i2s.o | ||
14 | obj-$(CONFIG_SND_S3C_I2SV2_SOC) += snd-soc-s3c-i2s-v2.o | ||
11 | 15 | ||
12 | # S3C24XX Machine Support | 16 | # S3C24XX Machine Support |
17 | snd-soc-jive-wm8750-objs := jive_wm8750.o | ||
13 | snd-soc-neo1973-wm8753-objs := neo1973_wm8753.o | 18 | snd-soc-neo1973-wm8753-objs := neo1973_wm8753.o |
14 | snd-soc-smdk2443-wm9710-objs := smdk2443_wm9710.o | 19 | snd-soc-smdk2443-wm9710-objs := smdk2443_wm9710.o |
15 | snd-soc-ln2440sbc-alc650-objs := ln2440sbc_alc650.o | 20 | snd-soc-ln2440sbc-alc650-objs := ln2440sbc_alc650.o |
16 | snd-soc-s3c24xx-uda134x-objs := s3c24xx_uda134x.o | 21 | snd-soc-s3c24xx-uda134x-objs := s3c24xx_uda134x.o |
17 | 22 | ||
23 | obj-$(CONFIG_SND_S3C24XX_SOC_JIVE_WM8750) += snd-soc-jive-wm8750.o | ||
18 | obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o | 24 | obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o |
19 | obj-$(CONFIG_SND_S3C24XX_SOC_SMDK2443_WM9710) += snd-soc-smdk2443-wm9710.o | 25 | obj-$(CONFIG_SND_S3C24XX_SOC_SMDK2443_WM9710) += snd-soc-smdk2443-wm9710.o |
20 | obj-$(CONFIG_SND_S3C24XX_SOC_LN2440SBC_ALC650) += snd-soc-ln2440sbc-alc650.o | 26 | obj-$(CONFIG_SND_S3C24XX_SOC_LN2440SBC_ALC650) += snd-soc-ln2440sbc-alc650.o |
diff --git a/sound/soc/s3c24xx/jive_wm8750.c b/sound/soc/s3c24xx/jive_wm8750.c new file mode 100644 index 000000000000..32063790d95b --- /dev/null +++ b/sound/soc/s3c24xx/jive_wm8750.c | |||
@@ -0,0 +1,201 @@ | |||
1 | /* sound/soc/s3c24xx/jive_wm8750.c | ||
2 | * | ||
3 | * Copyright 2007,2008 Simtec Electronics | ||
4 | * | ||
5 | * Based on sound/soc/pxa/spitz.c | ||
6 | * Copyright 2005 Wolfson Microelectronics PLC. | ||
7 | * Copyright 2005 Openedhand Ltd. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/moduleparam.h> | ||
16 | #include <linux/timer.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/clk.h> | ||
20 | |||
21 | #include <sound/core.h> | ||
22 | #include <sound/pcm.h> | ||
23 | #include <sound/soc.h> | ||
24 | #include <sound/soc-dapm.h> | ||
25 | |||
26 | #include <asm/mach-types.h> | ||
27 | |||
28 | #include "s3c24xx-pcm.h" | ||
29 | #include "s3c2412-i2s.h" | ||
30 | |||
31 | #include "../codecs/wm8750.h" | ||
32 | |||
33 | static const struct snd_soc_dapm_route audio_map[] = { | ||
34 | { "Headphone Jack", NULL, "LOUT1" }, | ||
35 | { "Headphone Jack", NULL, "ROUT1" }, | ||
36 | { "Internal Speaker", NULL, "LOUT2" }, | ||
37 | { "Internal Speaker", NULL, "ROUT2" }, | ||
38 | { "LINPUT1", NULL, "Line Input" }, | ||
39 | { "RINPUT1", NULL, "Line Input" }, | ||
40 | }; | ||
41 | |||
42 | static const struct snd_soc_dapm_widget wm8750_dapm_widgets[] = { | ||
43 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | ||
44 | SND_SOC_DAPM_SPK("Internal Speaker", NULL), | ||
45 | SND_SOC_DAPM_LINE("Line In", NULL), | ||
46 | }; | ||
47 | |||
48 | static int jive_hw_params(struct snd_pcm_substream *substream, | ||
49 | struct snd_pcm_hw_params *params) | ||
50 | { | ||
51 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
52 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | ||
53 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
54 | struct s3c_i2sv2_rate_calc div; | ||
55 | unsigned int clk = 0; | ||
56 | int ret = 0; | ||
57 | |||
58 | switch (params_rate(params)) { | ||
59 | case 8000: | ||
60 | case 16000: | ||
61 | case 48000: | ||
62 | case 96000: | ||
63 | clk = 12288000; | ||
64 | break; | ||
65 | case 11025: | ||
66 | case 22050: | ||
67 | case 44100: | ||
68 | clk = 11289600; | ||
69 | break; | ||
70 | } | ||
71 | |||
72 | s3c_i2sv2_calc_rate(&div, NULL, params_rate(params), | ||
73 | s3c2412_get_iisclk()); | ||
74 | |||
75 | /* set codec DAI configuration */ | ||
76 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | | ||
77 | SND_SOC_DAIFMT_NB_NF | | ||
78 | SND_SOC_DAIFMT_CBS_CFS); | ||
79 | if (ret < 0) | ||
80 | return ret; | ||
81 | |||
82 | /* set cpu DAI configuration */ | ||
83 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | | ||
84 | SND_SOC_DAIFMT_NB_NF | | ||
85 | SND_SOC_DAIFMT_CBS_CFS); | ||
86 | if (ret < 0) | ||
87 | return ret; | ||
88 | |||
89 | /* set the codec system clock for DAC and ADC */ | ||
90 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8750_SYSCLK, clk, | ||
91 | SND_SOC_CLOCK_IN); | ||
92 | if (ret < 0) | ||
93 | return ret; | ||
94 | |||
95 | ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C2412_DIV_RCLK, div.fs_div); | ||
96 | if (ret < 0) | ||
97 | return ret; | ||
98 | |||
99 | ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C2412_DIV_PRESCALER, | ||
100 | div.clk_div - 1); | ||
101 | if (ret < 0) | ||
102 | return ret; | ||
103 | |||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | static struct snd_soc_ops jive_ops = { | ||
108 | .hw_params = jive_hw_params, | ||
109 | }; | ||
110 | |||
111 | static int jive_wm8750_init(struct snd_soc_codec *codec) | ||
112 | { | ||
113 | int err; | ||
114 | |||
115 | /* These endpoints are not being used. */ | ||
116 | snd_soc_dapm_nc_pin(codec, "LINPUT2"); | ||
117 | snd_soc_dapm_nc_pin(codec, "RINPUT2"); | ||
118 | snd_soc_dapm_nc_pin(codec, "LINPUT3"); | ||
119 | snd_soc_dapm_nc_pin(codec, "RINPUT3"); | ||
120 | snd_soc_dapm_nc_pin(codec, "OUT3"); | ||
121 | snd_soc_dapm_nc_pin(codec, "MONO"); | ||
122 | |||
123 | /* Add jive specific widgets */ | ||
124 | err = snd_soc_dapm_new_controls(codec, wm8750_dapm_widgets, | ||
125 | ARRAY_SIZE(wm8750_dapm_widgets)); | ||
126 | if (err) { | ||
127 | printk(KERN_ERR "%s: failed to add widgets (%d)\n", | ||
128 | __func__, err); | ||
129 | return err; | ||
130 | } | ||
131 | |||
132 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | ||
133 | snd_soc_dapm_sync(codec); | ||
134 | |||
135 | return 0; | ||
136 | } | ||
137 | |||
138 | static struct snd_soc_dai_link jive_dai = { | ||
139 | .name = "wm8750", | ||
140 | .stream_name = "WM8750", | ||
141 | .cpu_dai = &s3c2412_i2s_dai, | ||
142 | .codec_dai = &wm8750_dai, | ||
143 | .init = jive_wm8750_init, | ||
144 | .ops = &jive_ops, | ||
145 | }; | ||
146 | |||
147 | /* jive audio machine driver */ | ||
148 | static struct snd_soc_machine snd_soc_machine_jive = { | ||
149 | .name = "Jive", | ||
150 | .dai_link = &jive_dai, | ||
151 | .num_links = 1, | ||
152 | }; | ||
153 | |||
154 | /* jive audio private data */ | ||
155 | static struct wm8750_setup_data jive_wm8750_setup = { | ||
156 | }; | ||
157 | |||
158 | /* jive audio subsystem */ | ||
159 | static struct snd_soc_device jive_snd_devdata = { | ||
160 | .machine = &snd_soc_machine_jive, | ||
161 | .platform = &s3c24xx_soc_platform, | ||
162 | .codec_dev = &soc_codec_dev_wm8750_spi, | ||
163 | .codec_data = &jive_wm8750_setup, | ||
164 | }; | ||
165 | |||
166 | static struct platform_device *jive_snd_device; | ||
167 | |||
168 | static int __init jive_init(void) | ||
169 | { | ||
170 | int ret; | ||
171 | |||
172 | if (!machine_is_jive()) | ||
173 | return 0; | ||
174 | |||
175 | printk("JIVE WM8750 Audio support\n"); | ||
176 | |||
177 | jive_snd_device = platform_device_alloc("soc-audio", -1); | ||
178 | if (!jive_snd_device) | ||
179 | return -ENOMEM; | ||
180 | |||
181 | platform_set_drvdata(jive_snd_device, &jive_snd_devdata); | ||
182 | jive_snd_devdata.dev = &jive_snd_device->dev; | ||
183 | ret = platform_device_add(jive_snd_device); | ||
184 | |||
185 | if (ret) | ||
186 | platform_device_put(jive_snd_device); | ||
187 | |||
188 | return ret; | ||
189 | } | ||
190 | |||
191 | static void __exit jive_exit(void) | ||
192 | { | ||
193 | platform_device_unregister(jive_snd_device); | ||
194 | } | ||
195 | |||
196 | module_init(jive_init); | ||
197 | module_exit(jive_exit); | ||
198 | |||
199 | MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); | ||
200 | MODULE_DESCRIPTION("ALSA SoC Jive Audio support"); | ||
201 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/s3c24xx/neo1973_wm8753.c b/sound/soc/s3c24xx/neo1973_wm8753.c index 45bb12e8ea44..289fadf60b10 100644 --- a/sound/soc/s3c24xx/neo1973_wm8753.c +++ b/sound/soc/s3c24xx/neo1973_wm8753.c | |||
@@ -29,25 +29,17 @@ | |||
29 | #include <mach/regs-clock.h> | 29 | #include <mach/regs-clock.h> |
30 | #include <mach/regs-gpio.h> | 30 | #include <mach/regs-gpio.h> |
31 | #include <mach/hardware.h> | 31 | #include <mach/hardware.h> |
32 | #include <mach/audio.h> | 32 | #include <plat/audio.h> |
33 | #include <linux/io.h> | 33 | #include <linux/io.h> |
34 | #include <mach/spi-gpio.h> | 34 | #include <mach/spi-gpio.h> |
35 | 35 | ||
36 | #include <asm/plat-s3c24xx/regs-iis.h> | 36 | #include <plat/regs-iis.h> |
37 | 37 | ||
38 | #include "../codecs/wm8753.h" | 38 | #include "../codecs/wm8753.h" |
39 | #include "lm4857.h" | 39 | #include "lm4857.h" |
40 | #include "s3c24xx-pcm.h" | 40 | #include "s3c24xx-pcm.h" |
41 | #include "s3c24xx-i2s.h" | 41 | #include "s3c24xx-i2s.h" |
42 | 42 | ||
43 | /* Debugging stuff */ | ||
44 | #define S3C24XX_SOC_NEO1973_WM8753_DEBUG 0 | ||
45 | #if S3C24XX_SOC_NEO1973_WM8753_DEBUG | ||
46 | #define DBG(x...) printk(KERN_DEBUG "s3c24xx-soc-neo1973-wm8753: " x) | ||
47 | #else | ||
48 | #define DBG(x...) | ||
49 | #endif | ||
50 | |||
51 | /* define the scenarios */ | 43 | /* define the scenarios */ |
52 | #define NEO_AUDIO_OFF 0 | 44 | #define NEO_AUDIO_OFF 0 |
53 | #define NEO_GSM_CALL_AUDIO_HANDSET 1 | 45 | #define NEO_GSM_CALL_AUDIO_HANDSET 1 |
@@ -72,7 +64,7 @@ static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream, | |||
72 | int ret = 0; | 64 | int ret = 0; |
73 | unsigned long iis_clkrate; | 65 | unsigned long iis_clkrate; |
74 | 66 | ||
75 | DBG("Entered %s\n", __func__); | 67 | pr_debug("Entered %s\n", __func__); |
76 | 68 | ||
77 | iis_clkrate = s3c24xx_i2s_get_clockrate(); | 69 | iis_clkrate = s3c24xx_i2s_get_clockrate(); |
78 | 70 | ||
@@ -158,7 +150,7 @@ static int neo1973_hifi_hw_free(struct snd_pcm_substream *substream) | |||
158 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 150 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
159 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 151 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; |
160 | 152 | ||
161 | DBG("Entered %s\n", __func__); | 153 | pr_debug("Entered %s\n", __func__); |
162 | 154 | ||
163 | /* disable the PLL */ | 155 | /* disable the PLL */ |
164 | return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0); | 156 | return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0); |
@@ -181,7 +173,7 @@ static int neo1973_voice_hw_params(struct snd_pcm_substream *substream, | |||
181 | int ret = 0; | 173 | int ret = 0; |
182 | unsigned long iis_clkrate; | 174 | unsigned long iis_clkrate; |
183 | 175 | ||
184 | DBG("Entered %s\n", __func__); | 176 | pr_debug("Entered %s\n", __func__); |
185 | 177 | ||
186 | iis_clkrate = s3c24xx_i2s_get_clockrate(); | 178 | iis_clkrate = s3c24xx_i2s_get_clockrate(); |
187 | 179 | ||
@@ -224,7 +216,7 @@ static int neo1973_voice_hw_free(struct snd_pcm_substream *substream) | |||
224 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 216 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
225 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 217 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; |
226 | 218 | ||
227 | DBG("Entered %s\n", __func__); | 219 | pr_debug("Entered %s\n", __func__); |
228 | 220 | ||
229 | /* disable the PLL */ | 221 | /* disable the PLL */ |
230 | return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0); | 222 | return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0); |
@@ -246,7 +238,7 @@ static int neo1973_get_scenario(struct snd_kcontrol *kcontrol, | |||
246 | 238 | ||
247 | static int set_scenario_endpoints(struct snd_soc_codec *codec, int scenario) | 239 | static int set_scenario_endpoints(struct snd_soc_codec *codec, int scenario) |
248 | { | 240 | { |
249 | DBG("Entered %s\n", __func__); | 241 | pr_debug("Entered %s\n", __func__); |
250 | 242 | ||
251 | switch (neo1973_scenario) { | 243 | switch (neo1973_scenario) { |
252 | case NEO_AUDIO_OFF: | 244 | case NEO_AUDIO_OFF: |
@@ -330,7 +322,7 @@ static int neo1973_set_scenario(struct snd_kcontrol *kcontrol, | |||
330 | { | 322 | { |
331 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 323 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
332 | 324 | ||
333 | DBG("Entered %s\n", __func__); | 325 | pr_debug("Entered %s\n", __func__); |
334 | 326 | ||
335 | if (neo1973_scenario == ucontrol->value.integer.value[0]) | 327 | if (neo1973_scenario == ucontrol->value.integer.value[0]) |
336 | return 0; | 328 | return 0; |
@@ -344,7 +336,7 @@ static u8 lm4857_regs[4] = {0x00, 0x40, 0x80, 0xC0}; | |||
344 | 336 | ||
345 | static void lm4857_write_regs(void) | 337 | static void lm4857_write_regs(void) |
346 | { | 338 | { |
347 | DBG("Entered %s\n", __func__); | 339 | pr_debug("Entered %s\n", __func__); |
348 | 340 | ||
349 | if (i2c_master_send(i2c, lm4857_regs, 4) != 4) | 341 | if (i2c_master_send(i2c, lm4857_regs, 4) != 4) |
350 | printk(KERN_ERR "lm4857: i2c write failed\n"); | 342 | printk(KERN_ERR "lm4857: i2c write failed\n"); |
@@ -357,7 +349,7 @@ static int lm4857_get_reg(struct snd_kcontrol *kcontrol, | |||
357 | int shift = (kcontrol->private_value >> 8) & 0x0F; | 349 | int shift = (kcontrol->private_value >> 8) & 0x0F; |
358 | int mask = (kcontrol->private_value >> 16) & 0xFF; | 350 | int mask = (kcontrol->private_value >> 16) & 0xFF; |
359 | 351 | ||
360 | DBG("Entered %s\n", __func__); | 352 | pr_debug("Entered %s\n", __func__); |
361 | 353 | ||
362 | ucontrol->value.integer.value[0] = (lm4857_regs[reg] >> shift) & mask; | 354 | ucontrol->value.integer.value[0] = (lm4857_regs[reg] >> shift) & mask; |
363 | return 0; | 355 | return 0; |
@@ -385,7 +377,7 @@ static int lm4857_get_mode(struct snd_kcontrol *kcontrol, | |||
385 | { | 377 | { |
386 | u8 value = lm4857_regs[LM4857_CTRL] & 0x0F; | 378 | u8 value = lm4857_regs[LM4857_CTRL] & 0x0F; |
387 | 379 | ||
388 | DBG("Entered %s\n", __func__); | 380 | pr_debug("Entered %s\n", __func__); |
389 | 381 | ||
390 | if (value) | 382 | if (value) |
391 | value -= 5; | 383 | value -= 5; |
@@ -399,7 +391,7 @@ static int lm4857_set_mode(struct snd_kcontrol *kcontrol, | |||
399 | { | 391 | { |
400 | u8 value = ucontrol->value.integer.value[0]; | 392 | u8 value = ucontrol->value.integer.value[0]; |
401 | 393 | ||
402 | DBG("Entered %s\n", __func__); | 394 | pr_debug("Entered %s\n", __func__); |
403 | 395 | ||
404 | if (value) | 396 | if (value) |
405 | value += 5; | 397 | value += 5; |
@@ -506,9 +498,9 @@ static const struct snd_kcontrol_new wm8753_neo1973_controls[] = { | |||
506 | */ | 498 | */ |
507 | static int neo1973_wm8753_init(struct snd_soc_codec *codec) | 499 | static int neo1973_wm8753_init(struct snd_soc_codec *codec) |
508 | { | 500 | { |
509 | int i, err; | 501 | int err; |
510 | 502 | ||
511 | DBG("Entered %s\n", __func__); | 503 | pr_debug("Entered %s\n", __func__); |
512 | 504 | ||
513 | /* set up NC codec pins */ | 505 | /* set up NC codec pins */ |
514 | snd_soc_dapm_nc_pin(codec, "LOUT2"); | 506 | snd_soc_dapm_nc_pin(codec, "LOUT2"); |
@@ -526,13 +518,10 @@ static int neo1973_wm8753_init(struct snd_soc_codec *codec) | |||
526 | set_scenario_endpoints(codec, NEO_AUDIO_OFF); | 518 | set_scenario_endpoints(codec, NEO_AUDIO_OFF); |
527 | 519 | ||
528 | /* add neo1973 specific controls */ | 520 | /* add neo1973 specific controls */ |
529 | for (i = 0; i < ARRAY_SIZE(wm8753_neo1973_controls); i++) { | 521 | err = snd_soc_add_controls(codec, wm8753_neo1973_controls, |
530 | err = snd_ctl_add(codec->card, | 522 | ARRAY_SIZE(8753_neo1973_controls)); |
531 | snd_soc_cnew(&wm8753_neo1973_controls[i], | 523 | if (err < 0) |
532 | codec, NULL)); | 524 | return err; |
533 | if (err < 0) | ||
534 | return err; | ||
535 | } | ||
536 | 525 | ||
537 | /* set up neo1973 specific audio routes */ | 526 | /* set up neo1973 specific audio routes */ |
538 | err = snd_soc_dapm_add_routes(codec, dapm_routes, | 527 | err = snd_soc_dapm_add_routes(codec, dapm_routes, |
@@ -585,21 +574,15 @@ static struct snd_soc_card neo1973 = { | |||
585 | .num_links = ARRAY_SIZE(neo1973_dai), | 574 | .num_links = ARRAY_SIZE(neo1973_dai), |
586 | }; | 575 | }; |
587 | 576 | ||
588 | static struct wm8753_setup_data neo1973_wm8753_setup = { | ||
589 | .i2c_bus = 0, | ||
590 | .i2c_address = 0x1a, | ||
591 | }; | ||
592 | |||
593 | static struct snd_soc_device neo1973_snd_devdata = { | 577 | static struct snd_soc_device neo1973_snd_devdata = { |
594 | .card = &neo1973, | 578 | .card = &neo1973, |
595 | .codec_dev = &soc_codec_dev_wm8753, | 579 | .codec_dev = &soc_codec_dev_wm8753, |
596 | .codec_data = &neo1973_wm8753_setup, | ||
597 | }; | 580 | }; |
598 | 581 | ||
599 | static int lm4857_i2c_probe(struct i2c_client *client, | 582 | static int lm4857_i2c_probe(struct i2c_client *client, |
600 | const struct i2c_device_id *id) | 583 | const struct i2c_device_id *id) |
601 | { | 584 | { |
602 | DBG("Entered %s\n", __func__); | 585 | pr_debug("Entered %s\n", __func__); |
603 | 586 | ||
604 | i2c = client; | 587 | i2c = client; |
605 | 588 | ||
@@ -609,7 +592,7 @@ static int lm4857_i2c_probe(struct i2c_client *client, | |||
609 | 592 | ||
610 | static int lm4857_i2c_remove(struct i2c_client *client) | 593 | static int lm4857_i2c_remove(struct i2c_client *client) |
611 | { | 594 | { |
612 | DBG("Entered %s\n", __func__); | 595 | pr_debug("Entered %s\n", __func__); |
613 | 596 | ||
614 | i2c = NULL; | 597 | i2c = NULL; |
615 | 598 | ||
@@ -620,7 +603,7 @@ static u8 lm4857_state; | |||
620 | 603 | ||
621 | static int lm4857_suspend(struct i2c_client *dev, pm_message_t state) | 604 | static int lm4857_suspend(struct i2c_client *dev, pm_message_t state) |
622 | { | 605 | { |
623 | DBG("Entered %s\n", __func__); | 606 | pr_debug("Entered %s\n", __func__); |
624 | 607 | ||
625 | dev_dbg(&dev->dev, "lm4857_suspend\n"); | 608 | dev_dbg(&dev->dev, "lm4857_suspend\n"); |
626 | lm4857_state = lm4857_regs[LM4857_CTRL] & 0xf; | 609 | lm4857_state = lm4857_regs[LM4857_CTRL] & 0xf; |
@@ -633,7 +616,7 @@ static int lm4857_suspend(struct i2c_client *dev, pm_message_t state) | |||
633 | 616 | ||
634 | static int lm4857_resume(struct i2c_client *dev) | 617 | static int lm4857_resume(struct i2c_client *dev) |
635 | { | 618 | { |
636 | DBG("Entered %s\n", __func__); | 619 | pr_debug("Entered %s\n", __func__); |
637 | 620 | ||
638 | if (lm4857_state) { | 621 | if (lm4857_state) { |
639 | lm4857_regs[LM4857_CTRL] |= (lm4857_state & 0x0f); | 622 | lm4857_regs[LM4857_CTRL] |= (lm4857_state & 0x0f); |
@@ -644,7 +627,7 @@ static int lm4857_resume(struct i2c_client *dev) | |||
644 | 627 | ||
645 | static void lm4857_shutdown(struct i2c_client *dev) | 628 | static void lm4857_shutdown(struct i2c_client *dev) |
646 | { | 629 | { |
647 | DBG("Entered %s\n", __func__); | 630 | pr_debug("Entered %s\n", __func__); |
648 | 631 | ||
649 | dev_dbg(&dev->dev, "lm4857_shutdown\n"); | 632 | dev_dbg(&dev->dev, "lm4857_shutdown\n"); |
650 | lm4857_regs[LM4857_CTRL] &= 0xf0; | 633 | lm4857_regs[LM4857_CTRL] &= 0xf0; |
@@ -675,7 +658,7 @@ static int __init neo1973_init(void) | |||
675 | { | 658 | { |
676 | int ret; | 659 | int ret; |
677 | 660 | ||
678 | DBG("Entered %s\n", __func__); | 661 | pr_debug("Entered %s\n", __func__); |
679 | 662 | ||
680 | if (!machine_is_neo1973_gta01()) { | 663 | if (!machine_is_neo1973_gta01()) { |
681 | printk(KERN_INFO | 664 | printk(KERN_INFO |
@@ -706,7 +689,7 @@ static int __init neo1973_init(void) | |||
706 | 689 | ||
707 | static void __exit neo1973_exit(void) | 690 | static void __exit neo1973_exit(void) |
708 | { | 691 | { |
709 | DBG("Entered %s\n", __func__); | 692 | pr_debug("Entered %s\n", __func__); |
710 | 693 | ||
711 | i2c_del_driver(&lm4857_i2c_driver); | 694 | i2c_del_driver(&lm4857_i2c_driver); |
712 | platform_device_unregister(neo1973_snd_device); | 695 | platform_device_unregister(neo1973_snd_device); |
diff --git a/sound/soc/s3c24xx/s3c-i2s-v2.c b/sound/soc/s3c24xx/s3c-i2s-v2.c new file mode 100644 index 000000000000..295a4c910262 --- /dev/null +++ b/sound/soc/s3c24xx/s3c-i2s-v2.c | |||
@@ -0,0 +1,638 @@ | |||
1 | /* sound/soc/s3c24xx/s3c-i2c-v2.c | ||
2 | * | ||
3 | * ALSA Soc Audio Layer - I2S core for newer Samsung SoCs. | ||
4 | * | ||
5 | * Copyright (c) 2006 Wolfson Microelectronics PLC. | ||
6 | * Graeme Gregory graeme.gregory@wolfsonmicro.com | ||
7 | * linux@wolfsonmicro.com | ||
8 | * | ||
9 | * Copyright (c) 2008, 2007, 2004-2005 Simtec Electronics | ||
10 | * http://armlinux.simtec.co.uk/ | ||
11 | * Ben Dooks <ben@simtec.co.uk> | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify it | ||
14 | * under the terms of the GNU General Public License as published by the | ||
15 | * Free Software Foundation; either version 2 of the License, or (at your | ||
16 | * option) any later version. | ||
17 | */ | ||
18 | |||
19 | #include <linux/init.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/device.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/clk.h> | ||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/io.h> | ||
26 | |||
27 | #include <sound/core.h> | ||
28 | #include <sound/pcm.h> | ||
29 | #include <sound/pcm_params.h> | ||
30 | #include <sound/initval.h> | ||
31 | #include <sound/soc.h> | ||
32 | |||
33 | #include <plat/regs-s3c2412-iis.h> | ||
34 | |||
35 | #include <plat/audio.h> | ||
36 | #include <mach/dma.h> | ||
37 | |||
38 | #include "s3c-i2s-v2.h" | ||
39 | |||
40 | #define S3C2412_I2S_DEBUG_CON 0 | ||
41 | |||
42 | static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai) | ||
43 | { | ||
44 | return cpu_dai->private_data; | ||
45 | } | ||
46 | |||
47 | #define bit_set(v, b) (((v) & (b)) ? 1 : 0) | ||
48 | |||
49 | #if S3C2412_I2S_DEBUG_CON | ||
50 | static void dbg_showcon(const char *fn, u32 con) | ||
51 | { | ||
52 | printk(KERN_DEBUG "%s: LRI=%d, TXFEMPT=%d, RXFEMPT=%d, TXFFULL=%d, RXFFULL=%d\n", fn, | ||
53 | bit_set(con, S3C2412_IISCON_LRINDEX), | ||
54 | bit_set(con, S3C2412_IISCON_TXFIFO_EMPTY), | ||
55 | bit_set(con, S3C2412_IISCON_RXFIFO_EMPTY), | ||
56 | bit_set(con, S3C2412_IISCON_TXFIFO_FULL), | ||
57 | bit_set(con, S3C2412_IISCON_RXFIFO_FULL)); | ||
58 | |||
59 | printk(KERN_DEBUG "%s: PAUSE: TXDMA=%d, RXDMA=%d, TXCH=%d, RXCH=%d\n", | ||
60 | fn, | ||
61 | bit_set(con, S3C2412_IISCON_TXDMA_PAUSE), | ||
62 | bit_set(con, S3C2412_IISCON_RXDMA_PAUSE), | ||
63 | bit_set(con, S3C2412_IISCON_TXCH_PAUSE), | ||
64 | bit_set(con, S3C2412_IISCON_RXCH_PAUSE)); | ||
65 | printk(KERN_DEBUG "%s: ACTIVE: TXDMA=%d, RXDMA=%d, IIS=%d\n", fn, | ||
66 | bit_set(con, S3C2412_IISCON_TXDMA_ACTIVE), | ||
67 | bit_set(con, S3C2412_IISCON_RXDMA_ACTIVE), | ||
68 | bit_set(con, S3C2412_IISCON_IIS_ACTIVE)); | ||
69 | } | ||
70 | #else | ||
71 | static inline void dbg_showcon(const char *fn, u32 con) | ||
72 | { | ||
73 | } | ||
74 | #endif | ||
75 | |||
76 | |||
77 | /* Turn on or off the transmission path. */ | ||
78 | void s3c2412_snd_txctrl(struct s3c_i2sv2_info *i2s, int on) | ||
79 | { | ||
80 | void __iomem *regs = i2s->regs; | ||
81 | u32 fic, con, mod; | ||
82 | |||
83 | pr_debug("%s(%d)\n", __func__, on); | ||
84 | |||
85 | fic = readl(regs + S3C2412_IISFIC); | ||
86 | con = readl(regs + S3C2412_IISCON); | ||
87 | mod = readl(regs + S3C2412_IISMOD); | ||
88 | |||
89 | pr_debug("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic); | ||
90 | |||
91 | if (on) { | ||
92 | con |= S3C2412_IISCON_TXDMA_ACTIVE | S3C2412_IISCON_IIS_ACTIVE; | ||
93 | con &= ~S3C2412_IISCON_TXDMA_PAUSE; | ||
94 | con &= ~S3C2412_IISCON_TXCH_PAUSE; | ||
95 | |||
96 | switch (mod & S3C2412_IISMOD_MODE_MASK) { | ||
97 | case S3C2412_IISMOD_MODE_TXONLY: | ||
98 | case S3C2412_IISMOD_MODE_TXRX: | ||
99 | /* do nothing, we are in the right mode */ | ||
100 | break; | ||
101 | |||
102 | case S3C2412_IISMOD_MODE_RXONLY: | ||
103 | mod &= ~S3C2412_IISMOD_MODE_MASK; | ||
104 | mod |= S3C2412_IISMOD_MODE_TXRX; | ||
105 | break; | ||
106 | |||
107 | default: | ||
108 | dev_err(i2s->dev, "TXEN: Invalid MODE in IISMOD\n"); | ||
109 | } | ||
110 | |||
111 | writel(con, regs + S3C2412_IISCON); | ||
112 | writel(mod, regs + S3C2412_IISMOD); | ||
113 | } else { | ||
114 | /* Note, we do not have any indication that the FIFO problems | ||
115 | * tha the S3C2410/2440 had apply here, so we should be able | ||
116 | * to disable the DMA and TX without resetting the FIFOS. | ||
117 | */ | ||
118 | |||
119 | con |= S3C2412_IISCON_TXDMA_PAUSE; | ||
120 | con |= S3C2412_IISCON_TXCH_PAUSE; | ||
121 | con &= ~S3C2412_IISCON_TXDMA_ACTIVE; | ||
122 | |||
123 | switch (mod & S3C2412_IISMOD_MODE_MASK) { | ||
124 | case S3C2412_IISMOD_MODE_TXRX: | ||
125 | mod &= ~S3C2412_IISMOD_MODE_MASK; | ||
126 | mod |= S3C2412_IISMOD_MODE_RXONLY; | ||
127 | break; | ||
128 | |||
129 | case S3C2412_IISMOD_MODE_TXONLY: | ||
130 | mod &= ~S3C2412_IISMOD_MODE_MASK; | ||
131 | con &= ~S3C2412_IISCON_IIS_ACTIVE; | ||
132 | break; | ||
133 | |||
134 | default: | ||
135 | dev_err(i2s->dev, "TXDIS: Invalid MODE in IISMOD\n"); | ||
136 | } | ||
137 | |||
138 | writel(mod, regs + S3C2412_IISMOD); | ||
139 | writel(con, regs + S3C2412_IISCON); | ||
140 | } | ||
141 | |||
142 | fic = readl(regs + S3C2412_IISFIC); | ||
143 | dbg_showcon(__func__, con); | ||
144 | pr_debug("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic); | ||
145 | } | ||
146 | EXPORT_SYMBOL_GPL(s3c2412_snd_txctrl); | ||
147 | |||
148 | void s3c2412_snd_rxctrl(struct s3c_i2sv2_info *i2s, int on) | ||
149 | { | ||
150 | void __iomem *regs = i2s->regs; | ||
151 | u32 fic, con, mod; | ||
152 | |||
153 | pr_debug("%s(%d)\n", __func__, on); | ||
154 | |||
155 | fic = readl(regs + S3C2412_IISFIC); | ||
156 | con = readl(regs + S3C2412_IISCON); | ||
157 | mod = readl(regs + S3C2412_IISMOD); | ||
158 | |||
159 | pr_debug("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic); | ||
160 | |||
161 | if (on) { | ||
162 | con |= S3C2412_IISCON_RXDMA_ACTIVE | S3C2412_IISCON_IIS_ACTIVE; | ||
163 | con &= ~S3C2412_IISCON_RXDMA_PAUSE; | ||
164 | con &= ~S3C2412_IISCON_RXCH_PAUSE; | ||
165 | |||
166 | switch (mod & S3C2412_IISMOD_MODE_MASK) { | ||
167 | case S3C2412_IISMOD_MODE_TXRX: | ||
168 | case S3C2412_IISMOD_MODE_RXONLY: | ||
169 | /* do nothing, we are in the right mode */ | ||
170 | break; | ||
171 | |||
172 | case S3C2412_IISMOD_MODE_TXONLY: | ||
173 | mod &= ~S3C2412_IISMOD_MODE_MASK; | ||
174 | mod |= S3C2412_IISMOD_MODE_TXRX; | ||
175 | break; | ||
176 | |||
177 | default: | ||
178 | dev_err(i2s->dev, "RXEN: Invalid MODE in IISMOD\n"); | ||
179 | } | ||
180 | |||
181 | writel(mod, regs + S3C2412_IISMOD); | ||
182 | writel(con, regs + S3C2412_IISCON); | ||
183 | } else { | ||
184 | /* See txctrl notes on FIFOs. */ | ||
185 | |||
186 | con &= ~S3C2412_IISCON_RXDMA_ACTIVE; | ||
187 | con |= S3C2412_IISCON_RXDMA_PAUSE; | ||
188 | con |= S3C2412_IISCON_RXCH_PAUSE; | ||
189 | |||
190 | switch (mod & S3C2412_IISMOD_MODE_MASK) { | ||
191 | case S3C2412_IISMOD_MODE_RXONLY: | ||
192 | con &= ~S3C2412_IISCON_IIS_ACTIVE; | ||
193 | mod &= ~S3C2412_IISMOD_MODE_MASK; | ||
194 | break; | ||
195 | |||
196 | case S3C2412_IISMOD_MODE_TXRX: | ||
197 | mod &= ~S3C2412_IISMOD_MODE_MASK; | ||
198 | mod |= S3C2412_IISMOD_MODE_TXONLY; | ||
199 | break; | ||
200 | |||
201 | default: | ||
202 | dev_err(i2s->dev, "RXEN: Invalid MODE in IISMOD\n"); | ||
203 | } | ||
204 | |||
205 | writel(con, regs + S3C2412_IISCON); | ||
206 | writel(mod, regs + S3C2412_IISMOD); | ||
207 | } | ||
208 | |||
209 | fic = readl(regs + S3C2412_IISFIC); | ||
210 | pr_debug("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic); | ||
211 | } | ||
212 | EXPORT_SYMBOL_GPL(s3c2412_snd_rxctrl); | ||
213 | |||
214 | /* | ||
215 | * Wait for the LR signal to allow synchronisation to the L/R clock | ||
216 | * from the codec. May only be needed for slave mode. | ||
217 | */ | ||
218 | static int s3c2412_snd_lrsync(struct s3c_i2sv2_info *i2s) | ||
219 | { | ||
220 | u32 iiscon; | ||
221 | unsigned long timeout = jiffies + msecs_to_jiffies(5); | ||
222 | |||
223 | pr_debug("Entered %s\n", __func__); | ||
224 | |||
225 | while (1) { | ||
226 | iiscon = readl(i2s->regs + S3C2412_IISCON); | ||
227 | if (iiscon & S3C2412_IISCON_LRINDEX) | ||
228 | break; | ||
229 | |||
230 | if (timeout < jiffies) { | ||
231 | printk(KERN_ERR "%s: timeout\n", __func__); | ||
232 | return -ETIMEDOUT; | ||
233 | } | ||
234 | } | ||
235 | |||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | /* | ||
240 | * Set S3C2412 I2S DAI format | ||
241 | */ | ||
242 | static int s3c2412_i2s_set_fmt(struct snd_soc_dai *cpu_dai, | ||
243 | unsigned int fmt) | ||
244 | { | ||
245 | struct s3c_i2sv2_info *i2s = to_info(cpu_dai); | ||
246 | u32 iismod; | ||
247 | |||
248 | pr_debug("Entered %s\n", __func__); | ||
249 | |||
250 | iismod = readl(i2s->regs + S3C2412_IISMOD); | ||
251 | pr_debug("hw_params r: IISMOD: %x \n", iismod); | ||
252 | |||
253 | #if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413) | ||
254 | #define IISMOD_MASTER_MASK S3C2412_IISMOD_MASTER_MASK | ||
255 | #define IISMOD_SLAVE S3C2412_IISMOD_SLAVE | ||
256 | #define IISMOD_MASTER S3C2412_IISMOD_MASTER_INTERNAL | ||
257 | #endif | ||
258 | |||
259 | #if defined(CONFIG_PLAT_S3C64XX) | ||
260 | /* From Rev1.1 datasheet, we have two master and two slave modes: | ||
261 | * IMS[11:10]: | ||
262 | * 00 = master mode, fed from PCLK | ||
263 | * 01 = master mode, fed from CLKAUDIO | ||
264 | * 10 = slave mode, using PCLK | ||
265 | * 11 = slave mode, using I2SCLK | ||
266 | */ | ||
267 | #define IISMOD_MASTER_MASK (1 << 11) | ||
268 | #define IISMOD_SLAVE (1 << 11) | ||
269 | #define IISMOD_MASTER (0x0) | ||
270 | #endif | ||
271 | |||
272 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
273 | case SND_SOC_DAIFMT_CBM_CFM: | ||
274 | i2s->master = 0; | ||
275 | iismod &= ~IISMOD_MASTER_MASK; | ||
276 | iismod |= IISMOD_SLAVE; | ||
277 | break; | ||
278 | case SND_SOC_DAIFMT_CBS_CFS: | ||
279 | i2s->master = 1; | ||
280 | iismod &= ~IISMOD_MASTER_MASK; | ||
281 | iismod |= IISMOD_MASTER; | ||
282 | break; | ||
283 | default: | ||
284 | pr_debug("unknwon master/slave format\n"); | ||
285 | return -EINVAL; | ||
286 | } | ||
287 | |||
288 | iismod &= ~S3C2412_IISMOD_SDF_MASK; | ||
289 | |||
290 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
291 | case SND_SOC_DAIFMT_RIGHT_J: | ||
292 | iismod |= S3C2412_IISMOD_SDF_MSB; | ||
293 | break; | ||
294 | case SND_SOC_DAIFMT_LEFT_J: | ||
295 | iismod |= S3C2412_IISMOD_SDF_LSB; | ||
296 | break; | ||
297 | case SND_SOC_DAIFMT_I2S: | ||
298 | iismod |= S3C2412_IISMOD_SDF_IIS; | ||
299 | break; | ||
300 | default: | ||
301 | pr_debug("Unknown data format\n"); | ||
302 | return -EINVAL; | ||
303 | } | ||
304 | |||
305 | writel(iismod, i2s->regs + S3C2412_IISMOD); | ||
306 | pr_debug("hw_params w: IISMOD: %x \n", iismod); | ||
307 | return 0; | ||
308 | } | ||
309 | |||
310 | static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream, | ||
311 | struct snd_pcm_hw_params *params, | ||
312 | struct snd_soc_dai *socdai) | ||
313 | { | ||
314 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
315 | struct snd_soc_dai_link *dai = rtd->dai; | ||
316 | struct s3c_i2sv2_info *i2s = to_info(dai->cpu_dai); | ||
317 | u32 iismod; | ||
318 | |||
319 | pr_debug("Entered %s\n", __func__); | ||
320 | |||
321 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
322 | dai->cpu_dai->dma_data = i2s->dma_playback; | ||
323 | else | ||
324 | dai->cpu_dai->dma_data = i2s->dma_capture; | ||
325 | |||
326 | /* Working copies of register */ | ||
327 | iismod = readl(i2s->regs + S3C2412_IISMOD); | ||
328 | pr_debug("%s: r: IISMOD: %x\n", __func__, iismod); | ||
329 | |||
330 | switch (params_format(params)) { | ||
331 | case SNDRV_PCM_FORMAT_S8: | ||
332 | iismod |= S3C2412_IISMOD_8BIT; | ||
333 | break; | ||
334 | case SNDRV_PCM_FORMAT_S16_LE: | ||
335 | iismod &= ~S3C2412_IISMOD_8BIT; | ||
336 | break; | ||
337 | } | ||
338 | |||
339 | writel(iismod, i2s->regs + S3C2412_IISMOD); | ||
340 | pr_debug("%s: w: IISMOD: %x\n", __func__, iismod); | ||
341 | return 0; | ||
342 | } | ||
343 | |||
344 | static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | ||
345 | struct snd_soc_dai *dai) | ||
346 | { | ||
347 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
348 | struct s3c_i2sv2_info *i2s = to_info(rtd->dai->cpu_dai); | ||
349 | int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); | ||
350 | unsigned long irqs; | ||
351 | int ret = 0; | ||
352 | |||
353 | pr_debug("Entered %s\n", __func__); | ||
354 | |||
355 | switch (cmd) { | ||
356 | case SNDRV_PCM_TRIGGER_START: | ||
357 | /* On start, ensure that the FIFOs are cleared and reset. */ | ||
358 | |||
359 | writel(capture ? S3C2412_IISFIC_RXFLUSH : S3C2412_IISFIC_TXFLUSH, | ||
360 | i2s->regs + S3C2412_IISFIC); | ||
361 | |||
362 | /* clear again, just in case */ | ||
363 | writel(0x0, i2s->regs + S3C2412_IISFIC); | ||
364 | |||
365 | case SNDRV_PCM_TRIGGER_RESUME: | ||
366 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
367 | if (!i2s->master) { | ||
368 | ret = s3c2412_snd_lrsync(i2s); | ||
369 | if (ret) | ||
370 | goto exit_err; | ||
371 | } | ||
372 | |||
373 | local_irq_save(irqs); | ||
374 | |||
375 | if (capture) | ||
376 | s3c2412_snd_rxctrl(i2s, 1); | ||
377 | else | ||
378 | s3c2412_snd_txctrl(i2s, 1); | ||
379 | |||
380 | local_irq_restore(irqs); | ||
381 | break; | ||
382 | |||
383 | case SNDRV_PCM_TRIGGER_STOP: | ||
384 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
385 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
386 | local_irq_save(irqs); | ||
387 | |||
388 | if (capture) | ||
389 | s3c2412_snd_rxctrl(i2s, 0); | ||
390 | else | ||
391 | s3c2412_snd_txctrl(i2s, 0); | ||
392 | |||
393 | local_irq_restore(irqs); | ||
394 | break; | ||
395 | default: | ||
396 | ret = -EINVAL; | ||
397 | break; | ||
398 | } | ||
399 | |||
400 | exit_err: | ||
401 | return ret; | ||
402 | } | ||
403 | |||
404 | /* | ||
405 | * Set S3C2412 Clock dividers | ||
406 | */ | ||
407 | static int s3c2412_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai, | ||
408 | int div_id, int div) | ||
409 | { | ||
410 | struct s3c_i2sv2_info *i2s = to_info(cpu_dai); | ||
411 | u32 reg; | ||
412 | |||
413 | pr_debug("%s(%p, %d, %d)\n", __func__, cpu_dai, div_id, div); | ||
414 | |||
415 | switch (div_id) { | ||
416 | case S3C_I2SV2_DIV_BCLK: | ||
417 | reg = readl(i2s->regs + S3C2412_IISMOD); | ||
418 | reg &= ~S3C2412_IISMOD_BCLK_MASK; | ||
419 | writel(reg | div, i2s->regs + S3C2412_IISMOD); | ||
420 | |||
421 | pr_debug("%s: MOD=%08x\n", __func__, readl(i2s->regs + S3C2412_IISMOD)); | ||
422 | break; | ||
423 | |||
424 | case S3C_I2SV2_DIV_RCLK: | ||
425 | if (div > 3) { | ||
426 | /* convert value to bit field */ | ||
427 | |||
428 | switch (div) { | ||
429 | case 256: | ||
430 | div = S3C2412_IISMOD_RCLK_256FS; | ||
431 | break; | ||
432 | |||
433 | case 384: | ||
434 | div = S3C2412_IISMOD_RCLK_384FS; | ||
435 | break; | ||
436 | |||
437 | case 512: | ||
438 | div = S3C2412_IISMOD_RCLK_512FS; | ||
439 | break; | ||
440 | |||
441 | case 768: | ||
442 | div = S3C2412_IISMOD_RCLK_768FS; | ||
443 | break; | ||
444 | |||
445 | default: | ||
446 | return -EINVAL; | ||
447 | } | ||
448 | } | ||
449 | |||
450 | reg = readl(i2s->regs + S3C2412_IISMOD); | ||
451 | reg &= ~S3C2412_IISMOD_RCLK_MASK; | ||
452 | writel(reg | div, i2s->regs + S3C2412_IISMOD); | ||
453 | pr_debug("%s: MOD=%08x\n", __func__, readl(i2s->regs + S3C2412_IISMOD)); | ||
454 | break; | ||
455 | |||
456 | case S3C_I2SV2_DIV_PRESCALER: | ||
457 | if (div >= 0) { | ||
458 | writel((div << 8) | S3C2412_IISPSR_PSREN, | ||
459 | i2s->regs + S3C2412_IISPSR); | ||
460 | } else { | ||
461 | writel(0x0, i2s->regs + S3C2412_IISPSR); | ||
462 | } | ||
463 | pr_debug("%s: PSR=%08x\n", __func__, readl(i2s->regs + S3C2412_IISPSR)); | ||
464 | break; | ||
465 | |||
466 | default: | ||
467 | return -EINVAL; | ||
468 | } | ||
469 | |||
470 | return 0; | ||
471 | } | ||
472 | |||
473 | /* default table of all avaialable root fs divisors */ | ||
474 | static unsigned int iis_fs_tab[] = { 256, 512, 384, 768 }; | ||
475 | |||
476 | int s3c2412_iis_calc_rate(struct s3c_i2sv2_rate_calc *info, | ||
477 | unsigned int *fstab, | ||
478 | unsigned int rate, struct clk *clk) | ||
479 | { | ||
480 | unsigned long clkrate = clk_get_rate(clk); | ||
481 | unsigned int div; | ||
482 | unsigned int fsclk; | ||
483 | unsigned int actual; | ||
484 | unsigned int fs; | ||
485 | unsigned int fsdiv; | ||
486 | signed int deviation = 0; | ||
487 | unsigned int best_fs = 0; | ||
488 | unsigned int best_div = 0; | ||
489 | unsigned int best_rate = 0; | ||
490 | unsigned int best_deviation = INT_MAX; | ||
491 | |||
492 | if (fstab == NULL) | ||
493 | fstab = iis_fs_tab; | ||
494 | |||
495 | for (fs = 0; fs < ARRAY_SIZE(iis_fs_tab); fs++) { | ||
496 | fsdiv = iis_fs_tab[fs]; | ||
497 | |||
498 | fsclk = clkrate / fsdiv; | ||
499 | div = fsclk / rate; | ||
500 | |||
501 | if ((fsclk % rate) > (rate / 2)) | ||
502 | div++; | ||
503 | |||
504 | if (div <= 1) | ||
505 | continue; | ||
506 | |||
507 | actual = clkrate / (fsdiv * div); | ||
508 | deviation = actual - rate; | ||
509 | |||
510 | printk(KERN_DEBUG "%dfs: div %d => result %d, deviation %d\n", | ||
511 | fsdiv, div, actual, deviation); | ||
512 | |||
513 | deviation = abs(deviation); | ||
514 | |||
515 | if (deviation < best_deviation) { | ||
516 | best_fs = fsdiv; | ||
517 | best_div = div; | ||
518 | best_rate = actual; | ||
519 | best_deviation = deviation; | ||
520 | } | ||
521 | |||
522 | if (deviation == 0) | ||
523 | break; | ||
524 | } | ||
525 | |||
526 | printk(KERN_DEBUG "best: fs=%d, div=%d, rate=%d\n", | ||
527 | best_fs, best_div, best_rate); | ||
528 | |||
529 | info->fs_div = best_fs; | ||
530 | info->clk_div = best_div; | ||
531 | |||
532 | return 0; | ||
533 | } | ||
534 | EXPORT_SYMBOL_GPL(s3c2412_iis_calc_rate); | ||
535 | |||
536 | int s3c_i2sv2_probe(struct platform_device *pdev, | ||
537 | struct snd_soc_dai *dai, | ||
538 | struct s3c_i2sv2_info *i2s, | ||
539 | unsigned long base) | ||
540 | { | ||
541 | struct device *dev = &pdev->dev; | ||
542 | |||
543 | i2s->dev = dev; | ||
544 | |||
545 | /* record our i2s structure for later use in the callbacks */ | ||
546 | dai->private_data = i2s; | ||
547 | |||
548 | i2s->regs = ioremap(base, 0x100); | ||
549 | if (i2s->regs == NULL) { | ||
550 | dev_err(dev, "cannot ioremap registers\n"); | ||
551 | return -ENXIO; | ||
552 | } | ||
553 | |||
554 | i2s->iis_pclk = clk_get(dev, "iis"); | ||
555 | if (i2s->iis_pclk == NULL) { | ||
556 | dev_err(dev, "failed to get iis_clock\n"); | ||
557 | iounmap(i2s->regs); | ||
558 | return -ENOENT; | ||
559 | } | ||
560 | |||
561 | clk_enable(i2s->iis_pclk); | ||
562 | |||
563 | s3c2412_snd_txctrl(i2s, 0); | ||
564 | s3c2412_snd_rxctrl(i2s, 0); | ||
565 | |||
566 | return 0; | ||
567 | } | ||
568 | |||
569 | EXPORT_SYMBOL_GPL(s3c_i2sv2_probe); | ||
570 | |||
571 | #ifdef CONFIG_PM | ||
572 | static int s3c2412_i2s_suspend(struct snd_soc_dai *dai) | ||
573 | { | ||
574 | struct s3c_i2sv2_info *i2s = to_info(dai); | ||
575 | u32 iismod; | ||
576 | |||
577 | if (dai->active) { | ||
578 | i2s->suspend_iismod = readl(i2s->regs + S3C2412_IISMOD); | ||
579 | i2s->suspend_iiscon = readl(i2s->regs + S3C2412_IISCON); | ||
580 | i2s->suspend_iispsr = readl(i2s->regs + S3C2412_IISPSR); | ||
581 | |||
582 | /* some basic suspend checks */ | ||
583 | |||
584 | iismod = readl(i2s->regs + S3C2412_IISMOD); | ||
585 | |||
586 | if (iismod & S3C2412_IISCON_RXDMA_ACTIVE) | ||
587 | pr_warning("%s: RXDMA active?\n", __func__); | ||
588 | |||
589 | if (iismod & S3C2412_IISCON_TXDMA_ACTIVE) | ||
590 | pr_warning("%s: TXDMA active?\n", __func__); | ||
591 | |||
592 | if (iismod & S3C2412_IISCON_IIS_ACTIVE) | ||
593 | pr_warning("%s: IIS active\n", __func__); | ||
594 | } | ||
595 | |||
596 | return 0; | ||
597 | } | ||
598 | |||
599 | static int s3c2412_i2s_resume(struct snd_soc_dai *dai) | ||
600 | { | ||
601 | struct s3c_i2sv2_info *i2s = to_info(dai); | ||
602 | |||
603 | pr_info("dai_active %d, IISMOD %08x, IISCON %08x\n", | ||
604 | dai->active, i2s->suspend_iismod, i2s->suspend_iiscon); | ||
605 | |||
606 | if (dai->active) { | ||
607 | writel(i2s->suspend_iiscon, i2s->regs + S3C2412_IISCON); | ||
608 | writel(i2s->suspend_iismod, i2s->regs + S3C2412_IISMOD); | ||
609 | writel(i2s->suspend_iispsr, i2s->regs + S3C2412_IISPSR); | ||
610 | |||
611 | writel(S3C2412_IISFIC_RXFLUSH | S3C2412_IISFIC_TXFLUSH, | ||
612 | i2s->regs + S3C2412_IISFIC); | ||
613 | |||
614 | ndelay(250); | ||
615 | writel(0x0, i2s->regs + S3C2412_IISFIC); | ||
616 | } | ||
617 | |||
618 | return 0; | ||
619 | } | ||
620 | #else | ||
621 | #define s3c2412_i2s_suspend NULL | ||
622 | #define s3c2412_i2s_resume NULL | ||
623 | #endif | ||
624 | |||
625 | int s3c_i2sv2_register_dai(struct snd_soc_dai *dai) | ||
626 | { | ||
627 | dai->ops.trigger = s3c2412_i2s_trigger; | ||
628 | dai->ops.hw_params = s3c2412_i2s_hw_params; | ||
629 | dai->ops.set_fmt = s3c2412_i2s_set_fmt; | ||
630 | dai->ops.set_clkdiv = s3c2412_i2s_set_clkdiv; | ||
631 | |||
632 | dai->suspend = s3c2412_i2s_suspend; | ||
633 | dai->resume = s3c2412_i2s_resume; | ||
634 | |||
635 | return snd_soc_register_dai(dai); | ||
636 | } | ||
637 | |||
638 | EXPORT_SYMBOL_GPL(s3c_i2sv2_register_dai); | ||
diff --git a/sound/soc/s3c24xx/s3c-i2s-v2.h b/sound/soc/s3c24xx/s3c-i2s-v2.h new file mode 100644 index 000000000000..f66854a77fb2 --- /dev/null +++ b/sound/soc/s3c24xx/s3c-i2s-v2.h | |||
@@ -0,0 +1,90 @@ | |||
1 | /* sound/soc/s3c24xx/s3c-i2s-v2.h | ||
2 | * | ||
3 | * ALSA Soc Audio Layer - S3C_I2SV2 I2S driver | ||
4 | * | ||
5 | * Copyright (c) 2007 Simtec Electronics | ||
6 | * http://armlinux.simtec.co.uk/ | ||
7 | * Ben Dooks <ben@simtec.co.uk> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | */ | ||
14 | |||
15 | /* This code is the core support for the I2S block found in a number of | ||
16 | * Samsung SoC devices which is unofficially named I2S-V2. Currently the | ||
17 | * S3C2412 and the S3C64XX series use this block to provide 1 or 2 I2S | ||
18 | * channels via configurable GPIO. | ||
19 | */ | ||
20 | |||
21 | #ifndef __SND_SOC_S3C24XX_S3C_I2SV2_I2S_H | ||
22 | #define __SND_SOC_S3C24XX_S3C_I2SV2_I2S_H __FILE__ | ||
23 | |||
24 | #define S3C_I2SV2_DIV_BCLK (1) | ||
25 | #define S3C_I2SV2_DIV_RCLK (2) | ||
26 | #define S3C_I2SV2_DIV_PRESCALER (3) | ||
27 | |||
28 | /** | ||
29 | * struct s3c_i2sv2_info - S3C I2S-V2 information | ||
30 | * @dev: The parent device passed to use from the probe. | ||
31 | * @regs: The pointer to the device registe block. | ||
32 | * @master: True if the I2S core is the I2S bit clock master. | ||
33 | * @dma_playback: DMA information for playback channel. | ||
34 | * @dma_capture: DMA information for capture channel. | ||
35 | * @suspend_iismod: PM save for the IISMOD register. | ||
36 | * @suspend_iiscon: PM save for the IISCON register. | ||
37 | * @suspend_iispsr: PM save for the IISPSR register. | ||
38 | * | ||
39 | * This is the private codec state for the hardware associated with an | ||
40 | * I2S channel such as the register mappings and clock sources. | ||
41 | */ | ||
42 | struct s3c_i2sv2_info { | ||
43 | struct device *dev; | ||
44 | void __iomem *regs; | ||
45 | |||
46 | struct clk *iis_pclk; | ||
47 | struct clk *iis_cclk; | ||
48 | struct clk *iis_clk; | ||
49 | |||
50 | unsigned char master; | ||
51 | |||
52 | struct s3c24xx_pcm_dma_params *dma_playback; | ||
53 | struct s3c24xx_pcm_dma_params *dma_capture; | ||
54 | |||
55 | u32 suspend_iismod; | ||
56 | u32 suspend_iiscon; | ||
57 | u32 suspend_iispsr; | ||
58 | }; | ||
59 | |||
60 | struct s3c_i2sv2_rate_calc { | ||
61 | unsigned int clk_div; /* for prescaler */ | ||
62 | unsigned int fs_div; /* for root frame clock */ | ||
63 | }; | ||
64 | |||
65 | extern int s3c_i2sv2_iis_calc_rate(struct s3c_i2sv2_rate_calc *info, | ||
66 | unsigned int *fstab, | ||
67 | unsigned int rate, struct clk *clk); | ||
68 | |||
69 | /** | ||
70 | * s3c_i2sv2_probe - probe for i2s device helper | ||
71 | * @pdev: The platform device supplied to the original probe. | ||
72 | * @dai: The ASoC DAI structure supplied to the original probe. | ||
73 | * @i2s: Our local i2s structure to fill in. | ||
74 | * @base: The base address for the registers. | ||
75 | */ | ||
76 | extern int s3c_i2sv2_probe(struct platform_device *pdev, | ||
77 | struct snd_soc_dai *dai, | ||
78 | struct s3c_i2sv2_info *i2s, | ||
79 | unsigned long base); | ||
80 | |||
81 | /** | ||
82 | * s3c_i2sv2_register_dai - register dai with soc core | ||
83 | * @dai: The snd_soc_dai structure to register | ||
84 | * | ||
85 | * Fill in any missing fields and then register the given dai with the | ||
86 | * soc core. | ||
87 | */ | ||
88 | extern int s3c_i2sv2_register_dai(struct snd_soc_dai *dai); | ||
89 | |||
90 | #endif /* __SND_SOC_S3C24XX_S3C_I2SV2_I2S_H */ | ||
diff --git a/sound/soc/s3c24xx/s3c2412-i2s.c b/sound/soc/s3c24xx/s3c2412-i2s.c index f3fc0aba0aaf..1ca3cdaa8213 100644 --- a/sound/soc/s3c24xx/s3c2412-i2s.c +++ b/sound/soc/s3c24xx/s3c2412-i2s.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
23 | #include <linux/clk.h> | 23 | #include <linux/clk.h> |
24 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
25 | #include <linux/io.h> | ||
25 | 26 | ||
26 | #include <sound/core.h> | 27 | #include <sound/core.h> |
27 | #include <sound/pcm.h> | 28 | #include <sound/pcm.h> |
@@ -30,26 +31,16 @@ | |||
30 | #include <sound/soc.h> | 31 | #include <sound/soc.h> |
31 | #include <mach/hardware.h> | 32 | #include <mach/hardware.h> |
32 | 33 | ||
33 | #include <linux/io.h> | 34 | #include <plat/regs-s3c2412-iis.h> |
34 | #include <asm/dma.h> | ||
35 | |||
36 | #include <asm/plat-s3c24xx/regs-s3c2412-iis.h> | ||
37 | 35 | ||
38 | #include <mach/regs-gpio.h> | 36 | #include <plat/regs-gpio.h> |
39 | #include <mach/audio.h> | 37 | #include <plat/audio.h> |
40 | #include <mach/dma.h> | 38 | #include <mach/dma.h> |
41 | 39 | ||
42 | #include "s3c24xx-pcm.h" | 40 | #include "s3c24xx-pcm.h" |
43 | #include "s3c2412-i2s.h" | 41 | #include "s3c2412-i2s.h" |
44 | 42 | ||
45 | #define S3C2412_I2S_DEBUG 0 | 43 | #define S3C2412_I2S_DEBUG 0 |
46 | #define S3C2412_I2S_DEBUG_CON 0 | ||
47 | |||
48 | #if S3C2412_I2S_DEBUG | ||
49 | #define DBG(x...) printk(KERN_INFO x) | ||
50 | #else | ||
51 | #define DBG(x...) do { } while (0) | ||
52 | #endif | ||
53 | 44 | ||
54 | static struct s3c2410_dma_client s3c2412_dma_client_out = { | 45 | static struct s3c2410_dma_client s3c2412_dma_client_out = { |
55 | .name = "I2S PCM Stereo out" | 46 | .name = "I2S PCM Stereo out" |
@@ -73,431 +64,7 @@ static struct s3c24xx_pcm_dma_params s3c2412_i2s_pcm_stereo_in = { | |||
73 | .dma_size = 4, | 64 | .dma_size = 4, |
74 | }; | 65 | }; |
75 | 66 | ||
76 | struct s3c2412_i2s_info { | 67 | static struct s3c_i2sv2_info s3c2412_i2s; |
77 | struct device *dev; | ||
78 | void __iomem *regs; | ||
79 | struct clk *iis_clk; | ||
80 | struct clk *iis_pclk; | ||
81 | struct clk *iis_cclk; | ||
82 | |||
83 | u32 suspend_iismod; | ||
84 | u32 suspend_iiscon; | ||
85 | u32 suspend_iispsr; | ||
86 | }; | ||
87 | |||
88 | static struct s3c2412_i2s_info s3c2412_i2s; | ||
89 | |||
90 | #define bit_set(v, b) (((v) & (b)) ? 1 : 0) | ||
91 | |||
92 | #if S3C2412_I2S_DEBUG_CON | ||
93 | static void dbg_showcon(const char *fn, u32 con) | ||
94 | { | ||
95 | printk(KERN_DEBUG "%s: LRI=%d, TXFEMPT=%d, RXFEMPT=%d, TXFFULL=%d, RXFFULL=%d\n", fn, | ||
96 | bit_set(con, S3C2412_IISCON_LRINDEX), | ||
97 | bit_set(con, S3C2412_IISCON_TXFIFO_EMPTY), | ||
98 | bit_set(con, S3C2412_IISCON_RXFIFO_EMPTY), | ||
99 | bit_set(con, S3C2412_IISCON_TXFIFO_FULL), | ||
100 | bit_set(con, S3C2412_IISCON_RXFIFO_FULL)); | ||
101 | |||
102 | printk(KERN_DEBUG "%s: PAUSE: TXDMA=%d, RXDMA=%d, TXCH=%d, RXCH=%d\n", | ||
103 | fn, | ||
104 | bit_set(con, S3C2412_IISCON_TXDMA_PAUSE), | ||
105 | bit_set(con, S3C2412_IISCON_RXDMA_PAUSE), | ||
106 | bit_set(con, S3C2412_IISCON_TXCH_PAUSE), | ||
107 | bit_set(con, S3C2412_IISCON_RXCH_PAUSE)); | ||
108 | printk(KERN_DEBUG "%s: ACTIVE: TXDMA=%d, RXDMA=%d, IIS=%d\n", fn, | ||
109 | bit_set(con, S3C2412_IISCON_TXDMA_ACTIVE), | ||
110 | bit_set(con, S3C2412_IISCON_RXDMA_ACTIVE), | ||
111 | bit_set(con, S3C2412_IISCON_IIS_ACTIVE)); | ||
112 | } | ||
113 | #else | ||
114 | static inline void dbg_showcon(const char *fn, u32 con) | ||
115 | { | ||
116 | } | ||
117 | #endif | ||
118 | |||
119 | /* Turn on or off the transmission path. */ | ||
120 | static void s3c2412_snd_txctrl(int on) | ||
121 | { | ||
122 | struct s3c2412_i2s_info *i2s = &s3c2412_i2s; | ||
123 | void __iomem *regs = i2s->regs; | ||
124 | u32 fic, con, mod; | ||
125 | |||
126 | DBG("%s(%d)\n", __func__, on); | ||
127 | |||
128 | fic = readl(regs + S3C2412_IISFIC); | ||
129 | con = readl(regs + S3C2412_IISCON); | ||
130 | mod = readl(regs + S3C2412_IISMOD); | ||
131 | |||
132 | DBG("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic); | ||
133 | |||
134 | if (on) { | ||
135 | con |= S3C2412_IISCON_TXDMA_ACTIVE | S3C2412_IISCON_IIS_ACTIVE; | ||
136 | con &= ~S3C2412_IISCON_TXDMA_PAUSE; | ||
137 | con &= ~S3C2412_IISCON_TXCH_PAUSE; | ||
138 | |||
139 | switch (mod & S3C2412_IISMOD_MODE_MASK) { | ||
140 | case S3C2412_IISMOD_MODE_TXONLY: | ||
141 | case S3C2412_IISMOD_MODE_TXRX: | ||
142 | /* do nothing, we are in the right mode */ | ||
143 | break; | ||
144 | |||
145 | case S3C2412_IISMOD_MODE_RXONLY: | ||
146 | mod &= ~S3C2412_IISMOD_MODE_MASK; | ||
147 | mod |= S3C2412_IISMOD_MODE_TXRX; | ||
148 | break; | ||
149 | |||
150 | default: | ||
151 | dev_err(i2s->dev, "TXEN: Invalid MODE in IISMOD\n"); | ||
152 | } | ||
153 | |||
154 | writel(con, regs + S3C2412_IISCON); | ||
155 | writel(mod, regs + S3C2412_IISMOD); | ||
156 | } else { | ||
157 | /* Note, we do not have any indication that the FIFO problems | ||
158 | * tha the S3C2410/2440 had apply here, so we should be able | ||
159 | * to disable the DMA and TX without resetting the FIFOS. | ||
160 | */ | ||
161 | |||
162 | con |= S3C2412_IISCON_TXDMA_PAUSE; | ||
163 | con |= S3C2412_IISCON_TXCH_PAUSE; | ||
164 | con &= ~S3C2412_IISCON_TXDMA_ACTIVE; | ||
165 | |||
166 | switch (mod & S3C2412_IISMOD_MODE_MASK) { | ||
167 | case S3C2412_IISMOD_MODE_TXRX: | ||
168 | mod &= ~S3C2412_IISMOD_MODE_MASK; | ||
169 | mod |= S3C2412_IISMOD_MODE_RXONLY; | ||
170 | break; | ||
171 | |||
172 | case S3C2412_IISMOD_MODE_TXONLY: | ||
173 | mod &= ~S3C2412_IISMOD_MODE_MASK; | ||
174 | con &= ~S3C2412_IISCON_IIS_ACTIVE; | ||
175 | break; | ||
176 | |||
177 | default: | ||
178 | dev_err(i2s->dev, "TXDIS: Invalid MODE in IISMOD\n"); | ||
179 | } | ||
180 | |||
181 | writel(mod, regs + S3C2412_IISMOD); | ||
182 | writel(con, regs + S3C2412_IISCON); | ||
183 | } | ||
184 | |||
185 | fic = readl(regs + S3C2412_IISFIC); | ||
186 | dbg_showcon(__func__, con); | ||
187 | DBG("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic); | ||
188 | } | ||
189 | |||
190 | static void s3c2412_snd_rxctrl(int on) | ||
191 | { | ||
192 | struct s3c2412_i2s_info *i2s = &s3c2412_i2s; | ||
193 | void __iomem *regs = i2s->regs; | ||
194 | u32 fic, con, mod; | ||
195 | |||
196 | DBG("%s(%d)\n", __func__, on); | ||
197 | |||
198 | fic = readl(regs + S3C2412_IISFIC); | ||
199 | con = readl(regs + S3C2412_IISCON); | ||
200 | mod = readl(regs + S3C2412_IISMOD); | ||
201 | |||
202 | DBG("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic); | ||
203 | |||
204 | if (on) { | ||
205 | con |= S3C2412_IISCON_RXDMA_ACTIVE | S3C2412_IISCON_IIS_ACTIVE; | ||
206 | con &= ~S3C2412_IISCON_RXDMA_PAUSE; | ||
207 | con &= ~S3C2412_IISCON_RXCH_PAUSE; | ||
208 | |||
209 | switch (mod & S3C2412_IISMOD_MODE_MASK) { | ||
210 | case S3C2412_IISMOD_MODE_TXRX: | ||
211 | case S3C2412_IISMOD_MODE_RXONLY: | ||
212 | /* do nothing, we are in the right mode */ | ||
213 | break; | ||
214 | |||
215 | case S3C2412_IISMOD_MODE_TXONLY: | ||
216 | mod &= ~S3C2412_IISMOD_MODE_MASK; | ||
217 | mod |= S3C2412_IISMOD_MODE_TXRX; | ||
218 | break; | ||
219 | |||
220 | default: | ||
221 | dev_err(i2s->dev, "RXEN: Invalid MODE in IISMOD\n"); | ||
222 | } | ||
223 | |||
224 | writel(mod, regs + S3C2412_IISMOD); | ||
225 | writel(con, regs + S3C2412_IISCON); | ||
226 | } else { | ||
227 | /* See txctrl notes on FIFOs. */ | ||
228 | |||
229 | con &= ~S3C2412_IISCON_RXDMA_ACTIVE; | ||
230 | con |= S3C2412_IISCON_RXDMA_PAUSE; | ||
231 | con |= S3C2412_IISCON_RXCH_PAUSE; | ||
232 | |||
233 | switch (mod & S3C2412_IISMOD_MODE_MASK) { | ||
234 | case S3C2412_IISMOD_MODE_RXONLY: | ||
235 | con &= ~S3C2412_IISCON_IIS_ACTIVE; | ||
236 | mod &= ~S3C2412_IISMOD_MODE_MASK; | ||
237 | break; | ||
238 | |||
239 | case S3C2412_IISMOD_MODE_TXRX: | ||
240 | mod &= ~S3C2412_IISMOD_MODE_MASK; | ||
241 | mod |= S3C2412_IISMOD_MODE_TXONLY; | ||
242 | break; | ||
243 | |||
244 | default: | ||
245 | dev_err(i2s->dev, "RXEN: Invalid MODE in IISMOD\n"); | ||
246 | } | ||
247 | |||
248 | writel(con, regs + S3C2412_IISCON); | ||
249 | writel(mod, regs + S3C2412_IISMOD); | ||
250 | } | ||
251 | |||
252 | fic = readl(regs + S3C2412_IISFIC); | ||
253 | DBG("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic); | ||
254 | } | ||
255 | |||
256 | |||
257 | /* | ||
258 | * Wait for the LR signal to allow synchronisation to the L/R clock | ||
259 | * from the codec. May only be needed for slave mode. | ||
260 | */ | ||
261 | static int s3c2412_snd_lrsync(void) | ||
262 | { | ||
263 | u32 iiscon; | ||
264 | unsigned long timeout = jiffies + msecs_to_jiffies(5); | ||
265 | |||
266 | DBG("Entered %s\n", __func__); | ||
267 | |||
268 | while (1) { | ||
269 | iiscon = readl(s3c2412_i2s.regs + S3C2412_IISCON); | ||
270 | if (iiscon & S3C2412_IISCON_LRINDEX) | ||
271 | break; | ||
272 | |||
273 | if (timeout < jiffies) { | ||
274 | printk(KERN_ERR "%s: timeout\n", __func__); | ||
275 | return -ETIMEDOUT; | ||
276 | } | ||
277 | } | ||
278 | |||
279 | return 0; | ||
280 | } | ||
281 | |||
282 | /* | ||
283 | * Check whether CPU is the master or slave | ||
284 | */ | ||
285 | static inline int s3c2412_snd_is_clkmaster(void) | ||
286 | { | ||
287 | u32 iismod = readl(s3c2412_i2s.regs + S3C2412_IISMOD); | ||
288 | |||
289 | DBG("Entered %s\n", __func__); | ||
290 | |||
291 | iismod &= S3C2412_IISMOD_MASTER_MASK; | ||
292 | return !(iismod == S3C2412_IISMOD_SLAVE); | ||
293 | } | ||
294 | |||
295 | /* | ||
296 | * Set S3C2412 I2S DAI format | ||
297 | */ | ||
298 | static int s3c2412_i2s_set_fmt(struct snd_soc_dai *cpu_dai, | ||
299 | unsigned int fmt) | ||
300 | { | ||
301 | u32 iismod; | ||
302 | |||
303 | |||
304 | DBG("Entered %s\n", __func__); | ||
305 | |||
306 | iismod = readl(s3c2412_i2s.regs + S3C2412_IISMOD); | ||
307 | DBG("hw_params r: IISMOD: %x \n", iismod); | ||
308 | |||
309 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
310 | case SND_SOC_DAIFMT_CBM_CFM: | ||
311 | iismod &= ~S3C2412_IISMOD_MASTER_MASK; | ||
312 | iismod |= S3C2412_IISMOD_SLAVE; | ||
313 | break; | ||
314 | case SND_SOC_DAIFMT_CBS_CFS: | ||
315 | iismod &= ~S3C2412_IISMOD_MASTER_MASK; | ||
316 | iismod |= S3C2412_IISMOD_MASTER_INTERNAL; | ||
317 | break; | ||
318 | default: | ||
319 | DBG("unknwon master/slave format\n"); | ||
320 | return -EINVAL; | ||
321 | } | ||
322 | |||
323 | iismod &= ~S3C2412_IISMOD_SDF_MASK; | ||
324 | |||
325 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
326 | case SND_SOC_DAIFMT_RIGHT_J: | ||
327 | iismod |= S3C2412_IISMOD_SDF_MSB; | ||
328 | break; | ||
329 | case SND_SOC_DAIFMT_LEFT_J: | ||
330 | iismod |= S3C2412_IISMOD_SDF_LSB; | ||
331 | break; | ||
332 | case SND_SOC_DAIFMT_I2S: | ||
333 | iismod |= S3C2412_IISMOD_SDF_IIS; | ||
334 | break; | ||
335 | default: | ||
336 | DBG("Unknown data format\n"); | ||
337 | return -EINVAL; | ||
338 | } | ||
339 | |||
340 | writel(iismod, s3c2412_i2s.regs + S3C2412_IISMOD); | ||
341 | DBG("hw_params w: IISMOD: %x \n", iismod); | ||
342 | return 0; | ||
343 | } | ||
344 | |||
345 | static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream, | ||
346 | struct snd_pcm_hw_params *params, | ||
347 | struct snd_soc_dai *dai) | ||
348 | { | ||
349 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
350 | u32 iismod; | ||
351 | |||
352 | DBG("Entered %s\n", __func__); | ||
353 | |||
354 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
355 | rtd->dai->cpu_dai->dma_data = &s3c2412_i2s_pcm_stereo_out; | ||
356 | else | ||
357 | rtd->dai->cpu_dai->dma_data = &s3c2412_i2s_pcm_stereo_in; | ||
358 | |||
359 | /* Working copies of register */ | ||
360 | iismod = readl(s3c2412_i2s.regs + S3C2412_IISMOD); | ||
361 | DBG("%s: r: IISMOD: %x\n", __func__, iismod); | ||
362 | |||
363 | switch (params_format(params)) { | ||
364 | case SNDRV_PCM_FORMAT_S8: | ||
365 | iismod |= S3C2412_IISMOD_8BIT; | ||
366 | break; | ||
367 | case SNDRV_PCM_FORMAT_S16_LE: | ||
368 | iismod &= ~S3C2412_IISMOD_8BIT; | ||
369 | break; | ||
370 | } | ||
371 | |||
372 | writel(iismod, s3c2412_i2s.regs + S3C2412_IISMOD); | ||
373 | DBG("%s: w: IISMOD: %x\n", __func__, iismod); | ||
374 | return 0; | ||
375 | } | ||
376 | |||
377 | static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | ||
378 | struct snd_soc_dai *dai) | ||
379 | { | ||
380 | int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); | ||
381 | unsigned long irqs; | ||
382 | int ret = 0; | ||
383 | |||
384 | DBG("Entered %s\n", __func__); | ||
385 | |||
386 | switch (cmd) { | ||
387 | case SNDRV_PCM_TRIGGER_START: | ||
388 | /* On start, ensure that the FIFOs are cleared and reset. */ | ||
389 | |||
390 | writel(capture ? S3C2412_IISFIC_RXFLUSH : S3C2412_IISFIC_TXFLUSH, | ||
391 | s3c2412_i2s.regs + S3C2412_IISFIC); | ||
392 | |||
393 | /* clear again, just in case */ | ||
394 | writel(0x0, s3c2412_i2s.regs + S3C2412_IISFIC); | ||
395 | |||
396 | case SNDRV_PCM_TRIGGER_RESUME: | ||
397 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
398 | if (!s3c2412_snd_is_clkmaster()) { | ||
399 | ret = s3c2412_snd_lrsync(); | ||
400 | if (ret) | ||
401 | goto exit_err; | ||
402 | } | ||
403 | |||
404 | local_irq_save(irqs); | ||
405 | |||
406 | if (capture) | ||
407 | s3c2412_snd_rxctrl(1); | ||
408 | else | ||
409 | s3c2412_snd_txctrl(1); | ||
410 | |||
411 | local_irq_restore(irqs); | ||
412 | break; | ||
413 | |||
414 | case SNDRV_PCM_TRIGGER_STOP: | ||
415 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
416 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
417 | local_irq_save(irqs); | ||
418 | |||
419 | if (capture) | ||
420 | s3c2412_snd_rxctrl(0); | ||
421 | else | ||
422 | s3c2412_snd_txctrl(0); | ||
423 | |||
424 | local_irq_restore(irqs); | ||
425 | break; | ||
426 | default: | ||
427 | ret = -EINVAL; | ||
428 | break; | ||
429 | } | ||
430 | |||
431 | exit_err: | ||
432 | return ret; | ||
433 | } | ||
434 | |||
435 | /* default table of all avaialable root fs divisors */ | ||
436 | static unsigned int s3c2412_iis_fs[] = { 256, 512, 384, 768, 0 }; | ||
437 | |||
438 | int s3c2412_iis_calc_rate(struct s3c2412_rate_calc *info, | ||
439 | unsigned int *fstab, | ||
440 | unsigned int rate, struct clk *clk) | ||
441 | { | ||
442 | unsigned long clkrate = clk_get_rate(clk); | ||
443 | unsigned int div; | ||
444 | unsigned int fsclk; | ||
445 | unsigned int actual; | ||
446 | unsigned int fs; | ||
447 | unsigned int fsdiv; | ||
448 | signed int deviation = 0; | ||
449 | unsigned int best_fs = 0; | ||
450 | unsigned int best_div = 0; | ||
451 | unsigned int best_rate = 0; | ||
452 | unsigned int best_deviation = INT_MAX; | ||
453 | |||
454 | |||
455 | if (fstab == NULL) | ||
456 | fstab = s3c2412_iis_fs; | ||
457 | |||
458 | for (fs = 0;; fs++) { | ||
459 | fsdiv = s3c2412_iis_fs[fs]; | ||
460 | |||
461 | if (fsdiv == 0) | ||
462 | break; | ||
463 | |||
464 | fsclk = clkrate / fsdiv; | ||
465 | div = fsclk / rate; | ||
466 | |||
467 | if ((fsclk % rate) > (rate / 2)) | ||
468 | div++; | ||
469 | |||
470 | if (div <= 1) | ||
471 | continue; | ||
472 | |||
473 | actual = clkrate / (fsdiv * div); | ||
474 | deviation = actual - rate; | ||
475 | |||
476 | printk(KERN_DEBUG "%dfs: div %d => result %d, deviation %d\n", | ||
477 | fsdiv, div, actual, deviation); | ||
478 | |||
479 | deviation = abs(deviation); | ||
480 | |||
481 | if (deviation < best_deviation) { | ||
482 | best_fs = fsdiv; | ||
483 | best_div = div; | ||
484 | best_rate = actual; | ||
485 | best_deviation = deviation; | ||
486 | } | ||
487 | |||
488 | if (deviation == 0) | ||
489 | break; | ||
490 | } | ||
491 | |||
492 | printk(KERN_DEBUG "best: fs=%d, div=%d, rate=%d\n", | ||
493 | best_fs, best_div, best_rate); | ||
494 | |||
495 | info->fs_div = best_fs; | ||
496 | info->clk_div = best_div; | ||
497 | |||
498 | return 0; | ||
499 | } | ||
500 | EXPORT_SYMBOL_GPL(s3c2412_iis_calc_rate); | ||
501 | 68 | ||
502 | /* | 69 | /* |
503 | * Set S3C2412 Clock source | 70 | * Set S3C2412 Clock source |
@@ -507,15 +74,17 @@ static int s3c2412_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, | |||
507 | { | 74 | { |
508 | u32 iismod = readl(s3c2412_i2s.regs + S3C2412_IISMOD); | 75 | u32 iismod = readl(s3c2412_i2s.regs + S3C2412_IISMOD); |
509 | 76 | ||
510 | DBG("%s(%p, %d, %u, %d)\n", __func__, cpu_dai, clk_id, | 77 | pr_debug("%s(%p, %d, %u, %d)\n", __func__, cpu_dai, clk_id, |
511 | freq, dir); | 78 | freq, dir); |
512 | 79 | ||
513 | switch (clk_id) { | 80 | switch (clk_id) { |
514 | case S3C2412_CLKSRC_PCLK: | 81 | case S3C2412_CLKSRC_PCLK: |
82 | s3c2412_i2s.master = 1; | ||
515 | iismod &= ~S3C2412_IISMOD_MASTER_MASK; | 83 | iismod &= ~S3C2412_IISMOD_MASTER_MASK; |
516 | iismod |= S3C2412_IISMOD_MASTER_INTERNAL; | 84 | iismod |= S3C2412_IISMOD_MASTER_INTERNAL; |
517 | break; | 85 | break; |
518 | case S3C2412_CLKSRC_I2SCLK: | 86 | case S3C2412_CLKSRC_I2SCLK: |
87 | s3c2412_i2s.master = 0; | ||
519 | iismod &= ~S3C2412_IISMOD_MASTER_MASK; | 88 | iismod &= ~S3C2412_IISMOD_MASTER_MASK; |
520 | iismod |= S3C2412_IISMOD_MASTER_EXTERNAL; | 89 | iismod |= S3C2412_IISMOD_MASTER_EXTERNAL; |
521 | break; | 90 | break; |
@@ -527,74 +96,6 @@ static int s3c2412_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, | |||
527 | return 0; | 96 | return 0; |
528 | } | 97 | } |
529 | 98 | ||
530 | /* | ||
531 | * Set S3C2412 Clock dividers | ||
532 | */ | ||
533 | static int s3c2412_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai, | ||
534 | int div_id, int div) | ||
535 | { | ||
536 | struct s3c2412_i2s_info *i2s = &s3c2412_i2s; | ||
537 | u32 reg; | ||
538 | |||
539 | DBG("%s(%p, %d, %d)\n", __func__, cpu_dai, div_id, div); | ||
540 | |||
541 | switch (div_id) { | ||
542 | case S3C2412_DIV_BCLK: | ||
543 | reg = readl(i2s->regs + S3C2412_IISMOD); | ||
544 | reg &= ~S3C2412_IISMOD_BCLK_MASK; | ||
545 | writel(reg | div, i2s->regs + S3C2412_IISMOD); | ||
546 | |||
547 | DBG("%s: MOD=%08x\n", __func__, readl(i2s->regs + S3C2412_IISMOD)); | ||
548 | break; | ||
549 | |||
550 | case S3C2412_DIV_RCLK: | ||
551 | if (div > 3) { | ||
552 | /* convert value to bit field */ | ||
553 | |||
554 | switch (div) { | ||
555 | case 256: | ||
556 | div = S3C2412_IISMOD_RCLK_256FS; | ||
557 | break; | ||
558 | |||
559 | case 384: | ||
560 | div = S3C2412_IISMOD_RCLK_384FS; | ||
561 | break; | ||
562 | |||
563 | case 512: | ||
564 | div = S3C2412_IISMOD_RCLK_512FS; | ||
565 | break; | ||
566 | |||
567 | case 768: | ||
568 | div = S3C2412_IISMOD_RCLK_768FS; | ||
569 | break; | ||
570 | |||
571 | default: | ||
572 | return -EINVAL; | ||
573 | } | ||
574 | } | ||
575 | |||
576 | reg = readl(s3c2412_i2s.regs + S3C2412_IISMOD); | ||
577 | reg &= ~S3C2412_IISMOD_RCLK_MASK; | ||
578 | writel(reg | div, i2s->regs + S3C2412_IISMOD); | ||
579 | DBG("%s: MOD=%08x\n", __func__, readl(i2s->regs + S3C2412_IISMOD)); | ||
580 | break; | ||
581 | |||
582 | case S3C2412_DIV_PRESCALER: | ||
583 | if (div >= 0) { | ||
584 | writel((div << 8) | S3C2412_IISPSR_PSREN, | ||
585 | i2s->regs + S3C2412_IISPSR); | ||
586 | } else { | ||
587 | writel(0x0, i2s->regs + S3C2412_IISPSR); | ||
588 | } | ||
589 | DBG("%s: PSR=%08x\n", __func__, readl(i2s->regs + S3C2412_IISPSR)); | ||
590 | break; | ||
591 | |||
592 | default: | ||
593 | return -EINVAL; | ||
594 | } | ||
595 | |||
596 | return 0; | ||
597 | } | ||
598 | 99 | ||
599 | struct clk *s3c2412_get_iisclk(void) | 100 | struct clk *s3c2412_get_iisclk(void) |
600 | { | 101 | { |
@@ -606,34 +107,30 @@ EXPORT_SYMBOL_GPL(s3c2412_get_iisclk); | |||
606 | static int s3c2412_i2s_probe(struct platform_device *pdev, | 107 | static int s3c2412_i2s_probe(struct platform_device *pdev, |
607 | struct snd_soc_dai *dai) | 108 | struct snd_soc_dai *dai) |
608 | { | 109 | { |
609 | DBG("Entered %s\n", __func__); | 110 | int ret; |
610 | 111 | ||
611 | s3c2412_i2s.dev = &pdev->dev; | 112 | pr_debug("Entered %s\n", __func__); |
612 | 113 | ||
613 | s3c2412_i2s.regs = ioremap(S3C2410_PA_IIS, 0x100); | 114 | ret = s3c_i2sv2_probe(pdev, dai, &s3c2412_i2s, S3C2410_PA_IIS); |
614 | if (s3c2412_i2s.regs == NULL) | 115 | if (ret) |
615 | return -ENXIO; | 116 | return ret; |
616 | 117 | ||
617 | s3c2412_i2s.iis_pclk = clk_get(&pdev->dev, "iis"); | 118 | s3c2412_i2s.dma_capture = &s3c2412_i2s_pcm_stereo_in; |
618 | if (s3c2412_i2s.iis_pclk == NULL) { | 119 | s3c2412_i2s.dma_playback = &s3c2412_i2s_pcm_stereo_out; |
619 | DBG("failed to get iis_clock\n"); | ||
620 | iounmap(s3c2412_i2s.regs); | ||
621 | return -ENODEV; | ||
622 | } | ||
623 | 120 | ||
624 | s3c2412_i2s.iis_cclk = clk_get(&pdev->dev, "i2sclk"); | 121 | s3c2412_i2s.iis_cclk = clk_get(&pdev->dev, "i2sclk"); |
625 | if (s3c2412_i2s.iis_cclk == NULL) { | 122 | if (s3c2412_i2s.iis_cclk == NULL) { |
626 | DBG("failed to get i2sclk clock\n"); | 123 | pr_debug("failed to get i2sclk clock\n"); |
627 | iounmap(s3c2412_i2s.regs); | 124 | iounmap(s3c2412_i2s.regs); |
628 | return -ENODEV; | 125 | return -ENODEV; |
629 | } | 126 | } |
630 | 127 | ||
631 | clk_set_parent(s3c2412_i2s.iis_cclk, clk_get(NULL, "mpll")); | 128 | /* Set MPLL as the source for IIS CLK */ |
632 | 129 | ||
633 | clk_enable(s3c2412_i2s.iis_pclk); | 130 | clk_set_parent(s3c2412_i2s.iis_cclk, clk_get(NULL, "mpll")); |
634 | clk_enable(s3c2412_i2s.iis_cclk); | 131 | clk_enable(s3c2412_i2s.iis_cclk); |
635 | 132 | ||
636 | s3c2412_i2s.iis_clk = s3c2412_i2s.iis_pclk; | 133 | s3c2412_i2s.iis_cclk = s3c2412_i2s.iis_pclk; |
637 | 134 | ||
638 | /* Configure the I2S pins in correct mode */ | 135 | /* Configure the I2S pins in correct mode */ |
639 | s3c2410_gpio_cfgpin(S3C2410_GPE0, S3C2410_GPE0_I2SLRCK); | 136 | s3c2410_gpio_cfgpin(S3C2410_GPE0, S3C2410_GPE0_I2SLRCK); |
@@ -642,78 +139,22 @@ static int s3c2412_i2s_probe(struct platform_device *pdev, | |||
642 | s3c2410_gpio_cfgpin(S3C2410_GPE3, S3C2410_GPE3_I2SSDI); | 139 | s3c2410_gpio_cfgpin(S3C2410_GPE3, S3C2410_GPE3_I2SSDI); |
643 | s3c2410_gpio_cfgpin(S3C2410_GPE4, S3C2410_GPE4_I2SSDO); | 140 | s3c2410_gpio_cfgpin(S3C2410_GPE4, S3C2410_GPE4_I2SSDO); |
644 | 141 | ||
645 | s3c2412_snd_txctrl(0); | ||
646 | s3c2412_snd_rxctrl(0); | ||
647 | |||
648 | return 0; | 142 | return 0; |
649 | } | 143 | } |
650 | 144 | ||
651 | #ifdef CONFIG_PM | ||
652 | static int s3c2412_i2s_suspend(struct snd_soc_dai *dai) | ||
653 | { | ||
654 | struct s3c2412_i2s_info *i2s = &s3c2412_i2s; | ||
655 | u32 iismod; | ||
656 | |||
657 | if (dai->active) { | ||
658 | i2s->suspend_iismod = readl(i2s->regs + S3C2412_IISMOD); | ||
659 | i2s->suspend_iiscon = readl(i2s->regs + S3C2412_IISCON); | ||
660 | i2s->suspend_iispsr = readl(i2s->regs + S3C2412_IISPSR); | ||
661 | |||
662 | /* some basic suspend checks */ | ||
663 | |||
664 | iismod = readl(i2s->regs + S3C2412_IISMOD); | ||
665 | |||
666 | if (iismod & S3C2412_IISCON_RXDMA_ACTIVE) | ||
667 | pr_warning("%s: RXDMA active?\n", __func__); | ||
668 | |||
669 | if (iismod & S3C2412_IISCON_TXDMA_ACTIVE) | ||
670 | pr_warning("%s: TXDMA active?\n", __func__); | ||
671 | |||
672 | if (iismod & S3C2412_IISCON_IIS_ACTIVE) | ||
673 | pr_warning("%s: IIS active\n", __func__); | ||
674 | } | ||
675 | |||
676 | return 0; | ||
677 | } | ||
678 | |||
679 | static int s3c2412_i2s_resume(struct snd_soc_dai *dai) | ||
680 | { | ||
681 | struct s3c2412_i2s_info *i2s = &s3c2412_i2s; | ||
682 | |||
683 | pr_info("dai_active %d, IISMOD %08x, IISCON %08x\n", | ||
684 | dai->active, i2s->suspend_iismod, i2s->suspend_iiscon); | ||
685 | |||
686 | if (dai->active) { | ||
687 | writel(i2s->suspend_iiscon, i2s->regs + S3C2412_IISCON); | ||
688 | writel(i2s->suspend_iismod, i2s->regs + S3C2412_IISMOD); | ||
689 | writel(i2s->suspend_iispsr, i2s->regs + S3C2412_IISPSR); | ||
690 | |||
691 | writel(S3C2412_IISFIC_RXFLUSH | S3C2412_IISFIC_TXFLUSH, | ||
692 | i2s->regs + S3C2412_IISFIC); | ||
693 | |||
694 | ndelay(250); | ||
695 | writel(0x0, i2s->regs + S3C2412_IISFIC); | ||
696 | |||
697 | } | ||
698 | |||
699 | return 0; | ||
700 | } | ||
701 | #else | ||
702 | #define s3c2412_i2s_suspend NULL | ||
703 | #define s3c2412_i2s_resume NULL | ||
704 | #endif /* CONFIG_PM */ | ||
705 | |||
706 | #define S3C2412_I2S_RATES \ | 145 | #define S3C2412_I2S_RATES \ |
707 | (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \ | 146 | (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \ |
708 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ | 147 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ |
709 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) | 148 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) |
710 | 149 | ||
150 | static struct snd_soc_dai_ops s3c2412_i2s_dai_ops = { | ||
151 | .set_sysclk = s3c2412_i2s_set_sysclk, | ||
152 | }; | ||
153 | |||
711 | struct snd_soc_dai s3c2412_i2s_dai = { | 154 | struct snd_soc_dai s3c2412_i2s_dai = { |
712 | .name = "s3c2412-i2s", | 155 | .name = "s3c2412-i2s", |
713 | .id = 0, | 156 | .id = 0, |
714 | .probe = s3c2412_i2s_probe, | 157 | .probe = s3c2412_i2s_probe, |
715 | .suspend = s3c2412_i2s_suspend, | ||
716 | .resume = s3c2412_i2s_resume, | ||
717 | .playback = { | 158 | .playback = { |
718 | .channels_min = 2, | 159 | .channels_min = 2, |
719 | .channels_max = 2, | 160 | .channels_max = 2, |
@@ -726,19 +167,13 @@ struct snd_soc_dai s3c2412_i2s_dai = { | |||
726 | .rates = S3C2412_I2S_RATES, | 167 | .rates = S3C2412_I2S_RATES, |
727 | .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE, | 168 | .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE, |
728 | }, | 169 | }, |
729 | .ops = { | 170 | .ops = &s3c2412_i2s_dai_ops, |
730 | .trigger = s3c2412_i2s_trigger, | ||
731 | .hw_params = s3c2412_i2s_hw_params, | ||
732 | .set_fmt = s3c2412_i2s_set_fmt, | ||
733 | .set_clkdiv = s3c2412_i2s_set_clkdiv, | ||
734 | .set_sysclk = s3c2412_i2s_set_sysclk, | ||
735 | }, | ||
736 | }; | 171 | }; |
737 | EXPORT_SYMBOL_GPL(s3c2412_i2s_dai); | 172 | EXPORT_SYMBOL_GPL(s3c2412_i2s_dai); |
738 | 173 | ||
739 | static int __init s3c2412_i2s_init(void) | 174 | static int __init s3c2412_i2s_init(void) |
740 | { | 175 | { |
741 | return snd_soc_register_dai(&s3c2412_i2s_dai); | 176 | return s3c_i2sv2_register_dai(&s3c2412_i2s_dai); |
742 | } | 177 | } |
743 | module_init(s3c2412_i2s_init); | 178 | module_init(s3c2412_i2s_init); |
744 | 179 | ||
@@ -748,7 +183,6 @@ static void __exit s3c2412_i2s_exit(void) | |||
748 | } | 183 | } |
749 | module_exit(s3c2412_i2s_exit); | 184 | module_exit(s3c2412_i2s_exit); |
750 | 185 | ||
751 | |||
752 | /* Module information */ | 186 | /* Module information */ |
753 | MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); | 187 | MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); |
754 | MODULE_DESCRIPTION("S3C2412 I2S SoC Interface"); | 188 | MODULE_DESCRIPTION("S3C2412 I2S SoC Interface"); |
diff --git a/sound/soc/s3c24xx/s3c2412-i2s.h b/sound/soc/s3c24xx/s3c2412-i2s.h index aac08a25e541..92848e54be16 100644 --- a/sound/soc/s3c24xx/s3c2412-i2s.h +++ b/sound/soc/s3c24xx/s3c2412-i2s.h | |||
@@ -15,9 +15,11 @@ | |||
15 | #ifndef __SND_SOC_S3C24XX_S3C2412_I2S_H | 15 | #ifndef __SND_SOC_S3C24XX_S3C2412_I2S_H |
16 | #define __SND_SOC_S3C24XX_S3C2412_I2S_H __FILE__ | 16 | #define __SND_SOC_S3C24XX_S3C2412_I2S_H __FILE__ |
17 | 17 | ||
18 | #define S3C2412_DIV_BCLK (1) | 18 | #include "s3c-i2s-v2.h" |
19 | #define S3C2412_DIV_RCLK (2) | 19 | |
20 | #define S3C2412_DIV_PRESCALER (3) | 20 | #define S3C2412_DIV_BCLK S3C_I2SV2_DIV_BCLK |
21 | #define S3C2412_DIV_RCLK S3C_I2SV2_DIV_RCLK | ||
22 | #define S3C2412_DIV_PRESCALER S3C_I2SV2_DIV_PRESCALER | ||
21 | 23 | ||
22 | #define S3C2412_CLKSRC_PCLK (0) | 24 | #define S3C2412_CLKSRC_PCLK (0) |
23 | #define S3C2412_CLKSRC_I2SCLK (1) | 25 | #define S3C2412_CLKSRC_I2SCLK (1) |
@@ -26,13 +28,4 @@ extern struct clk *s3c2412_get_iisclk(void); | |||
26 | 28 | ||
27 | extern struct snd_soc_dai s3c2412_i2s_dai; | 29 | extern struct snd_soc_dai s3c2412_i2s_dai; |
28 | 30 | ||
29 | struct s3c2412_rate_calc { | ||
30 | unsigned int clk_div; /* for prescaler */ | ||
31 | unsigned int fs_div; /* for root frame clock */ | ||
32 | }; | ||
33 | |||
34 | extern int s3c2412_iis_calc_rate(struct s3c2412_rate_calc *info, | ||
35 | unsigned int *fstab, | ||
36 | unsigned int rate, struct clk *clk); | ||
37 | |||
38 | #endif /* __SND_SOC_S3C24XX_S3C2412_I2S_H */ | 31 | #endif /* __SND_SOC_S3C24XX_S3C2412_I2S_H */ |
diff --git a/sound/soc/s3c24xx/s3c2443-ac97.c b/sound/soc/s3c24xx/s3c2443-ac97.c index 5822d2dd49ba..3698f707c44d 100644 --- a/sound/soc/s3c24xx/s3c2443-ac97.c +++ b/sound/soc/s3c24xx/s3c2443-ac97.c | |||
@@ -31,7 +31,7 @@ | |||
31 | #include <plat/regs-ac97.h> | 31 | #include <plat/regs-ac97.h> |
32 | #include <mach/regs-gpio.h> | 32 | #include <mach/regs-gpio.h> |
33 | #include <mach/regs-clock.h> | 33 | #include <mach/regs-clock.h> |
34 | #include <mach/audio.h> | 34 | #include <plat/audio.h> |
35 | #include <asm/dma.h> | 35 | #include <asm/dma.h> |
36 | #include <mach/dma.h> | 36 | #include <mach/dma.h> |
37 | 37 | ||
@@ -355,6 +355,16 @@ static int s3c2443_ac97_mic_trigger(struct snd_pcm_substream *substream, | |||
355 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \ | 355 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \ |
356 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) | 356 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) |
357 | 357 | ||
358 | static struct snd_soc_dai_ops s3c2443_ac97_dai_ops = { | ||
359 | .hw_params = s3c2443_ac97_hw_params, | ||
360 | .trigger = s3c2443_ac97_trigger, | ||
361 | }; | ||
362 | |||
363 | static struct snd_soc_dai_ops s3c2443_ac97_mic_dai_ops = { | ||
364 | .hw_params = s3c2443_ac97_hw_mic_params, | ||
365 | .trigger = s3c2443_ac97_mic_trigger, | ||
366 | }; | ||
367 | |||
358 | struct snd_soc_dai s3c2443_ac97_dai[] = { | 368 | struct snd_soc_dai s3c2443_ac97_dai[] = { |
359 | { | 369 | { |
360 | .name = "s3c2443-ac97", | 370 | .name = "s3c2443-ac97", |
@@ -374,9 +384,7 @@ struct snd_soc_dai s3c2443_ac97_dai[] = { | |||
374 | .channels_max = 2, | 384 | .channels_max = 2, |
375 | .rates = s3c2443_AC97_RATES, | 385 | .rates = s3c2443_AC97_RATES, |
376 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | 386 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, |
377 | .ops = { | 387 | .ops = &s3c2443_ac97_dai_ops, |
378 | .hw_params = s3c2443_ac97_hw_params, | ||
379 | .trigger = s3c2443_ac97_trigger}, | ||
380 | }, | 388 | }, |
381 | { | 389 | { |
382 | .name = "pxa2xx-ac97-mic", | 390 | .name = "pxa2xx-ac97-mic", |
@@ -388,9 +396,7 @@ struct snd_soc_dai s3c2443_ac97_dai[] = { | |||
388 | .channels_max = 1, | 396 | .channels_max = 1, |
389 | .rates = s3c2443_AC97_RATES, | 397 | .rates = s3c2443_AC97_RATES, |
390 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | 398 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, |
391 | .ops = { | 399 | .ops = &s3c2443_ac97_mic_dai_ops, |
392 | .hw_params = s3c2443_ac97_hw_mic_params, | ||
393 | .trigger = s3c2443_ac97_mic_trigger,}, | ||
394 | }, | 400 | }, |
395 | }; | 401 | }; |
396 | EXPORT_SYMBOL_GPL(s3c2443_ac97_dai); | 402 | EXPORT_SYMBOL_GPL(s3c2443_ac97_dai); |
diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.c b/sound/soc/s3c24xx/s3c24xx-i2s.c index 6f4d439b57aa..cc066964dad6 100644 --- a/sound/soc/s3c24xx/s3c24xx-i2s.c +++ b/sound/soc/s3c24xx/s3c24xx-i2s.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * (c) 2006 Wolfson Microelectronics PLC. | 4 | * (c) 2006 Wolfson Microelectronics PLC. |
5 | * Graeme Gregory graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com | 5 | * Graeme Gregory graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com |
6 | * | 6 | * |
7 | * (c) 2004-2005 Simtec Electronics | 7 | * Copyright 2004-2005 Simtec Electronics |
8 | * http://armlinux.simtec.co.uk/ | 8 | * http://armlinux.simtec.co.uk/ |
9 | * Ben Dooks <ben@simtec.co.uk> | 9 | * Ben Dooks <ben@simtec.co.uk> |
10 | * | 10 | * |
@@ -30,22 +30,15 @@ | |||
30 | #include <mach/hardware.h> | 30 | #include <mach/hardware.h> |
31 | #include <mach/regs-gpio.h> | 31 | #include <mach/regs-gpio.h> |
32 | #include <mach/regs-clock.h> | 32 | #include <mach/regs-clock.h> |
33 | #include <mach/audio.h> | 33 | #include <plat/audio.h> |
34 | #include <asm/dma.h> | 34 | #include <asm/dma.h> |
35 | #include <mach/dma.h> | 35 | #include <mach/dma.h> |
36 | 36 | ||
37 | #include <asm/plat-s3c24xx/regs-iis.h> | 37 | #include <plat/regs-iis.h> |
38 | 38 | ||
39 | #include "s3c24xx-pcm.h" | 39 | #include "s3c24xx-pcm.h" |
40 | #include "s3c24xx-i2s.h" | 40 | #include "s3c24xx-i2s.h" |
41 | 41 | ||
42 | #define S3C24XX_I2S_DEBUG 0 | ||
43 | #if S3C24XX_I2S_DEBUG | ||
44 | #define DBG(x...) printk(KERN_DEBUG "s3c24xx-i2s: " x) | ||
45 | #else | ||
46 | #define DBG(x...) | ||
47 | #endif | ||
48 | |||
49 | static struct s3c2410_dma_client s3c24xx_dma_client_out = { | 42 | static struct s3c2410_dma_client s3c24xx_dma_client_out = { |
50 | .name = "I2S PCM Stereo out" | 43 | .name = "I2S PCM Stereo out" |
51 | }; | 44 | }; |
@@ -84,13 +77,13 @@ static void s3c24xx_snd_txctrl(int on) | |||
84 | u32 iiscon; | 77 | u32 iiscon; |
85 | u32 iismod; | 78 | u32 iismod; |
86 | 79 | ||
87 | DBG("Entered %s\n", __func__); | 80 | pr_debug("Entered %s\n", __func__); |
88 | 81 | ||
89 | iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON); | 82 | iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON); |
90 | iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON); | 83 | iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON); |
91 | iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); | 84 | iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); |
92 | 85 | ||
93 | DBG("r: IISCON: %lx IISMOD: %lx IISFCON: %lx\n", iiscon, iismod, iisfcon); | 86 | pr_debug("r: IISCON: %x IISMOD: %x IISFCON: %x\n", iiscon, iismod, iisfcon); |
94 | 87 | ||
95 | if (on) { | 88 | if (on) { |
96 | iisfcon |= S3C2410_IISFCON_TXDMA | S3C2410_IISFCON_TXENABLE; | 89 | iisfcon |= S3C2410_IISFCON_TXDMA | S3C2410_IISFCON_TXENABLE; |
@@ -120,7 +113,7 @@ static void s3c24xx_snd_txctrl(int on) | |||
120 | writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD); | 113 | writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD); |
121 | } | 114 | } |
122 | 115 | ||
123 | DBG("w: IISCON: %lx IISMOD: %lx IISFCON: %lx\n", iiscon, iismod, iisfcon); | 116 | pr_debug("w: IISCON: %x IISMOD: %x IISFCON: %x\n", iiscon, iismod, iisfcon); |
124 | } | 117 | } |
125 | 118 | ||
126 | static void s3c24xx_snd_rxctrl(int on) | 119 | static void s3c24xx_snd_rxctrl(int on) |
@@ -129,13 +122,13 @@ static void s3c24xx_snd_rxctrl(int on) | |||
129 | u32 iiscon; | 122 | u32 iiscon; |
130 | u32 iismod; | 123 | u32 iismod; |
131 | 124 | ||
132 | DBG("Entered %s\n", __func__); | 125 | pr_debug("Entered %s\n", __func__); |
133 | 126 | ||
134 | iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON); | 127 | iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON); |
135 | iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON); | 128 | iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON); |
136 | iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); | 129 | iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); |
137 | 130 | ||
138 | DBG("r: IISCON: %lx IISMOD: %lx IISFCON: %lx\n", iiscon, iismod, iisfcon); | 131 | pr_debug("r: IISCON: %x IISMOD: %x IISFCON: %x\n", iiscon, iismod, iisfcon); |
139 | 132 | ||
140 | if (on) { | 133 | if (on) { |
141 | iisfcon |= S3C2410_IISFCON_RXDMA | S3C2410_IISFCON_RXENABLE; | 134 | iisfcon |= S3C2410_IISFCON_RXDMA | S3C2410_IISFCON_RXENABLE; |
@@ -165,7 +158,7 @@ static void s3c24xx_snd_rxctrl(int on) | |||
165 | writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD); | 158 | writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD); |
166 | } | 159 | } |
167 | 160 | ||
168 | DBG("w: IISCON: %lx IISMOD: %lx IISFCON: %lx\n", iiscon, iismod, iisfcon); | 161 | pr_debug("w: IISCON: %x IISMOD: %x IISFCON: %x\n", iiscon, iismod, iisfcon); |
169 | } | 162 | } |
170 | 163 | ||
171 | /* | 164 | /* |
@@ -177,7 +170,7 @@ static int s3c24xx_snd_lrsync(void) | |||
177 | u32 iiscon; | 170 | u32 iiscon; |
178 | int timeout = 50; /* 5ms */ | 171 | int timeout = 50; /* 5ms */ |
179 | 172 | ||
180 | DBG("Entered %s\n", __func__); | 173 | pr_debug("Entered %s\n", __func__); |
181 | 174 | ||
182 | while (1) { | 175 | while (1) { |
183 | iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON); | 176 | iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON); |
@@ -197,7 +190,7 @@ static int s3c24xx_snd_lrsync(void) | |||
197 | */ | 190 | */ |
198 | static inline int s3c24xx_snd_is_clkmaster(void) | 191 | static inline int s3c24xx_snd_is_clkmaster(void) |
199 | { | 192 | { |
200 | DBG("Entered %s\n", __func__); | 193 | pr_debug("Entered %s\n", __func__); |
201 | 194 | ||
202 | return (readl(s3c24xx_i2s.regs + S3C2410_IISMOD) & S3C2410_IISMOD_SLAVE) ? 0:1; | 195 | return (readl(s3c24xx_i2s.regs + S3C2410_IISMOD) & S3C2410_IISMOD_SLAVE) ? 0:1; |
203 | } | 196 | } |
@@ -210,10 +203,10 @@ static int s3c24xx_i2s_set_fmt(struct snd_soc_dai *cpu_dai, | |||
210 | { | 203 | { |
211 | u32 iismod; | 204 | u32 iismod; |
212 | 205 | ||
213 | DBG("Entered %s\n", __func__); | 206 | pr_debug("Entered %s\n", __func__); |
214 | 207 | ||
215 | iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); | 208 | iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); |
216 | DBG("hw_params r: IISMOD: %lx \n", iismod); | 209 | pr_debug("hw_params r: IISMOD: %x \n", iismod); |
217 | 210 | ||
218 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | 211 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { |
219 | case SND_SOC_DAIFMT_CBM_CFM: | 212 | case SND_SOC_DAIFMT_CBM_CFM: |
@@ -238,7 +231,7 @@ static int s3c24xx_i2s_set_fmt(struct snd_soc_dai *cpu_dai, | |||
238 | } | 231 | } |
239 | 232 | ||
240 | writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD); | 233 | writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD); |
241 | DBG("hw_params w: IISMOD: %lx \n", iismod); | 234 | pr_debug("hw_params w: IISMOD: %x \n", iismod); |
242 | return 0; | 235 | return 0; |
243 | } | 236 | } |
244 | 237 | ||
@@ -249,7 +242,7 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
249 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 242 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
250 | u32 iismod; | 243 | u32 iismod; |
251 | 244 | ||
252 | DBG("Entered %s\n", __func__); | 245 | pr_debug("Entered %s\n", __func__); |
253 | 246 | ||
254 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 247 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
255 | rtd->dai->cpu_dai->dma_data = &s3c24xx_i2s_pcm_stereo_out; | 248 | rtd->dai->cpu_dai->dma_data = &s3c24xx_i2s_pcm_stereo_out; |
@@ -258,7 +251,7 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
258 | 251 | ||
259 | /* Working copies of register */ | 252 | /* Working copies of register */ |
260 | iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); | 253 | iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); |
261 | DBG("hw_params r: IISMOD: %lx\n", iismod); | 254 | pr_debug("hw_params r: IISMOD: %x\n", iismod); |
262 | 255 | ||
263 | switch (params_format(params)) { | 256 | switch (params_format(params)) { |
264 | case SNDRV_PCM_FORMAT_S8: | 257 | case SNDRV_PCM_FORMAT_S8: |
@@ -276,7 +269,7 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
276 | } | 269 | } |
277 | 270 | ||
278 | writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD); | 271 | writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD); |
279 | DBG("hw_params w: IISMOD: %lx\n", iismod); | 272 | pr_debug("hw_params w: IISMOD: %x\n", iismod); |
280 | return 0; | 273 | return 0; |
281 | } | 274 | } |
282 | 275 | ||
@@ -285,7 +278,7 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | |||
285 | { | 278 | { |
286 | int ret = 0; | 279 | int ret = 0; |
287 | 280 | ||
288 | DBG("Entered %s\n", __func__); | 281 | pr_debug("Entered %s\n", __func__); |
289 | 282 | ||
290 | switch (cmd) { | 283 | switch (cmd) { |
291 | case SNDRV_PCM_TRIGGER_START: | 284 | case SNDRV_PCM_TRIGGER_START: |
@@ -327,7 +320,7 @@ static int s3c24xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, | |||
327 | { | 320 | { |
328 | u32 iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); | 321 | u32 iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); |
329 | 322 | ||
330 | DBG("Entered %s\n", __func__); | 323 | pr_debug("Entered %s\n", __func__); |
331 | 324 | ||
332 | iismod &= ~S3C2440_IISMOD_MPLL; | 325 | iismod &= ~S3C2440_IISMOD_MPLL; |
333 | 326 | ||
@@ -353,7 +346,7 @@ static int s3c24xx_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai, | |||
353 | { | 346 | { |
354 | u32 reg; | 347 | u32 reg; |
355 | 348 | ||
356 | DBG("Entered %s\n", __func__); | 349 | pr_debug("Entered %s\n", __func__); |
357 | 350 | ||
358 | switch (div_id) { | 351 | switch (div_id) { |
359 | case S3C24XX_DIV_BCLK: | 352 | case S3C24XX_DIV_BCLK: |
@@ -389,7 +382,7 @@ EXPORT_SYMBOL_GPL(s3c24xx_i2s_get_clockrate); | |||
389 | static int s3c24xx_i2s_probe(struct platform_device *pdev, | 382 | static int s3c24xx_i2s_probe(struct platform_device *pdev, |
390 | struct snd_soc_dai *dai) | 383 | struct snd_soc_dai *dai) |
391 | { | 384 | { |
392 | DBG("Entered %s\n", __func__); | 385 | pr_debug("Entered %s\n", __func__); |
393 | 386 | ||
394 | s3c24xx_i2s.regs = ioremap(S3C2410_PA_IIS, 0x100); | 387 | s3c24xx_i2s.regs = ioremap(S3C2410_PA_IIS, 0x100); |
395 | if (s3c24xx_i2s.regs == NULL) | 388 | if (s3c24xx_i2s.regs == NULL) |
@@ -397,7 +390,7 @@ static int s3c24xx_i2s_probe(struct platform_device *pdev, | |||
397 | 390 | ||
398 | s3c24xx_i2s.iis_clk = clk_get(&pdev->dev, "iis"); | 391 | s3c24xx_i2s.iis_clk = clk_get(&pdev->dev, "iis"); |
399 | if (s3c24xx_i2s.iis_clk == NULL) { | 392 | if (s3c24xx_i2s.iis_clk == NULL) { |
400 | DBG("failed to get iis_clock\n"); | 393 | pr_err("failed to get iis_clock\n"); |
401 | iounmap(s3c24xx_i2s.regs); | 394 | iounmap(s3c24xx_i2s.regs); |
402 | return -ENODEV; | 395 | return -ENODEV; |
403 | } | 396 | } |
@@ -421,7 +414,7 @@ static int s3c24xx_i2s_probe(struct platform_device *pdev, | |||
421 | #ifdef CONFIG_PM | 414 | #ifdef CONFIG_PM |
422 | static int s3c24xx_i2s_suspend(struct snd_soc_dai *cpu_dai) | 415 | static int s3c24xx_i2s_suspend(struct snd_soc_dai *cpu_dai) |
423 | { | 416 | { |
424 | DBG("Entered %s\n", __func__); | 417 | pr_debug("Entered %s\n", __func__); |
425 | 418 | ||
426 | s3c24xx_i2s.iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON); | 419 | s3c24xx_i2s.iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON); |
427 | s3c24xx_i2s.iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); | 420 | s3c24xx_i2s.iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); |
@@ -435,7 +428,7 @@ static int s3c24xx_i2s_suspend(struct snd_soc_dai *cpu_dai) | |||
435 | 428 | ||
436 | static int s3c24xx_i2s_resume(struct snd_soc_dai *cpu_dai) | 429 | static int s3c24xx_i2s_resume(struct snd_soc_dai *cpu_dai) |
437 | { | 430 | { |
438 | DBG("Entered %s\n", __func__); | 431 | pr_debug("Entered %s\n", __func__); |
439 | clk_enable(s3c24xx_i2s.iis_clk); | 432 | clk_enable(s3c24xx_i2s.iis_clk); |
440 | 433 | ||
441 | writel(s3c24xx_i2s.iiscon, s3c24xx_i2s.regs + S3C2410_IISCON); | 434 | writel(s3c24xx_i2s.iiscon, s3c24xx_i2s.regs + S3C2410_IISCON); |
@@ -456,6 +449,14 @@ static int s3c24xx_i2s_resume(struct snd_soc_dai *cpu_dai) | |||
456 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ | 449 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ |
457 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) | 450 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) |
458 | 451 | ||
452 | static struct snd_soc_dai_ops s3c24xx_i2s_dai_ops = { | ||
453 | .trigger = s3c24xx_i2s_trigger, | ||
454 | .hw_params = s3c24xx_i2s_hw_params, | ||
455 | .set_fmt = s3c24xx_i2s_set_fmt, | ||
456 | .set_clkdiv = s3c24xx_i2s_set_clkdiv, | ||
457 | .set_sysclk = s3c24xx_i2s_set_sysclk, | ||
458 | }; | ||
459 | |||
459 | struct snd_soc_dai s3c24xx_i2s_dai = { | 460 | struct snd_soc_dai s3c24xx_i2s_dai = { |
460 | .name = "s3c24xx-i2s", | 461 | .name = "s3c24xx-i2s", |
461 | .id = 0, | 462 | .id = 0, |
@@ -472,13 +473,7 @@ struct snd_soc_dai s3c24xx_i2s_dai = { | |||
472 | .channels_max = 2, | 473 | .channels_max = 2, |
473 | .rates = S3C24XX_I2S_RATES, | 474 | .rates = S3C24XX_I2S_RATES, |
474 | .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,}, | 475 | .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,}, |
475 | .ops = { | 476 | .ops = &s3c24xx_i2s_dai_ops, |
476 | .trigger = s3c24xx_i2s_trigger, | ||
477 | .hw_params = s3c24xx_i2s_hw_params, | ||
478 | .set_fmt = s3c24xx_i2s_set_fmt, | ||
479 | .set_clkdiv = s3c24xx_i2s_set_clkdiv, | ||
480 | .set_sysclk = s3c24xx_i2s_set_sysclk, | ||
481 | }, | ||
482 | }; | 477 | }; |
483 | EXPORT_SYMBOL_GPL(s3c24xx_i2s_dai); | 478 | EXPORT_SYMBOL_GPL(s3c24xx_i2s_dai); |
484 | 479 | ||
diff --git a/sound/soc/s3c24xx/s3c24xx-pcm.c b/sound/soc/s3c24xx/s3c24xx-pcm.c index 7c64d31d067e..a9d68fa2b34a 100644 --- a/sound/soc/s3c24xx/s3c24xx-pcm.c +++ b/sound/soc/s3c24xx/s3c24xx-pcm.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * (c) 2006 Wolfson Microelectronics PLC. | 4 | * (c) 2006 Wolfson Microelectronics PLC. |
5 | * Graeme Gregory graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com | 5 | * Graeme Gregory graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com |
6 | * | 6 | * |
7 | * (c) 2004-2005 Simtec Electronics | 7 | * Copyright 2004-2005 Simtec Electronics |
8 | * http://armlinux.simtec.co.uk/ | 8 | * http://armlinux.simtec.co.uk/ |
9 | * Ben Dooks <ben@simtec.co.uk> | 9 | * Ben Dooks <ben@simtec.co.uk> |
10 | * | 10 | * |
@@ -29,17 +29,10 @@ | |||
29 | #include <asm/dma.h> | 29 | #include <asm/dma.h> |
30 | #include <mach/hardware.h> | 30 | #include <mach/hardware.h> |
31 | #include <mach/dma.h> | 31 | #include <mach/dma.h> |
32 | #include <mach/audio.h> | 32 | #include <plat/audio.h> |
33 | 33 | ||
34 | #include "s3c24xx-pcm.h" | 34 | #include "s3c24xx-pcm.h" |
35 | 35 | ||
36 | #define S3C24XX_PCM_DEBUG 0 | ||
37 | #if S3C24XX_PCM_DEBUG | ||
38 | #define DBG(x...) printk(KERN_DEBUG "s3c24xx-pcm: " x) | ||
39 | #else | ||
40 | #define DBG(x...) | ||
41 | #endif | ||
42 | |||
43 | static const struct snd_pcm_hardware s3c24xx_pcm_hardware = { | 36 | static const struct snd_pcm_hardware s3c24xx_pcm_hardware = { |
44 | .info = SNDRV_PCM_INFO_INTERLEAVED | | 37 | .info = SNDRV_PCM_INFO_INTERLEAVED | |
45 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 38 | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
@@ -84,16 +77,16 @@ static void s3c24xx_pcm_enqueue(struct snd_pcm_substream *substream) | |||
84 | dma_addr_t pos = prtd->dma_pos; | 77 | dma_addr_t pos = prtd->dma_pos; |
85 | int ret; | 78 | int ret; |
86 | 79 | ||
87 | DBG("Entered %s\n", __func__); | 80 | pr_debug("Entered %s\n", __func__); |
88 | 81 | ||
89 | while (prtd->dma_loaded < prtd->dma_limit) { | 82 | while (prtd->dma_loaded < prtd->dma_limit) { |
90 | unsigned long len = prtd->dma_period; | 83 | unsigned long len = prtd->dma_period; |
91 | 84 | ||
92 | DBG("dma_loaded: %d\n", prtd->dma_loaded); | 85 | pr_debug("dma_loaded: %d\n", prtd->dma_loaded); |
93 | 86 | ||
94 | if ((pos + len) > prtd->dma_end) { | 87 | if ((pos + len) > prtd->dma_end) { |
95 | len = prtd->dma_end - pos; | 88 | len = prtd->dma_end - pos; |
96 | DBG(KERN_DEBUG "%s: corrected dma len %ld\n", | 89 | pr_debug(KERN_DEBUG "%s: corrected dma len %ld\n", |
97 | __func__, len); | 90 | __func__, len); |
98 | } | 91 | } |
99 | 92 | ||
@@ -119,7 +112,7 @@ static void s3c24xx_audio_buffdone(struct s3c2410_dma_chan *channel, | |||
119 | struct snd_pcm_substream *substream = dev_id; | 112 | struct snd_pcm_substream *substream = dev_id; |
120 | struct s3c24xx_runtime_data *prtd; | 113 | struct s3c24xx_runtime_data *prtd; |
121 | 114 | ||
122 | DBG("Entered %s\n", __func__); | 115 | pr_debug("Entered %s\n", __func__); |
123 | 116 | ||
124 | if (result == S3C2410_RES_ABORT || result == S3C2410_RES_ERR) | 117 | if (result == S3C2410_RES_ABORT || result == S3C2410_RES_ERR) |
125 | return; | 118 | return; |
@@ -148,7 +141,7 @@ static int s3c24xx_pcm_hw_params(struct snd_pcm_substream *substream, | |||
148 | unsigned long totbytes = params_buffer_bytes(params); | 141 | unsigned long totbytes = params_buffer_bytes(params); |
149 | int ret = 0; | 142 | int ret = 0; |
150 | 143 | ||
151 | DBG("Entered %s\n", __func__); | 144 | pr_debug("Entered %s\n", __func__); |
152 | 145 | ||
153 | /* return if this is a bufferless transfer e.g. | 146 | /* return if this is a bufferless transfer e.g. |
154 | * codec <--> BT codec or GSM modem -- lg FIXME */ | 147 | * codec <--> BT codec or GSM modem -- lg FIXME */ |
@@ -161,14 +154,14 @@ static int s3c24xx_pcm_hw_params(struct snd_pcm_substream *substream, | |||
161 | /* prepare DMA */ | 154 | /* prepare DMA */ |
162 | prtd->params = dma; | 155 | prtd->params = dma; |
163 | 156 | ||
164 | DBG("params %p, client %p, channel %d\n", prtd->params, | 157 | pr_debug("params %p, client %p, channel %d\n", prtd->params, |
165 | prtd->params->client, prtd->params->channel); | 158 | prtd->params->client, prtd->params->channel); |
166 | 159 | ||
167 | ret = s3c2410_dma_request(prtd->params->channel, | 160 | ret = s3c2410_dma_request(prtd->params->channel, |
168 | prtd->params->client, NULL); | 161 | prtd->params->client, NULL); |
169 | 162 | ||
170 | if (ret < 0) { | 163 | if (ret < 0) { |
171 | DBG(KERN_ERR "failed to get dma channel\n"); | 164 | printk(KERN_ERR "failed to get dma channel\n"); |
172 | return ret; | 165 | return ret; |
173 | } | 166 | } |
174 | } | 167 | } |
@@ -196,7 +189,7 @@ static int s3c24xx_pcm_hw_free(struct snd_pcm_substream *substream) | |||
196 | { | 189 | { |
197 | struct s3c24xx_runtime_data *prtd = substream->runtime->private_data; | 190 | struct s3c24xx_runtime_data *prtd = substream->runtime->private_data; |
198 | 191 | ||
199 | DBG("Entered %s\n", __func__); | 192 | pr_debug("Entered %s\n", __func__); |
200 | 193 | ||
201 | /* TODO - do we need to ensure DMA flushed */ | 194 | /* TODO - do we need to ensure DMA flushed */ |
202 | snd_pcm_set_runtime_buffer(substream, NULL); | 195 | snd_pcm_set_runtime_buffer(substream, NULL); |
@@ -214,7 +207,7 @@ static int s3c24xx_pcm_prepare(struct snd_pcm_substream *substream) | |||
214 | struct s3c24xx_runtime_data *prtd = substream->runtime->private_data; | 207 | struct s3c24xx_runtime_data *prtd = substream->runtime->private_data; |
215 | int ret = 0; | 208 | int ret = 0; |
216 | 209 | ||
217 | DBG("Entered %s\n", __func__); | 210 | pr_debug("Entered %s\n", __func__); |
218 | 211 | ||
219 | /* return if this is a bufferless transfer e.g. | 212 | /* return if this is a bufferless transfer e.g. |
220 | * codec <--> BT codec or GSM modem -- lg FIXME */ | 213 | * codec <--> BT codec or GSM modem -- lg FIXME */ |
@@ -259,7 +252,7 @@ static int s3c24xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
259 | struct s3c24xx_runtime_data *prtd = substream->runtime->private_data; | 252 | struct s3c24xx_runtime_data *prtd = substream->runtime->private_data; |
260 | int ret = 0; | 253 | int ret = 0; |
261 | 254 | ||
262 | DBG("Entered %s\n", __func__); | 255 | pr_debug("Entered %s\n", __func__); |
263 | 256 | ||
264 | spin_lock(&prtd->lock); | 257 | spin_lock(&prtd->lock); |
265 | 258 | ||
@@ -297,7 +290,7 @@ s3c24xx_pcm_pointer(struct snd_pcm_substream *substream) | |||
297 | unsigned long res; | 290 | unsigned long res; |
298 | dma_addr_t src, dst; | 291 | dma_addr_t src, dst; |
299 | 292 | ||
300 | DBG("Entered %s\n", __func__); | 293 | pr_debug("Entered %s\n", __func__); |
301 | 294 | ||
302 | spin_lock(&prtd->lock); | 295 | spin_lock(&prtd->lock); |
303 | s3c2410_dma_getposition(prtd->params->channel, &src, &dst); | 296 | s3c2410_dma_getposition(prtd->params->channel, &src, &dst); |
@@ -309,7 +302,7 @@ s3c24xx_pcm_pointer(struct snd_pcm_substream *substream) | |||
309 | 302 | ||
310 | spin_unlock(&prtd->lock); | 303 | spin_unlock(&prtd->lock); |
311 | 304 | ||
312 | DBG("Pointer %x %x\n", src, dst); | 305 | pr_debug("Pointer %x %x\n", src, dst); |
313 | 306 | ||
314 | /* we seem to be getting the odd error from the pcm library due | 307 | /* we seem to be getting the odd error from the pcm library due |
315 | * to out-of-bounds pointers. this is maybe due to the dma engine | 308 | * to out-of-bounds pointers. this is maybe due to the dma engine |
@@ -330,7 +323,7 @@ static int s3c24xx_pcm_open(struct snd_pcm_substream *substream) | |||
330 | struct snd_pcm_runtime *runtime = substream->runtime; | 323 | struct snd_pcm_runtime *runtime = substream->runtime; |
331 | struct s3c24xx_runtime_data *prtd; | 324 | struct s3c24xx_runtime_data *prtd; |
332 | 325 | ||
333 | DBG("Entered %s\n", __func__); | 326 | pr_debug("Entered %s\n", __func__); |
334 | 327 | ||
335 | snd_soc_set_runtime_hwparams(substream, &s3c24xx_pcm_hardware); | 328 | snd_soc_set_runtime_hwparams(substream, &s3c24xx_pcm_hardware); |
336 | 329 | ||
@@ -349,10 +342,10 @@ static int s3c24xx_pcm_close(struct snd_pcm_substream *substream) | |||
349 | struct snd_pcm_runtime *runtime = substream->runtime; | 342 | struct snd_pcm_runtime *runtime = substream->runtime; |
350 | struct s3c24xx_runtime_data *prtd = runtime->private_data; | 343 | struct s3c24xx_runtime_data *prtd = runtime->private_data; |
351 | 344 | ||
352 | DBG("Entered %s\n", __func__); | 345 | pr_debug("Entered %s\n", __func__); |
353 | 346 | ||
354 | if (!prtd) | 347 | if (!prtd) |
355 | DBG("s3c24xx_pcm_close called with prtd == NULL\n"); | 348 | pr_debug("s3c24xx_pcm_close called with prtd == NULL\n"); |
356 | 349 | ||
357 | kfree(prtd); | 350 | kfree(prtd); |
358 | 351 | ||
@@ -364,7 +357,7 @@ static int s3c24xx_pcm_mmap(struct snd_pcm_substream *substream, | |||
364 | { | 357 | { |
365 | struct snd_pcm_runtime *runtime = substream->runtime; | 358 | struct snd_pcm_runtime *runtime = substream->runtime; |
366 | 359 | ||
367 | DBG("Entered %s\n", __func__); | 360 | pr_debug("Entered %s\n", __func__); |
368 | 361 | ||
369 | return dma_mmap_writecombine(substream->pcm->card->dev, vma, | 362 | return dma_mmap_writecombine(substream->pcm->card->dev, vma, |
370 | runtime->dma_area, | 363 | runtime->dma_area, |
@@ -390,7 +383,7 @@ static int s3c24xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) | |||
390 | struct snd_dma_buffer *buf = &substream->dma_buffer; | 383 | struct snd_dma_buffer *buf = &substream->dma_buffer; |
391 | size_t size = s3c24xx_pcm_hardware.buffer_bytes_max; | 384 | size_t size = s3c24xx_pcm_hardware.buffer_bytes_max; |
392 | 385 | ||
393 | DBG("Entered %s\n", __func__); | 386 | pr_debug("Entered %s\n", __func__); |
394 | 387 | ||
395 | buf->dev.type = SNDRV_DMA_TYPE_DEV; | 388 | buf->dev.type = SNDRV_DMA_TYPE_DEV; |
396 | buf->dev.dev = pcm->card->dev; | 389 | buf->dev.dev = pcm->card->dev; |
@@ -409,7 +402,7 @@ static void s3c24xx_pcm_free_dma_buffers(struct snd_pcm *pcm) | |||
409 | struct snd_dma_buffer *buf; | 402 | struct snd_dma_buffer *buf; |
410 | int stream; | 403 | int stream; |
411 | 404 | ||
412 | DBG("Entered %s\n", __func__); | 405 | pr_debug("Entered %s\n", __func__); |
413 | 406 | ||
414 | for (stream = 0; stream < 2; stream++) { | 407 | for (stream = 0; stream < 2; stream++) { |
415 | substream = pcm->streams[stream].substream; | 408 | substream = pcm->streams[stream].substream; |
@@ -433,7 +426,7 @@ static int s3c24xx_pcm_new(struct snd_card *card, | |||
433 | { | 426 | { |
434 | int ret = 0; | 427 | int ret = 0; |
435 | 428 | ||
436 | DBG("Entered %s\n", __func__); | 429 | pr_debug("Entered %s\n", __func__); |
437 | 430 | ||
438 | if (!card->dev->dma_mask) | 431 | if (!card->dev->dma_mask) |
439 | card->dev->dma_mask = &s3c24xx_pcm_dmamask; | 432 | card->dev->dma_mask = &s3c24xx_pcm_dmamask; |
diff --git a/sound/soc/s3c24xx/s3c24xx_uda134x.c b/sound/soc/s3c24xx/s3c24xx_uda134x.c index a0a4d1832a14..8e79a416db57 100644 --- a/sound/soc/s3c24xx/s3c24xx_uda134x.c +++ b/sound/soc/s3c24xx/s3c24xx_uda134x.c | |||
@@ -22,7 +22,7 @@ | |||
22 | #include <sound/s3c24xx_uda134x.h> | 22 | #include <sound/s3c24xx_uda134x.h> |
23 | #include <sound/uda134x.h> | 23 | #include <sound/uda134x.h> |
24 | 24 | ||
25 | #include <asm/plat-s3c24xx/regs-iis.h> | 25 | #include <plat/regs-iis.h> |
26 | 26 | ||
27 | #include "s3c24xx-pcm.h" | 27 | #include "s3c24xx-pcm.h" |
28 | #include "s3c24xx-i2s.h" | 28 | #include "s3c24xx-i2s.h" |
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.c b/sound/soc/s3c24xx/s3c64xx-i2s.c new file mode 100644 index 000000000000..33c5de7e255f --- /dev/null +++ b/sound/soc/s3c24xx/s3c64xx-i2s.c | |||
@@ -0,0 +1,222 @@ | |||
1 | /* sound/soc/s3c24xx/s3c64xx-i2s.c | ||
2 | * | ||
3 | * ALSA SoC Audio Layer - S3C64XX I2S driver | ||
4 | * | ||
5 | * Copyright 2008 Openmoko, Inc. | ||
6 | * Copyright 2008 Simtec Electronics | ||
7 | * Ben Dooks <ben@simtec.co.uk> | ||
8 | * http://armlinux.simtec.co.uk/ | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #include <linux/init.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/device.h> | ||
18 | #include <linux/delay.h> | ||
19 | #include <linux/clk.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/gpio.h> | ||
22 | #include <linux/io.h> | ||
23 | |||
24 | #include <sound/core.h> | ||
25 | #include <sound/pcm.h> | ||
26 | #include <sound/pcm_params.h> | ||
27 | #include <sound/initval.h> | ||
28 | #include <sound/soc.h> | ||
29 | |||
30 | #include <plat/regs-s3c2412-iis.h> | ||
31 | #include <plat/gpio-bank-d.h> | ||
32 | #include <plat/gpio-bank-e.h> | ||
33 | #include <plat/gpio-cfg.h> | ||
34 | #include <plat/audio.h> | ||
35 | |||
36 | #include <mach/map.h> | ||
37 | #include <mach/dma.h> | ||
38 | |||
39 | #include "s3c24xx-pcm.h" | ||
40 | #include "s3c64xx-i2s.h" | ||
41 | |||
42 | static struct s3c2410_dma_client s3c64xx_dma_client_out = { | ||
43 | .name = "I2S PCM Stereo out" | ||
44 | }; | ||
45 | |||
46 | static struct s3c2410_dma_client s3c64xx_dma_client_in = { | ||
47 | .name = "I2S PCM Stereo in" | ||
48 | }; | ||
49 | |||
50 | static struct s3c24xx_pcm_dma_params s3c64xx_i2s_pcm_stereo_out[2] = { | ||
51 | [0] = { | ||
52 | .channel = DMACH_I2S0_OUT, | ||
53 | .client = &s3c64xx_dma_client_out, | ||
54 | .dma_addr = S3C64XX_PA_IIS0 + S3C2412_IISTXD, | ||
55 | .dma_size = 4, | ||
56 | }, | ||
57 | [1] = { | ||
58 | .channel = DMACH_I2S1_OUT, | ||
59 | .client = &s3c64xx_dma_client_out, | ||
60 | .dma_addr = S3C64XX_PA_IIS1 + S3C2412_IISTXD, | ||
61 | .dma_size = 4, | ||
62 | }, | ||
63 | }; | ||
64 | |||
65 | static struct s3c24xx_pcm_dma_params s3c64xx_i2s_pcm_stereo_in[2] = { | ||
66 | [0] = { | ||
67 | .channel = DMACH_I2S0_IN, | ||
68 | .client = &s3c64xx_dma_client_in, | ||
69 | .dma_addr = S3C64XX_PA_IIS0 + S3C2412_IISRXD, | ||
70 | .dma_size = 4, | ||
71 | }, | ||
72 | [1] = { | ||
73 | .channel = DMACH_I2S1_IN, | ||
74 | .client = &s3c64xx_dma_client_in, | ||
75 | .dma_addr = S3C64XX_PA_IIS1 + S3C2412_IISRXD, | ||
76 | .dma_size = 4, | ||
77 | }, | ||
78 | }; | ||
79 | |||
80 | static struct s3c_i2sv2_info s3c64xx_i2s[2]; | ||
81 | |||
82 | static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai) | ||
83 | { | ||
84 | return cpu_dai->private_data; | ||
85 | } | ||
86 | |||
87 | static int s3c64xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, | ||
88 | int clk_id, unsigned int freq, int dir) | ||
89 | { | ||
90 | struct s3c_i2sv2_info *i2s = to_info(cpu_dai); | ||
91 | u32 iismod = readl(i2s->regs + S3C2412_IISMOD); | ||
92 | |||
93 | switch (clk_id) { | ||
94 | case S3C64XX_CLKSRC_PCLK: | ||
95 | iismod &= ~S3C64XX_IISMOD_IMS_SYSMUX; | ||
96 | break; | ||
97 | |||
98 | case S3C64XX_CLKSRC_MUX: | ||
99 | iismod |= S3C64XX_IISMOD_IMS_SYSMUX; | ||
100 | break; | ||
101 | |||
102 | default: | ||
103 | return -EINVAL; | ||
104 | } | ||
105 | |||
106 | writel(iismod, i2s->regs + S3C2412_IISMOD); | ||
107 | |||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | |||
112 | unsigned long s3c64xx_i2s_get_clockrate(struct snd_soc_dai *dai) | ||
113 | { | ||
114 | struct s3c_i2sv2_info *i2s = to_info(dai); | ||
115 | |||
116 | return clk_get_rate(i2s->iis_cclk); | ||
117 | } | ||
118 | EXPORT_SYMBOL_GPL(s3c64xx_i2s_get_clockrate); | ||
119 | |||
120 | static int s3c64xx_i2s_probe(struct platform_device *pdev, | ||
121 | struct snd_soc_dai *dai) | ||
122 | { | ||
123 | struct device *dev = &pdev->dev; | ||
124 | struct s3c_i2sv2_info *i2s; | ||
125 | int ret; | ||
126 | |||
127 | dev_dbg(dev, "%s: probing dai %d\n", __func__, pdev->id); | ||
128 | |||
129 | if (pdev->id < 0 || pdev->id > ARRAY_SIZE(s3c64xx_i2s)) { | ||
130 | dev_err(dev, "id %d out of range\n", pdev->id); | ||
131 | return -EINVAL; | ||
132 | } | ||
133 | |||
134 | i2s = &s3c64xx_i2s[pdev->id]; | ||
135 | |||
136 | ret = s3c_i2sv2_probe(pdev, dai, i2s, | ||
137 | pdev->id ? S3C64XX_PA_IIS1 : S3C64XX_PA_IIS0); | ||
138 | if (ret) | ||
139 | return ret; | ||
140 | |||
141 | i2s->dma_capture = &s3c64xx_i2s_pcm_stereo_in[pdev->id]; | ||
142 | i2s->dma_playback = &s3c64xx_i2s_pcm_stereo_out[pdev->id]; | ||
143 | |||
144 | i2s->iis_cclk = clk_get(dev, "audio-bus"); | ||
145 | if (IS_ERR(i2s->iis_cclk)) { | ||
146 | dev_err(dev, "failed to get audio-bus"); | ||
147 | iounmap(i2s->regs); | ||
148 | return -ENODEV; | ||
149 | } | ||
150 | |||
151 | /* configure GPIO for i2s port */ | ||
152 | switch (pdev->id) { | ||
153 | case 0: | ||
154 | s3c_gpio_cfgpin(S3C64XX_GPD(0), S3C64XX_GPD0_I2S0_CLK); | ||
155 | s3c_gpio_cfgpin(S3C64XX_GPD(1), S3C64XX_GPD1_I2S0_CDCLK); | ||
156 | s3c_gpio_cfgpin(S3C64XX_GPD(2), S3C64XX_GPD2_I2S0_LRCLK); | ||
157 | s3c_gpio_cfgpin(S3C64XX_GPD(3), S3C64XX_GPD3_I2S0_DI); | ||
158 | s3c_gpio_cfgpin(S3C64XX_GPD(4), S3C64XX_GPD4_I2S0_D0); | ||
159 | break; | ||
160 | case 1: | ||
161 | s3c_gpio_cfgpin(S3C64XX_GPE(0), S3C64XX_GPE0_I2S1_CLK); | ||
162 | s3c_gpio_cfgpin(S3C64XX_GPE(1), S3C64XX_GPE1_I2S1_CDCLK); | ||
163 | s3c_gpio_cfgpin(S3C64XX_GPE(2), S3C64XX_GPE2_I2S1_LRCLK); | ||
164 | s3c_gpio_cfgpin(S3C64XX_GPE(3), S3C64XX_GPE3_I2S1_DI); | ||
165 | s3c_gpio_cfgpin(S3C64XX_GPE(4), S3C64XX_GPE4_I2S1_D0); | ||
166 | } | ||
167 | |||
168 | return 0; | ||
169 | } | ||
170 | |||
171 | |||
172 | #define S3C64XX_I2S_RATES \ | ||
173 | (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \ | ||
174 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ | ||
175 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) | ||
176 | |||
177 | #define S3C64XX_I2S_FMTS \ | ||
178 | (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE) | ||
179 | |||
180 | static struct snd_soc_dai_ops s3c64xx_i2s_dai_ops = { | ||
181 | .set_sysclk = s3c64xx_i2s_set_sysclk, | ||
182 | }; | ||
183 | |||
184 | struct snd_soc_dai s3c64xx_i2s_dai = { | ||
185 | .name = "s3c64xx-i2s", | ||
186 | .id = 0, | ||
187 | .probe = s3c64xx_i2s_probe, | ||
188 | .playback = { | ||
189 | .channels_min = 2, | ||
190 | .channels_max = 2, | ||
191 | .rates = S3C64XX_I2S_RATES, | ||
192 | .formats = S3C64XX_I2S_FMTS, | ||
193 | }, | ||
194 | .capture = { | ||
195 | .channels_min = 2, | ||
196 | .channels_max = 2, | ||
197 | .rates = S3C64XX_I2S_RATES, | ||
198 | .formats = S3C64XX_I2S_FMTS, | ||
199 | }, | ||
200 | .ops = &s3c64xx_i2s_dai_ops, | ||
201 | }; | ||
202 | EXPORT_SYMBOL_GPL(s3c64xx_i2s_dai); | ||
203 | |||
204 | static int __init s3c64xx_i2s_init(void) | ||
205 | { | ||
206 | return s3c_i2sv2_register_dai(&s3c64xx_i2s_dai); | ||
207 | } | ||
208 | module_init(s3c64xx_i2s_init); | ||
209 | |||
210 | static void __exit s3c64xx_i2s_exit(void) | ||
211 | { | ||
212 | snd_soc_unregister_dai(&s3c64xx_i2s_dai); | ||
213 | } | ||
214 | module_exit(s3c64xx_i2s_exit); | ||
215 | |||
216 | /* Module information */ | ||
217 | MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); | ||
218 | MODULE_DESCRIPTION("S3C64XX I2S SoC Interface"); | ||
219 | MODULE_LICENSE("GPL"); | ||
220 | |||
221 | |||
222 | |||
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.h b/sound/soc/s3c24xx/s3c64xx-i2s.h new file mode 100644 index 000000000000..b7ffe3c38b66 --- /dev/null +++ b/sound/soc/s3c24xx/s3c64xx-i2s.h | |||
@@ -0,0 +1,31 @@ | |||
1 | /* sound/soc/s3c24xx/s3c64xx-i2s.h | ||
2 | * | ||
3 | * ALSA SoC Audio Layer - S3C64XX I2S driver | ||
4 | * | ||
5 | * Copyright 2008 Openmoko, Inc. | ||
6 | * Copyright 2008 Simtec Electronics | ||
7 | * Ben Dooks <ben@simtec.co.uk> | ||
8 | * http://armlinux.simtec.co.uk/ | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #ifndef __SND_SOC_S3C24XX_S3C64XX_I2S_H | ||
16 | #define __SND_SOC_S3C24XX_S3C64XX_I2S_H __FILE__ | ||
17 | |||
18 | #include "s3c-i2s-v2.h" | ||
19 | |||
20 | #define S3C64XX_DIV_BCLK S3C_I2SV2_DIV_BCLK | ||
21 | #define S3C64XX_DIV_RCLK S3C_I2SV2_DIV_RCLK | ||
22 | #define S3C64XX_DIV_PRESCALER S3C_I2SV2_DIV_PRESCALER | ||
23 | |||
24 | #define S3C64XX_CLKSRC_PCLK (0) | ||
25 | #define S3C64XX_CLKSRC_MUX (1) | ||
26 | |||
27 | extern struct snd_soc_dai s3c64xx_i2s_dai; | ||
28 | |||
29 | extern unsigned long s3c64xx_i2s_get_clockrate(struct snd_soc_dai *cpu_dai); | ||
30 | |||
31 | #endif /* __SND_SOC_S3C24XX_S3C64XX_I2S_H */ | ||
diff --git a/sound/soc/sh/hac.c b/sound/soc/sh/hac.c index eab31838badf..41db75af3c69 100644 --- a/sound/soc/sh/hac.c +++ b/sound/soc/sh/hac.c | |||
@@ -267,6 +267,10 @@ static int hac_hw_params(struct snd_pcm_substream *substream, | |||
267 | #define AC97_FMTS \ | 267 | #define AC97_FMTS \ |
268 | SNDRV_PCM_FMTBIT_S16_LE | 268 | SNDRV_PCM_FMTBIT_S16_LE |
269 | 269 | ||
270 | static struct snd_soc_dai_ops hac_dai_ops = { | ||
271 | .hw_params = hac_hw_params, | ||
272 | }; | ||
273 | |||
270 | struct snd_soc_dai sh4_hac_dai[] = { | 274 | struct snd_soc_dai sh4_hac_dai[] = { |
271 | { | 275 | { |
272 | .name = "HAC0", | 276 | .name = "HAC0", |
@@ -284,9 +288,7 @@ struct snd_soc_dai sh4_hac_dai[] = { | |||
284 | .channels_min = 2, | 288 | .channels_min = 2, |
285 | .channels_max = 2, | 289 | .channels_max = 2, |
286 | }, | 290 | }, |
287 | .ops = { | 291 | .ops = &hac_dai_ops, |
288 | .hw_params = hac_hw_params, | ||
289 | }, | ||
290 | }, | 292 | }, |
291 | #ifdef CONFIG_CPU_SUBTYPE_SH7760 | 293 | #ifdef CONFIG_CPU_SUBTYPE_SH7760 |
292 | { | 294 | { |
@@ -305,9 +307,7 @@ struct snd_soc_dai sh4_hac_dai[] = { | |||
305 | .channels_min = 2, | 307 | .channels_min = 2, |
306 | .channels_max = 2, | 308 | .channels_max = 2, |
307 | }, | 309 | }, |
308 | .ops = { | 310 | .ops = &hac_dai_ops, |
309 | .hw_params = hac_hw_params, | ||
310 | }, | ||
311 | 311 | ||
312 | }, | 312 | }, |
313 | #endif | 313 | #endif |
diff --git a/sound/soc/sh/ssi.c b/sound/soc/sh/ssi.c index d1e5390fddeb..56fa0872abbb 100644 --- a/sound/soc/sh/ssi.c +++ b/sound/soc/sh/ssi.c | |||
@@ -336,6 +336,16 @@ static int ssi_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
336 | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_U24_3LE | \ | 336 | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_U24_3LE | \ |
337 | SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_U32_LE) | 337 | SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_U32_LE) |
338 | 338 | ||
339 | static struct snd_soc_dai_ops ssi_dai_ops = { | ||
340 | .startup = ssi_startup, | ||
341 | .shutdown = ssi_shutdown, | ||
342 | .trigger = ssi_trigger, | ||
343 | .hw_params = ssi_hw_params, | ||
344 | .set_sysclk = ssi_set_sysclk, | ||
345 | .set_clkdiv = ssi_set_clkdiv, | ||
346 | .set_fmt = ssi_set_fmt, | ||
347 | }; | ||
348 | |||
339 | struct snd_soc_dai sh4_ssi_dai[] = { | 349 | struct snd_soc_dai sh4_ssi_dai[] = { |
340 | { | 350 | { |
341 | .name = "SSI0", | 351 | .name = "SSI0", |
@@ -352,15 +362,7 @@ struct snd_soc_dai sh4_ssi_dai[] = { | |||
352 | .channels_min = 2, | 362 | .channels_min = 2, |
353 | .channels_max = 8, | 363 | .channels_max = 8, |
354 | }, | 364 | }, |
355 | .ops = { | 365 | .ops = &ssi_dai_ops, |
356 | .startup = ssi_startup, | ||
357 | .shutdown = ssi_shutdown, | ||
358 | .trigger = ssi_trigger, | ||
359 | .hw_params = ssi_hw_params, | ||
360 | .set_sysclk = ssi_set_sysclk, | ||
361 | .set_clkdiv = ssi_set_clkdiv, | ||
362 | .set_fmt = ssi_set_fmt, | ||
363 | }, | ||
364 | }, | 366 | }, |
365 | #ifdef CONFIG_CPU_SUBTYPE_SH7760 | 367 | #ifdef CONFIG_CPU_SUBTYPE_SH7760 |
366 | { | 368 | { |
@@ -378,15 +380,7 @@ struct snd_soc_dai sh4_ssi_dai[] = { | |||
378 | .channels_min = 2, | 380 | .channels_min = 2, |
379 | .channels_max = 8, | 381 | .channels_max = 8, |
380 | }, | 382 | }, |
381 | .ops = { | 383 | .ops = &ssi_dai_ops, |
382 | .startup = ssi_startup, | ||
383 | .shutdown = ssi_shutdown, | ||
384 | .trigger = ssi_trigger, | ||
385 | .hw_params = ssi_hw_params, | ||
386 | .set_sysclk = ssi_set_sysclk, | ||
387 | .set_clkdiv = ssi_set_clkdiv, | ||
388 | .set_fmt = ssi_set_fmt, | ||
389 | }, | ||
390 | }, | 384 | }, |
391 | #endif | 385 | #endif |
392 | }; | 386 | }; |
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index ec3f8bb4b51d..6e710f705a74 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -133,8 +133,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
133 | mutex_lock(&pcm_mutex); | 133 | mutex_lock(&pcm_mutex); |
134 | 134 | ||
135 | /* startup the audio subsystem */ | 135 | /* startup the audio subsystem */ |
136 | if (cpu_dai->ops.startup) { | 136 | if (cpu_dai->ops->startup) { |
137 | ret = cpu_dai->ops.startup(substream, cpu_dai); | 137 | ret = cpu_dai->ops->startup(substream, cpu_dai); |
138 | if (ret < 0) { | 138 | if (ret < 0) { |
139 | printk(KERN_ERR "asoc: can't open interface %s\n", | 139 | printk(KERN_ERR "asoc: can't open interface %s\n", |
140 | cpu_dai->name); | 140 | cpu_dai->name); |
@@ -150,8 +150,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
150 | } | 150 | } |
151 | } | 151 | } |
152 | 152 | ||
153 | if (codec_dai->ops.startup) { | 153 | if (codec_dai->ops->startup) { |
154 | ret = codec_dai->ops.startup(substream, codec_dai); | 154 | ret = codec_dai->ops->startup(substream, codec_dai); |
155 | if (ret < 0) { | 155 | if (ret < 0) { |
156 | printk(KERN_ERR "asoc: can't open codec %s\n", | 156 | printk(KERN_ERR "asoc: can't open codec %s\n", |
157 | codec_dai->name); | 157 | codec_dai->name); |
@@ -234,7 +234,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
234 | cpu_dai->capture.active = codec_dai->capture.active = 1; | 234 | cpu_dai->capture.active = codec_dai->capture.active = 1; |
235 | cpu_dai->active = codec_dai->active = 1; | 235 | cpu_dai->active = codec_dai->active = 1; |
236 | cpu_dai->runtime = runtime; | 236 | cpu_dai->runtime = runtime; |
237 | socdev->codec->active++; | 237 | card->codec->active++; |
238 | mutex_unlock(&pcm_mutex); | 238 | mutex_unlock(&pcm_mutex); |
239 | return 0; | 239 | return 0; |
240 | 240 | ||
@@ -247,8 +247,8 @@ codec_dai_err: | |||
247 | platform->pcm_ops->close(substream); | 247 | platform->pcm_ops->close(substream); |
248 | 248 | ||
249 | platform_err: | 249 | platform_err: |
250 | if (cpu_dai->ops.shutdown) | 250 | if (cpu_dai->ops->shutdown) |
251 | cpu_dai->ops.shutdown(substream, cpu_dai); | 251 | cpu_dai->ops->shutdown(substream, cpu_dai); |
252 | out: | 252 | out: |
253 | mutex_unlock(&pcm_mutex); | 253 | mutex_unlock(&pcm_mutex); |
254 | return ret; | 254 | return ret; |
@@ -264,7 +264,7 @@ static void close_delayed_work(struct work_struct *work) | |||
264 | struct snd_soc_card *card = container_of(work, struct snd_soc_card, | 264 | struct snd_soc_card *card = container_of(work, struct snd_soc_card, |
265 | delayed_work.work); | 265 | delayed_work.work); |
266 | struct snd_soc_device *socdev = card->socdev; | 266 | struct snd_soc_device *socdev = card->socdev; |
267 | struct snd_soc_codec *codec = socdev->codec; | 267 | struct snd_soc_codec *codec = card->codec; |
268 | struct snd_soc_dai *codec_dai; | 268 | struct snd_soc_dai *codec_dai; |
269 | int i; | 269 | int i; |
270 | 270 | ||
@@ -319,7 +319,7 @@ static int soc_codec_close(struct snd_pcm_substream *substream) | |||
319 | struct snd_soc_platform *platform = card->platform; | 319 | struct snd_soc_platform *platform = card->platform; |
320 | struct snd_soc_dai *cpu_dai = machine->cpu_dai; | 320 | struct snd_soc_dai *cpu_dai = machine->cpu_dai; |
321 | struct snd_soc_dai *codec_dai = machine->codec_dai; | 321 | struct snd_soc_dai *codec_dai = machine->codec_dai; |
322 | struct snd_soc_codec *codec = socdev->codec; | 322 | struct snd_soc_codec *codec = card->codec; |
323 | 323 | ||
324 | mutex_lock(&pcm_mutex); | 324 | mutex_lock(&pcm_mutex); |
325 | 325 | ||
@@ -340,11 +340,11 @@ static int soc_codec_close(struct snd_pcm_substream *substream) | |||
340 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 340 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
341 | snd_soc_dai_digital_mute(codec_dai, 1); | 341 | snd_soc_dai_digital_mute(codec_dai, 1); |
342 | 342 | ||
343 | if (cpu_dai->ops.shutdown) | 343 | if (cpu_dai->ops->shutdown) |
344 | cpu_dai->ops.shutdown(substream, cpu_dai); | 344 | cpu_dai->ops->shutdown(substream, cpu_dai); |
345 | 345 | ||
346 | if (codec_dai->ops.shutdown) | 346 | if (codec_dai->ops->shutdown) |
347 | codec_dai->ops.shutdown(substream, codec_dai); | 347 | codec_dai->ops->shutdown(substream, codec_dai); |
348 | 348 | ||
349 | if (machine->ops && machine->ops->shutdown) | 349 | if (machine->ops && machine->ops->shutdown) |
350 | machine->ops->shutdown(substream); | 350 | machine->ops->shutdown(substream); |
@@ -387,7 +387,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) | |||
387 | struct snd_soc_platform *platform = card->platform; | 387 | struct snd_soc_platform *platform = card->platform; |
388 | struct snd_soc_dai *cpu_dai = machine->cpu_dai; | 388 | struct snd_soc_dai *cpu_dai = machine->cpu_dai; |
389 | struct snd_soc_dai *codec_dai = machine->codec_dai; | 389 | struct snd_soc_dai *codec_dai = machine->codec_dai; |
390 | struct snd_soc_codec *codec = socdev->codec; | 390 | struct snd_soc_codec *codec = card->codec; |
391 | int ret = 0; | 391 | int ret = 0; |
392 | 392 | ||
393 | mutex_lock(&pcm_mutex); | 393 | mutex_lock(&pcm_mutex); |
@@ -408,16 +408,16 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) | |||
408 | } | 408 | } |
409 | } | 409 | } |
410 | 410 | ||
411 | if (codec_dai->ops.prepare) { | 411 | if (codec_dai->ops->prepare) { |
412 | ret = codec_dai->ops.prepare(substream, codec_dai); | 412 | ret = codec_dai->ops->prepare(substream, codec_dai); |
413 | if (ret < 0) { | 413 | if (ret < 0) { |
414 | printk(KERN_ERR "asoc: codec DAI prepare error\n"); | 414 | printk(KERN_ERR "asoc: codec DAI prepare error\n"); |
415 | goto out; | 415 | goto out; |
416 | } | 416 | } |
417 | } | 417 | } |
418 | 418 | ||
419 | if (cpu_dai->ops.prepare) { | 419 | if (cpu_dai->ops->prepare) { |
420 | ret = cpu_dai->ops.prepare(substream, cpu_dai); | 420 | ret = cpu_dai->ops->prepare(substream, cpu_dai); |
421 | if (ret < 0) { | 421 | if (ret < 0) { |
422 | printk(KERN_ERR "asoc: cpu DAI prepare error\n"); | 422 | printk(KERN_ERR "asoc: cpu DAI prepare error\n"); |
423 | goto out; | 423 | goto out; |
@@ -494,8 +494,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, | |||
494 | } | 494 | } |
495 | } | 495 | } |
496 | 496 | ||
497 | if (codec_dai->ops.hw_params) { | 497 | if (codec_dai->ops->hw_params) { |
498 | ret = codec_dai->ops.hw_params(substream, params, codec_dai); | 498 | ret = codec_dai->ops->hw_params(substream, params, codec_dai); |
499 | if (ret < 0) { | 499 | if (ret < 0) { |
500 | printk(KERN_ERR "asoc: can't set codec %s hw params\n", | 500 | printk(KERN_ERR "asoc: can't set codec %s hw params\n", |
501 | codec_dai->name); | 501 | codec_dai->name); |
@@ -503,8 +503,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, | |||
503 | } | 503 | } |
504 | } | 504 | } |
505 | 505 | ||
506 | if (cpu_dai->ops.hw_params) { | 506 | if (cpu_dai->ops->hw_params) { |
507 | ret = cpu_dai->ops.hw_params(substream, params, cpu_dai); | 507 | ret = cpu_dai->ops->hw_params(substream, params, cpu_dai); |
508 | if (ret < 0) { | 508 | if (ret < 0) { |
509 | printk(KERN_ERR "asoc: interface %s hw params failed\n", | 509 | printk(KERN_ERR "asoc: interface %s hw params failed\n", |
510 | cpu_dai->name); | 510 | cpu_dai->name); |
@@ -526,12 +526,12 @@ out: | |||
526 | return ret; | 526 | return ret; |
527 | 527 | ||
528 | platform_err: | 528 | platform_err: |
529 | if (cpu_dai->ops.hw_free) | 529 | if (cpu_dai->ops->hw_free) |
530 | cpu_dai->ops.hw_free(substream, cpu_dai); | 530 | cpu_dai->ops->hw_free(substream, cpu_dai); |
531 | 531 | ||
532 | interface_err: | 532 | interface_err: |
533 | if (codec_dai->ops.hw_free) | 533 | if (codec_dai->ops->hw_free) |
534 | codec_dai->ops.hw_free(substream, codec_dai); | 534 | codec_dai->ops->hw_free(substream, codec_dai); |
535 | 535 | ||
536 | codec_err: | 536 | codec_err: |
537 | if (machine->ops && machine->ops->hw_free) | 537 | if (machine->ops && machine->ops->hw_free) |
@@ -553,7 +553,7 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) | |||
553 | struct snd_soc_platform *platform = card->platform; | 553 | struct snd_soc_platform *platform = card->platform; |
554 | struct snd_soc_dai *cpu_dai = machine->cpu_dai; | 554 | struct snd_soc_dai *cpu_dai = machine->cpu_dai; |
555 | struct snd_soc_dai *codec_dai = machine->codec_dai; | 555 | struct snd_soc_dai *codec_dai = machine->codec_dai; |
556 | struct snd_soc_codec *codec = socdev->codec; | 556 | struct snd_soc_codec *codec = card->codec; |
557 | 557 | ||
558 | mutex_lock(&pcm_mutex); | 558 | mutex_lock(&pcm_mutex); |
559 | 559 | ||
@@ -570,11 +570,11 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) | |||
570 | platform->pcm_ops->hw_free(substream); | 570 | platform->pcm_ops->hw_free(substream); |
571 | 571 | ||
572 | /* now free hw params for the DAI's */ | 572 | /* now free hw params for the DAI's */ |
573 | if (codec_dai->ops.hw_free) | 573 | if (codec_dai->ops->hw_free) |
574 | codec_dai->ops.hw_free(substream, codec_dai); | 574 | codec_dai->ops->hw_free(substream, codec_dai); |
575 | 575 | ||
576 | if (cpu_dai->ops.hw_free) | 576 | if (cpu_dai->ops->hw_free) |
577 | cpu_dai->ops.hw_free(substream, cpu_dai); | 577 | cpu_dai->ops->hw_free(substream, cpu_dai); |
578 | 578 | ||
579 | mutex_unlock(&pcm_mutex); | 579 | mutex_unlock(&pcm_mutex); |
580 | return 0; | 580 | return 0; |
@@ -591,8 +591,8 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
591 | struct snd_soc_dai *codec_dai = machine->codec_dai; | 591 | struct snd_soc_dai *codec_dai = machine->codec_dai; |
592 | int ret; | 592 | int ret; |
593 | 593 | ||
594 | if (codec_dai->ops.trigger) { | 594 | if (codec_dai->ops->trigger) { |
595 | ret = codec_dai->ops.trigger(substream, cmd, codec_dai); | 595 | ret = codec_dai->ops->trigger(substream, cmd, codec_dai); |
596 | if (ret < 0) | 596 | if (ret < 0) |
597 | return ret; | 597 | return ret; |
598 | } | 598 | } |
@@ -603,8 +603,8 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
603 | return ret; | 603 | return ret; |
604 | } | 604 | } |
605 | 605 | ||
606 | if (cpu_dai->ops.trigger) { | 606 | if (cpu_dai->ops->trigger) { |
607 | ret = cpu_dai->ops.trigger(substream, cmd, cpu_dai); | 607 | ret = cpu_dai->ops->trigger(substream, cmd, cpu_dai); |
608 | if (ret < 0) | 608 | if (ret < 0) |
609 | return ret; | 609 | return ret; |
610 | } | 610 | } |
@@ -629,7 +629,7 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state) | |||
629 | struct snd_soc_card *card = socdev->card; | 629 | struct snd_soc_card *card = socdev->card; |
630 | struct snd_soc_platform *platform = card->platform; | 630 | struct snd_soc_platform *platform = card->platform; |
631 | struct snd_soc_codec_device *codec_dev = socdev->codec_dev; | 631 | struct snd_soc_codec_device *codec_dev = socdev->codec_dev; |
632 | struct snd_soc_codec *codec = socdev->codec; | 632 | struct snd_soc_codec *codec = card->codec; |
633 | int i; | 633 | int i; |
634 | 634 | ||
635 | /* Due to the resume being scheduled into a workqueue we could | 635 | /* Due to the resume being scheduled into a workqueue we could |
@@ -645,8 +645,8 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state) | |||
645 | /* mute any active DAC's */ | 645 | /* mute any active DAC's */ |
646 | for (i = 0; i < card->num_links; i++) { | 646 | for (i = 0; i < card->num_links; i++) { |
647 | struct snd_soc_dai *dai = card->dai_link[i].codec_dai; | 647 | struct snd_soc_dai *dai = card->dai_link[i].codec_dai; |
648 | if (dai->ops.digital_mute && dai->playback.active) | 648 | if (dai->ops->digital_mute && dai->playback.active) |
649 | dai->ops.digital_mute(dai, 1); | 649 | dai->ops->digital_mute(dai, 1); |
650 | } | 650 | } |
651 | 651 | ||
652 | /* suspend all pcms */ | 652 | /* suspend all pcms */ |
@@ -705,7 +705,7 @@ static void soc_resume_deferred(struct work_struct *work) | |||
705 | struct snd_soc_device *socdev = card->socdev; | 705 | struct snd_soc_device *socdev = card->socdev; |
706 | struct snd_soc_platform *platform = card->platform; | 706 | struct snd_soc_platform *platform = card->platform; |
707 | struct snd_soc_codec_device *codec_dev = socdev->codec_dev; | 707 | struct snd_soc_codec_device *codec_dev = socdev->codec_dev; |
708 | struct snd_soc_codec *codec = socdev->codec; | 708 | struct snd_soc_codec *codec = card->codec; |
709 | struct platform_device *pdev = to_platform_device(socdev->dev); | 709 | struct platform_device *pdev = to_platform_device(socdev->dev); |
710 | int i; | 710 | int i; |
711 | 711 | ||
@@ -741,8 +741,8 @@ static void soc_resume_deferred(struct work_struct *work) | |||
741 | /* unmute any active DACs */ | 741 | /* unmute any active DACs */ |
742 | for (i = 0; i < card->num_links; i++) { | 742 | for (i = 0; i < card->num_links; i++) { |
743 | struct snd_soc_dai *dai = card->dai_link[i].codec_dai; | 743 | struct snd_soc_dai *dai = card->dai_link[i].codec_dai; |
744 | if (dai->ops.digital_mute && dai->playback.active) | 744 | if (dai->ops->digital_mute && dai->playback.active) |
745 | dai->ops.digital_mute(dai, 0); | 745 | dai->ops->digital_mute(dai, 0); |
746 | } | 746 | } |
747 | 747 | ||
748 | for (i = 0; i < card->num_links; i++) { | 748 | for (i = 0; i < card->num_links; i++) { |
@@ -982,8 +982,8 @@ static struct platform_driver soc_driver = { | |||
982 | static int soc_new_pcm(struct snd_soc_device *socdev, | 982 | static int soc_new_pcm(struct snd_soc_device *socdev, |
983 | struct snd_soc_dai_link *dai_link, int num) | 983 | struct snd_soc_dai_link *dai_link, int num) |
984 | { | 984 | { |
985 | struct snd_soc_codec *codec = socdev->codec; | ||
986 | struct snd_soc_card *card = socdev->card; | 985 | struct snd_soc_card *card = socdev->card; |
986 | struct snd_soc_codec *codec = card->codec; | ||
987 | struct snd_soc_platform *platform = card->platform; | 987 | struct snd_soc_platform *platform = card->platform; |
988 | struct snd_soc_dai *codec_dai = dai_link->codec_dai; | 988 | struct snd_soc_dai *codec_dai = dai_link->codec_dai; |
989 | struct snd_soc_dai *cpu_dai = dai_link->cpu_dai; | 989 | struct snd_soc_dai *cpu_dai = dai_link->cpu_dai; |
@@ -998,7 +998,7 @@ static int soc_new_pcm(struct snd_soc_device *socdev, | |||
998 | 998 | ||
999 | rtd->dai = dai_link; | 999 | rtd->dai = dai_link; |
1000 | rtd->socdev = socdev; | 1000 | rtd->socdev = socdev; |
1001 | codec_dai->codec = socdev->codec; | 1001 | codec_dai->codec = card->codec; |
1002 | 1002 | ||
1003 | /* check client and interface hw capabilities */ | 1003 | /* check client and interface hw capabilities */ |
1004 | sprintf(new_name, "%s %s-%d", dai_link->stream_name, codec_dai->name, | 1004 | sprintf(new_name, "%s %s-%d", dai_link->stream_name, codec_dai->name, |
@@ -1048,9 +1048,8 @@ static int soc_new_pcm(struct snd_soc_device *socdev, | |||
1048 | } | 1048 | } |
1049 | 1049 | ||
1050 | /* codec register dump */ | 1050 | /* codec register dump */ |
1051 | static ssize_t soc_codec_reg_show(struct snd_soc_device *devdata, char *buf) | 1051 | static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf) |
1052 | { | 1052 | { |
1053 | struct snd_soc_codec *codec = devdata->codec; | ||
1054 | int i, step = 1, count = 0; | 1053 | int i, step = 1, count = 0; |
1055 | 1054 | ||
1056 | if (!codec->reg_cache_size) | 1055 | if (!codec->reg_cache_size) |
@@ -1090,7 +1089,7 @@ static ssize_t codec_reg_show(struct device *dev, | |||
1090 | struct device_attribute *attr, char *buf) | 1089 | struct device_attribute *attr, char *buf) |
1091 | { | 1090 | { |
1092 | struct snd_soc_device *devdata = dev_get_drvdata(dev); | 1091 | struct snd_soc_device *devdata = dev_get_drvdata(dev); |
1093 | return soc_codec_reg_show(devdata, buf); | 1092 | return soc_codec_reg_show(devdata->card->codec, buf); |
1094 | } | 1093 | } |
1095 | 1094 | ||
1096 | static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL); | 1095 | static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL); |
@@ -1107,12 +1106,10 @@ static ssize_t codec_reg_read_file(struct file *file, char __user *user_buf, | |||
1107 | { | 1106 | { |
1108 | ssize_t ret; | 1107 | ssize_t ret; |
1109 | struct snd_soc_codec *codec = file->private_data; | 1108 | struct snd_soc_codec *codec = file->private_data; |
1110 | struct device *card_dev = codec->card->dev; | ||
1111 | struct snd_soc_device *devdata = card_dev->driver_data; | ||
1112 | char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL); | 1109 | char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL); |
1113 | if (!buf) | 1110 | if (!buf) |
1114 | return -ENOMEM; | 1111 | return -ENOMEM; |
1115 | ret = soc_codec_reg_show(devdata, buf); | 1112 | ret = soc_codec_reg_show(codec, buf); |
1116 | if (ret >= 0) | 1113 | if (ret >= 0) |
1117 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); | 1114 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); |
1118 | kfree(buf); | 1115 | kfree(buf); |
@@ -1309,19 +1306,19 @@ EXPORT_SYMBOL_GPL(snd_soc_test_bits); | |||
1309 | */ | 1306 | */ |
1310 | int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid) | 1307 | int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid) |
1311 | { | 1308 | { |
1312 | struct snd_soc_codec *codec = socdev->codec; | ||
1313 | struct snd_soc_card *card = socdev->card; | 1309 | struct snd_soc_card *card = socdev->card; |
1314 | int ret = 0, i; | 1310 | struct snd_soc_codec *codec = card->codec; |
1311 | int ret, i; | ||
1315 | 1312 | ||
1316 | mutex_lock(&codec->mutex); | 1313 | mutex_lock(&codec->mutex); |
1317 | 1314 | ||
1318 | /* register a sound card */ | 1315 | /* register a sound card */ |
1319 | codec->card = snd_card_new(idx, xid, codec->owner, 0); | 1316 | ret = snd_card_create(idx, xid, codec->owner, 0, &codec->card); |
1320 | if (!codec->card) { | 1317 | if (ret < 0) { |
1321 | printk(KERN_ERR "asoc: can't create sound card for codec %s\n", | 1318 | printk(KERN_ERR "asoc: can't create sound card for codec %s\n", |
1322 | codec->name); | 1319 | codec->name); |
1323 | mutex_unlock(&codec->mutex); | 1320 | mutex_unlock(&codec->mutex); |
1324 | return -ENODEV; | 1321 | return ret; |
1325 | } | 1322 | } |
1326 | 1323 | ||
1327 | codec->card->dev = socdev->dev; | 1324 | codec->card->dev = socdev->dev; |
@@ -1355,8 +1352,8 @@ EXPORT_SYMBOL_GPL(snd_soc_new_pcms); | |||
1355 | */ | 1352 | */ |
1356 | int snd_soc_init_card(struct snd_soc_device *socdev) | 1353 | int snd_soc_init_card(struct snd_soc_device *socdev) |
1357 | { | 1354 | { |
1358 | struct snd_soc_codec *codec = socdev->codec; | ||
1359 | struct snd_soc_card *card = socdev->card; | 1355 | struct snd_soc_card *card = socdev->card; |
1356 | struct snd_soc_codec *codec = card->codec; | ||
1360 | int ret = 0, i, ac97 = 0, err = 0; | 1357 | int ret = 0, i, ac97 = 0, err = 0; |
1361 | 1358 | ||
1362 | for (i = 0; i < card->num_links; i++) { | 1359 | for (i = 0; i < card->num_links; i++) { |
@@ -1407,7 +1404,7 @@ int snd_soc_init_card(struct snd_soc_device *socdev) | |||
1407 | if (err < 0) | 1404 | if (err < 0) |
1408 | printk(KERN_WARNING "asoc: failed to add codec sysfs files\n"); | 1405 | printk(KERN_WARNING "asoc: failed to add codec sysfs files\n"); |
1409 | 1406 | ||
1410 | soc_init_codec_debugfs(socdev->codec); | 1407 | soc_init_codec_debugfs(codec); |
1411 | mutex_unlock(&codec->mutex); | 1408 | mutex_unlock(&codec->mutex); |
1412 | 1409 | ||
1413 | out: | 1410 | out: |
@@ -1424,18 +1421,19 @@ EXPORT_SYMBOL_GPL(snd_soc_init_card); | |||
1424 | */ | 1421 | */ |
1425 | void snd_soc_free_pcms(struct snd_soc_device *socdev) | 1422 | void snd_soc_free_pcms(struct snd_soc_device *socdev) |
1426 | { | 1423 | { |
1427 | struct snd_soc_codec *codec = socdev->codec; | 1424 | struct snd_soc_codec *codec = socdev->card->codec; |
1428 | #ifdef CONFIG_SND_SOC_AC97_BUS | 1425 | #ifdef CONFIG_SND_SOC_AC97_BUS |
1429 | struct snd_soc_dai *codec_dai; | 1426 | struct snd_soc_dai *codec_dai; |
1430 | int i; | 1427 | int i; |
1431 | #endif | 1428 | #endif |
1432 | 1429 | ||
1433 | mutex_lock(&codec->mutex); | 1430 | mutex_lock(&codec->mutex); |
1434 | soc_cleanup_codec_debugfs(socdev->codec); | 1431 | soc_cleanup_codec_debugfs(codec); |
1435 | #ifdef CONFIG_SND_SOC_AC97_BUS | 1432 | #ifdef CONFIG_SND_SOC_AC97_BUS |
1436 | for (i = 0; i < codec->num_dai; i++) { | 1433 | for (i = 0; i < codec->num_dai; i++) { |
1437 | codec_dai = &codec->dai[i]; | 1434 | codec_dai = &codec->dai[i]; |
1438 | if (codec_dai->ac97_control && codec->ac97) { | 1435 | if (codec_dai->ac97_control && codec->ac97 && |
1436 | strcmp(codec->name, "AC97") != 0) { | ||
1439 | soc_ac97_dev_unregister(codec); | 1437 | soc_ac97_dev_unregister(codec); |
1440 | goto free_card; | 1438 | goto free_card; |
1441 | } | 1439 | } |
@@ -1498,6 +1496,37 @@ struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template, | |||
1498 | EXPORT_SYMBOL_GPL(snd_soc_cnew); | 1496 | EXPORT_SYMBOL_GPL(snd_soc_cnew); |
1499 | 1497 | ||
1500 | /** | 1498 | /** |
1499 | * snd_soc_add_controls - add an array of controls to a codec. | ||
1500 | * Convienience function to add a list of controls. Many codecs were | ||
1501 | * duplicating this code. | ||
1502 | * | ||
1503 | * @codec: codec to add controls to | ||
1504 | * @controls: array of controls to add | ||
1505 | * @num_controls: number of elements in the array | ||
1506 | * | ||
1507 | * Return 0 for success, else error. | ||
1508 | */ | ||
1509 | int snd_soc_add_controls(struct snd_soc_codec *codec, | ||
1510 | const struct snd_kcontrol_new *controls, int num_controls) | ||
1511 | { | ||
1512 | struct snd_card *card = codec->card; | ||
1513 | int err, i; | ||
1514 | |||
1515 | for (i = 0; i < num_controls; i++) { | ||
1516 | const struct snd_kcontrol_new *control = &controls[i]; | ||
1517 | err = snd_ctl_add(card, snd_soc_cnew(control, codec, NULL)); | ||
1518 | if (err < 0) { | ||
1519 | dev_err(codec->dev, "%s: Failed to add %s\n", | ||
1520 | codec->name, control->name); | ||
1521 | return err; | ||
1522 | } | ||
1523 | } | ||
1524 | |||
1525 | return 0; | ||
1526 | } | ||
1527 | EXPORT_SYMBOL_GPL(snd_soc_add_controls); | ||
1528 | |||
1529 | /** | ||
1501 | * snd_soc_info_enum_double - enumerated double mixer info callback | 1530 | * snd_soc_info_enum_double - enumerated double mixer info callback |
1502 | * @kcontrol: mixer control | 1531 | * @kcontrol: mixer control |
1503 | * @uinfo: control element information | 1532 | * @uinfo: control element information |
@@ -2023,8 +2052,8 @@ EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8); | |||
2023 | int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, | 2052 | int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, |
2024 | unsigned int freq, int dir) | 2053 | unsigned int freq, int dir) |
2025 | { | 2054 | { |
2026 | if (dai->ops.set_sysclk) | 2055 | if (dai->ops->set_sysclk) |
2027 | return dai->ops.set_sysclk(dai, clk_id, freq, dir); | 2056 | return dai->ops->set_sysclk(dai, clk_id, freq, dir); |
2028 | else | 2057 | else |
2029 | return -EINVAL; | 2058 | return -EINVAL; |
2030 | } | 2059 | } |
@@ -2043,8 +2072,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk); | |||
2043 | int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai, | 2072 | int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai, |
2044 | int div_id, int div) | 2073 | int div_id, int div) |
2045 | { | 2074 | { |
2046 | if (dai->ops.set_clkdiv) | 2075 | if (dai->ops->set_clkdiv) |
2047 | return dai->ops.set_clkdiv(dai, div_id, div); | 2076 | return dai->ops->set_clkdiv(dai, div_id, div); |
2048 | else | 2077 | else |
2049 | return -EINVAL; | 2078 | return -EINVAL; |
2050 | } | 2079 | } |
@@ -2062,8 +2091,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv); | |||
2062 | int snd_soc_dai_set_pll(struct snd_soc_dai *dai, | 2091 | int snd_soc_dai_set_pll(struct snd_soc_dai *dai, |
2063 | int pll_id, unsigned int freq_in, unsigned int freq_out) | 2092 | int pll_id, unsigned int freq_in, unsigned int freq_out) |
2064 | { | 2093 | { |
2065 | if (dai->ops.set_pll) | 2094 | if (dai->ops->set_pll) |
2066 | return dai->ops.set_pll(dai, pll_id, freq_in, freq_out); | 2095 | return dai->ops->set_pll(dai, pll_id, freq_in, freq_out); |
2067 | else | 2096 | else |
2068 | return -EINVAL; | 2097 | return -EINVAL; |
2069 | } | 2098 | } |
@@ -2078,8 +2107,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll); | |||
2078 | */ | 2107 | */ |
2079 | int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | 2108 | int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) |
2080 | { | 2109 | { |
2081 | if (dai->ops.set_fmt) | 2110 | if (dai->ops->set_fmt) |
2082 | return dai->ops.set_fmt(dai, fmt); | 2111 | return dai->ops->set_fmt(dai, fmt); |
2083 | else | 2112 | else |
2084 | return -EINVAL; | 2113 | return -EINVAL; |
2085 | } | 2114 | } |
@@ -2097,8 +2126,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt); | |||
2097 | int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, | 2126 | int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, |
2098 | unsigned int mask, int slots) | 2127 | unsigned int mask, int slots) |
2099 | { | 2128 | { |
2100 | if (dai->ops.set_sysclk) | 2129 | if (dai->ops->set_sysclk) |
2101 | return dai->ops.set_tdm_slot(dai, mask, slots); | 2130 | return dai->ops->set_tdm_slot(dai, mask, slots); |
2102 | else | 2131 | else |
2103 | return -EINVAL; | 2132 | return -EINVAL; |
2104 | } | 2133 | } |
@@ -2113,8 +2142,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot); | |||
2113 | */ | 2142 | */ |
2114 | int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate) | 2143 | int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate) |
2115 | { | 2144 | { |
2116 | if (dai->ops.set_sysclk) | 2145 | if (dai->ops->set_sysclk) |
2117 | return dai->ops.set_tristate(dai, tristate); | 2146 | return dai->ops->set_tristate(dai, tristate); |
2118 | else | 2147 | else |
2119 | return -EINVAL; | 2148 | return -EINVAL; |
2120 | } | 2149 | } |
@@ -2129,8 +2158,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate); | |||
2129 | */ | 2158 | */ |
2130 | int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute) | 2159 | int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute) |
2131 | { | 2160 | { |
2132 | if (dai->ops.digital_mute) | 2161 | if (dai->ops->digital_mute) |
2133 | return dai->ops.digital_mute(dai, mute); | 2162 | return dai->ops->digital_mute(dai, mute); |
2134 | else | 2163 | else |
2135 | return -EINVAL; | 2164 | return -EINVAL; |
2136 | } | 2165 | } |
@@ -2183,6 +2212,9 @@ static int snd_soc_unregister_card(struct snd_soc_card *card) | |||
2183 | return 0; | 2212 | return 0; |
2184 | } | 2213 | } |
2185 | 2214 | ||
2215 | static struct snd_soc_dai_ops null_dai_ops = { | ||
2216 | }; | ||
2217 | |||
2186 | /** | 2218 | /** |
2187 | * snd_soc_register_dai - Register a DAI with the ASoC core | 2219 | * snd_soc_register_dai - Register a DAI with the ASoC core |
2188 | * | 2220 | * |
@@ -2197,6 +2229,9 @@ int snd_soc_register_dai(struct snd_soc_dai *dai) | |||
2197 | if (!dai->dev) | 2229 | if (!dai->dev) |
2198 | printk(KERN_WARNING "No device for DAI %s\n", dai->name); | 2230 | printk(KERN_WARNING "No device for DAI %s\n", dai->name); |
2199 | 2231 | ||
2232 | if (!dai->ops) | ||
2233 | dai->ops = &null_dai_ops; | ||
2234 | |||
2200 | INIT_LIST_HEAD(&dai->list); | 2235 | INIT_LIST_HEAD(&dai->list); |
2201 | 2236 | ||
2202 | mutex_lock(&client_mutex); | 2237 | mutex_lock(&client_mutex); |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index a2f1da8b4646..735903a74675 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -54,14 +54,15 @@ | |||
54 | static int dapm_up_seq[] = { | 54 | static int dapm_up_seq[] = { |
55 | snd_soc_dapm_pre, snd_soc_dapm_micbias, snd_soc_dapm_mic, | 55 | snd_soc_dapm_pre, snd_soc_dapm_micbias, snd_soc_dapm_mic, |
56 | snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_dac, | 56 | snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_dac, |
57 | snd_soc_dapm_mixer, snd_soc_dapm_pga, snd_soc_dapm_adc, snd_soc_dapm_hp, | 57 | snd_soc_dapm_mixer, snd_soc_dapm_mixer_named_ctl, snd_soc_dapm_pga, |
58 | snd_soc_dapm_spk, snd_soc_dapm_post | 58 | snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk, snd_soc_dapm_post |
59 | }; | 59 | }; |
60 | |||
60 | static int dapm_down_seq[] = { | 61 | static int dapm_down_seq[] = { |
61 | snd_soc_dapm_pre, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk, | 62 | snd_soc_dapm_pre, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk, |
62 | snd_soc_dapm_pga, snd_soc_dapm_mixer, snd_soc_dapm_dac, snd_soc_dapm_mic, | 63 | snd_soc_dapm_pga, snd_soc_dapm_mixer_named_ctl, snd_soc_dapm_mixer, |
63 | snd_soc_dapm_micbias, snd_soc_dapm_mux, snd_soc_dapm_value_mux, | 64 | snd_soc_dapm_dac, snd_soc_dapm_mic, snd_soc_dapm_micbias, |
64 | snd_soc_dapm_post | 65 | snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_post |
65 | }; | 66 | }; |
66 | 67 | ||
67 | static int dapm_status = 1; | 68 | static int dapm_status = 1; |
@@ -101,7 +102,8 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, | |||
101 | { | 102 | { |
102 | switch (w->id) { | 103 | switch (w->id) { |
103 | case snd_soc_dapm_switch: | 104 | case snd_soc_dapm_switch: |
104 | case snd_soc_dapm_mixer: { | 105 | case snd_soc_dapm_mixer: |
106 | case snd_soc_dapm_mixer_named_ctl: { | ||
105 | int val; | 107 | int val; |
106 | struct soc_mixer_control *mc = (struct soc_mixer_control *) | 108 | struct soc_mixer_control *mc = (struct soc_mixer_control *) |
107 | w->kcontrols[i].private_value; | 109 | w->kcontrols[i].private_value; |
@@ -323,15 +325,32 @@ static int dapm_new_mixer(struct snd_soc_codec *codec, | |||
323 | if (path->name != (char*)w->kcontrols[i].name) | 325 | if (path->name != (char*)w->kcontrols[i].name) |
324 | continue; | 326 | continue; |
325 | 327 | ||
326 | /* add dapm control with long name */ | 328 | /* add dapm control with long name. |
327 | name_len = 2 + strlen(w->name) | 329 | * for dapm_mixer this is the concatenation of the |
328 | + strlen(w->kcontrols[i].name); | 330 | * mixer and kcontrol name. |
331 | * for dapm_mixer_named_ctl this is simply the | ||
332 | * kcontrol name. | ||
333 | */ | ||
334 | name_len = strlen(w->kcontrols[i].name) + 1; | ||
335 | if (w->id != snd_soc_dapm_mixer_named_ctl) | ||
336 | name_len += 1 + strlen(w->name); | ||
337 | |||
329 | path->long_name = kmalloc(name_len, GFP_KERNEL); | 338 | path->long_name = kmalloc(name_len, GFP_KERNEL); |
339 | |||
330 | if (path->long_name == NULL) | 340 | if (path->long_name == NULL) |
331 | return -ENOMEM; | 341 | return -ENOMEM; |
332 | 342 | ||
333 | snprintf(path->long_name, name_len, "%s %s", | 343 | switch (w->id) { |
334 | w->name, w->kcontrols[i].name); | 344 | default: |
345 | snprintf(path->long_name, name_len, "%s %s", | ||
346 | w->name, w->kcontrols[i].name); | ||
347 | break; | ||
348 | case snd_soc_dapm_mixer_named_ctl: | ||
349 | snprintf(path->long_name, name_len, "%s", | ||
350 | w->kcontrols[i].name); | ||
351 | break; | ||
352 | } | ||
353 | |||
335 | path->long_name[name_len - 1] = '\0'; | 354 | path->long_name[name_len - 1] = '\0'; |
336 | 355 | ||
337 | path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w, | 356 | path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w, |
@@ -503,6 +522,137 @@ int dapm_reg_event(struct snd_soc_dapm_widget *w, | |||
503 | EXPORT_SYMBOL_GPL(dapm_reg_event); | 522 | EXPORT_SYMBOL_GPL(dapm_reg_event); |
504 | 523 | ||
505 | /* | 524 | /* |
525 | * Scan a single DAPM widget for a complete audio path and update the | ||
526 | * power status appropriately. | ||
527 | */ | ||
528 | static int dapm_power_widget(struct snd_soc_codec *codec, int event, | ||
529 | struct snd_soc_dapm_widget *w) | ||
530 | { | ||
531 | int in, out, power_change, power, ret; | ||
532 | |||
533 | /* vmid - no action */ | ||
534 | if (w->id == snd_soc_dapm_vmid) | ||
535 | return 0; | ||
536 | |||
537 | /* active ADC */ | ||
538 | if (w->id == snd_soc_dapm_adc && w->active) { | ||
539 | in = is_connected_input_ep(w); | ||
540 | dapm_clear_walk(w->codec); | ||
541 | w->power = (in != 0) ? 1 : 0; | ||
542 | dapm_update_bits(w); | ||
543 | return 0; | ||
544 | } | ||
545 | |||
546 | /* active DAC */ | ||
547 | if (w->id == snd_soc_dapm_dac && w->active) { | ||
548 | out = is_connected_output_ep(w); | ||
549 | dapm_clear_walk(w->codec); | ||
550 | w->power = (out != 0) ? 1 : 0; | ||
551 | dapm_update_bits(w); | ||
552 | return 0; | ||
553 | } | ||
554 | |||
555 | /* pre and post event widgets */ | ||
556 | if (w->id == snd_soc_dapm_pre) { | ||
557 | if (!w->event) | ||
558 | return 0; | ||
559 | |||
560 | if (event == SND_SOC_DAPM_STREAM_START) { | ||
561 | ret = w->event(w, | ||
562 | NULL, SND_SOC_DAPM_PRE_PMU); | ||
563 | if (ret < 0) | ||
564 | return ret; | ||
565 | } else if (event == SND_SOC_DAPM_STREAM_STOP) { | ||
566 | ret = w->event(w, | ||
567 | NULL, SND_SOC_DAPM_PRE_PMD); | ||
568 | if (ret < 0) | ||
569 | return ret; | ||
570 | } | ||
571 | return 0; | ||
572 | } | ||
573 | if (w->id == snd_soc_dapm_post) { | ||
574 | if (!w->event) | ||
575 | return 0; | ||
576 | |||
577 | if (event == SND_SOC_DAPM_STREAM_START) { | ||
578 | ret = w->event(w, | ||
579 | NULL, SND_SOC_DAPM_POST_PMU); | ||
580 | if (ret < 0) | ||
581 | return ret; | ||
582 | } else if (event == SND_SOC_DAPM_STREAM_STOP) { | ||
583 | ret = w->event(w, | ||
584 | NULL, SND_SOC_DAPM_POST_PMD); | ||
585 | if (ret < 0) | ||
586 | return ret; | ||
587 | } | ||
588 | return 0; | ||
589 | } | ||
590 | |||
591 | /* all other widgets */ | ||
592 | in = is_connected_input_ep(w); | ||
593 | dapm_clear_walk(w->codec); | ||
594 | out = is_connected_output_ep(w); | ||
595 | dapm_clear_walk(w->codec); | ||
596 | power = (out != 0 && in != 0) ? 1 : 0; | ||
597 | power_change = (w->power == power) ? 0 : 1; | ||
598 | w->power = power; | ||
599 | |||
600 | if (!power_change) | ||
601 | return 0; | ||
602 | |||
603 | /* call any power change event handlers */ | ||
604 | if (w->event) | ||
605 | pr_debug("power %s event for %s flags %x\n", | ||
606 | w->power ? "on" : "off", | ||
607 | w->name, w->event_flags); | ||
608 | |||
609 | /* power up pre event */ | ||
610 | if (power && w->event && | ||
611 | (w->event_flags & SND_SOC_DAPM_PRE_PMU)) { | ||
612 | ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMU); | ||
613 | if (ret < 0) | ||
614 | return ret; | ||
615 | } | ||
616 | |||
617 | /* power down pre event */ | ||
618 | if (!power && w->event && | ||
619 | (w->event_flags & SND_SOC_DAPM_PRE_PMD)) { | ||
620 | ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMD); | ||
621 | if (ret < 0) | ||
622 | return ret; | ||
623 | } | ||
624 | |||
625 | /* Lower PGA volume to reduce pops */ | ||
626 | if (w->id == snd_soc_dapm_pga && !power) | ||
627 | dapm_set_pga(w, power); | ||
628 | |||
629 | dapm_update_bits(w); | ||
630 | |||
631 | /* Raise PGA volume to reduce pops */ | ||
632 | if (w->id == snd_soc_dapm_pga && power) | ||
633 | dapm_set_pga(w, power); | ||
634 | |||
635 | /* power up post event */ | ||
636 | if (power && w->event && | ||
637 | (w->event_flags & SND_SOC_DAPM_POST_PMU)) { | ||
638 | ret = w->event(w, | ||
639 | NULL, SND_SOC_DAPM_POST_PMU); | ||
640 | if (ret < 0) | ||
641 | return ret; | ||
642 | } | ||
643 | |||
644 | /* power down post event */ | ||
645 | if (!power && w->event && | ||
646 | (w->event_flags & SND_SOC_DAPM_POST_PMD)) { | ||
647 | ret = w->event(w, NULL, SND_SOC_DAPM_POST_PMD); | ||
648 | if (ret < 0) | ||
649 | return ret; | ||
650 | } | ||
651 | |||
652 | return 0; | ||
653 | } | ||
654 | |||
655 | /* | ||
506 | * Scan each dapm widget for complete audio path. | 656 | * Scan each dapm widget for complete audio path. |
507 | * A complete path is a route that has valid endpoints i.e.:- | 657 | * A complete path is a route that has valid endpoints i.e.:- |
508 | * | 658 | * |
@@ -514,7 +664,7 @@ EXPORT_SYMBOL_GPL(dapm_reg_event); | |||
514 | static int dapm_power_widgets(struct snd_soc_codec *codec, int event) | 664 | static int dapm_power_widgets(struct snd_soc_codec *codec, int event) |
515 | { | 665 | { |
516 | struct snd_soc_dapm_widget *w; | 666 | struct snd_soc_dapm_widget *w; |
517 | int in, out, i, c = 1, *seq = NULL, ret = 0, power_change, power; | 667 | int i, c = 1, *seq = NULL, ret = 0; |
518 | 668 | ||
519 | /* do we have a sequenced stream event */ | 669 | /* do we have a sequenced stream event */ |
520 | if (event == SND_SOC_DAPM_STREAM_START) { | 670 | if (event == SND_SOC_DAPM_STREAM_START) { |
@@ -525,135 +675,20 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event) | |||
525 | seq = dapm_down_seq; | 675 | seq = dapm_down_seq; |
526 | } | 676 | } |
527 | 677 | ||
528 | for(i = 0; i < c; i++) { | 678 | for (i = 0; i < c; i++) { |
529 | list_for_each_entry(w, &codec->dapm_widgets, list) { | 679 | list_for_each_entry(w, &codec->dapm_widgets, list) { |
530 | 680 | ||
531 | /* is widget in stream order */ | 681 | /* is widget in stream order */ |
532 | if (seq && seq[i] && w->id != seq[i]) | 682 | if (seq && seq[i] && w->id != seq[i]) |
533 | continue; | 683 | continue; |
534 | 684 | ||
535 | /* vmid - no action */ | 685 | ret = dapm_power_widget(codec, event, w); |
536 | if (w->id == snd_soc_dapm_vmid) | 686 | if (ret != 0) |
537 | continue; | 687 | return ret; |
538 | |||
539 | /* active ADC */ | ||
540 | if (w->id == snd_soc_dapm_adc && w->active) { | ||
541 | in = is_connected_input_ep(w); | ||
542 | dapm_clear_walk(w->codec); | ||
543 | w->power = (in != 0) ? 1 : 0; | ||
544 | dapm_update_bits(w); | ||
545 | continue; | ||
546 | } | ||
547 | |||
548 | /* active DAC */ | ||
549 | if (w->id == snd_soc_dapm_dac && w->active) { | ||
550 | out = is_connected_output_ep(w); | ||
551 | dapm_clear_walk(w->codec); | ||
552 | w->power = (out != 0) ? 1 : 0; | ||
553 | dapm_update_bits(w); | ||
554 | continue; | ||
555 | } | ||
556 | |||
557 | /* pre and post event widgets */ | ||
558 | if (w->id == snd_soc_dapm_pre) { | ||
559 | if (!w->event) | ||
560 | continue; | ||
561 | |||
562 | if (event == SND_SOC_DAPM_STREAM_START) { | ||
563 | ret = w->event(w, | ||
564 | NULL, SND_SOC_DAPM_PRE_PMU); | ||
565 | if (ret < 0) | ||
566 | return ret; | ||
567 | } else if (event == SND_SOC_DAPM_STREAM_STOP) { | ||
568 | ret = w->event(w, | ||
569 | NULL, SND_SOC_DAPM_PRE_PMD); | ||
570 | if (ret < 0) | ||
571 | return ret; | ||
572 | } | ||
573 | continue; | ||
574 | } | ||
575 | if (w->id == snd_soc_dapm_post) { | ||
576 | if (!w->event) | ||
577 | continue; | ||
578 | |||
579 | if (event == SND_SOC_DAPM_STREAM_START) { | ||
580 | ret = w->event(w, | ||
581 | NULL, SND_SOC_DAPM_POST_PMU); | ||
582 | if (ret < 0) | ||
583 | return ret; | ||
584 | } else if (event == SND_SOC_DAPM_STREAM_STOP) { | ||
585 | ret = w->event(w, | ||
586 | NULL, SND_SOC_DAPM_POST_PMD); | ||
587 | if (ret < 0) | ||
588 | return ret; | ||
589 | } | ||
590 | continue; | ||
591 | } | ||
592 | |||
593 | /* all other widgets */ | ||
594 | in = is_connected_input_ep(w); | ||
595 | dapm_clear_walk(w->codec); | ||
596 | out = is_connected_output_ep(w); | ||
597 | dapm_clear_walk(w->codec); | ||
598 | power = (out != 0 && in != 0) ? 1 : 0; | ||
599 | power_change = (w->power == power) ? 0: 1; | ||
600 | w->power = power; | ||
601 | |||
602 | if (!power_change) | ||
603 | continue; | ||
604 | |||
605 | /* call any power change event handlers */ | ||
606 | if (w->event) | ||
607 | pr_debug("power %s event for %s flags %x\n", | ||
608 | w->power ? "on" : "off", | ||
609 | w->name, w->event_flags); | ||
610 | |||
611 | /* power up pre event */ | ||
612 | if (power && w->event && | ||
613 | (w->event_flags & SND_SOC_DAPM_PRE_PMU)) { | ||
614 | ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMU); | ||
615 | if (ret < 0) | ||
616 | return ret; | ||
617 | } | ||
618 | |||
619 | /* power down pre event */ | ||
620 | if (!power && w->event && | ||
621 | (w->event_flags & SND_SOC_DAPM_PRE_PMD)) { | ||
622 | ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMD); | ||
623 | if (ret < 0) | ||
624 | return ret; | ||
625 | } | ||
626 | |||
627 | /* Lower PGA volume to reduce pops */ | ||
628 | if (w->id == snd_soc_dapm_pga && !power) | ||
629 | dapm_set_pga(w, power); | ||
630 | |||
631 | dapm_update_bits(w); | ||
632 | |||
633 | /* Raise PGA volume to reduce pops */ | ||
634 | if (w->id == snd_soc_dapm_pga && power) | ||
635 | dapm_set_pga(w, power); | ||
636 | |||
637 | /* power up post event */ | ||
638 | if (power && w->event && | ||
639 | (w->event_flags & SND_SOC_DAPM_POST_PMU)) { | ||
640 | ret = w->event(w, | ||
641 | NULL, SND_SOC_DAPM_POST_PMU); | ||
642 | if (ret < 0) | ||
643 | return ret; | ||
644 | } | ||
645 | |||
646 | /* power down post event */ | ||
647 | if (!power && w->event && | ||
648 | (w->event_flags & SND_SOC_DAPM_POST_PMD)) { | ||
649 | ret = w->event(w, NULL, SND_SOC_DAPM_POST_PMD); | ||
650 | if (ret < 0) | ||
651 | return ret; | ||
652 | } | ||
653 | } | 688 | } |
654 | } | 689 | } |
655 | 690 | ||
656 | return ret; | 691 | return 0; |
657 | } | 692 | } |
658 | 693 | ||
659 | #ifdef DEBUG | 694 | #ifdef DEBUG |
@@ -687,6 +722,7 @@ static void dbg_dump_dapm(struct snd_soc_codec* codec, const char *action) | |||
687 | case snd_soc_dapm_adc: | 722 | case snd_soc_dapm_adc: |
688 | case snd_soc_dapm_pga: | 723 | case snd_soc_dapm_pga: |
689 | case snd_soc_dapm_mixer: | 724 | case snd_soc_dapm_mixer: |
725 | case snd_soc_dapm_mixer_named_ctl: | ||
690 | if (w->name) { | 726 | if (w->name) { |
691 | in = is_connected_input_ep(w); | 727 | in = is_connected_input_ep(w); |
692 | dapm_clear_walk(w->codec); | 728 | dapm_clear_walk(w->codec); |
@@ -760,6 +796,7 @@ static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget, | |||
760 | int found = 0; | 796 | int found = 0; |
761 | 797 | ||
762 | if (widget->id != snd_soc_dapm_mixer && | 798 | if (widget->id != snd_soc_dapm_mixer && |
799 | widget->id != snd_soc_dapm_mixer_named_ctl && | ||
763 | widget->id != snd_soc_dapm_switch) | 800 | widget->id != snd_soc_dapm_switch) |
764 | return -ENODEV; | 801 | return -ENODEV; |
765 | 802 | ||
@@ -795,7 +832,7 @@ static ssize_t dapm_widget_show(struct device *dev, | |||
795 | struct device_attribute *attr, char *buf) | 832 | struct device_attribute *attr, char *buf) |
796 | { | 833 | { |
797 | struct snd_soc_device *devdata = dev_get_drvdata(dev); | 834 | struct snd_soc_device *devdata = dev_get_drvdata(dev); |
798 | struct snd_soc_codec *codec = devdata->codec; | 835 | struct snd_soc_codec *codec = devdata->card->codec; |
799 | struct snd_soc_dapm_widget *w; | 836 | struct snd_soc_dapm_widget *w; |
800 | int count = 0; | 837 | int count = 0; |
801 | char *state = "not set"; | 838 | char *state = "not set"; |
@@ -813,6 +850,7 @@ static ssize_t dapm_widget_show(struct device *dev, | |||
813 | case snd_soc_dapm_adc: | 850 | case snd_soc_dapm_adc: |
814 | case snd_soc_dapm_pga: | 851 | case snd_soc_dapm_pga: |
815 | case snd_soc_dapm_mixer: | 852 | case snd_soc_dapm_mixer: |
853 | case snd_soc_dapm_mixer_named_ctl: | ||
816 | if (w->name) | 854 | if (w->name) |
817 | count += sprintf(buf + count, "%s: %s\n", | 855 | count += sprintf(buf + count, "%s: %s\n", |
818 | w->name, w->power ? "On":"Off"); | 856 | w->name, w->power ? "On":"Off"); |
@@ -876,7 +914,7 @@ static void dapm_free_widgets(struct snd_soc_codec *codec) | |||
876 | } | 914 | } |
877 | 915 | ||
878 | static int snd_soc_dapm_set_pin(struct snd_soc_codec *codec, | 916 | static int snd_soc_dapm_set_pin(struct snd_soc_codec *codec, |
879 | char *pin, int status) | 917 | const char *pin, int status) |
880 | { | 918 | { |
881 | struct snd_soc_dapm_widget *w; | 919 | struct snd_soc_dapm_widget *w; |
882 | 920 | ||
@@ -991,6 +1029,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_codec *codec, | |||
991 | break; | 1029 | break; |
992 | case snd_soc_dapm_switch: | 1030 | case snd_soc_dapm_switch: |
993 | case snd_soc_dapm_mixer: | 1031 | case snd_soc_dapm_mixer: |
1032 | case snd_soc_dapm_mixer_named_ctl: | ||
994 | ret = dapm_connect_mixer(codec, wsource, wsink, path, control); | 1033 | ret = dapm_connect_mixer(codec, wsource, wsink, path, control); |
995 | if (ret != 0) | 1034 | if (ret != 0) |
996 | goto err; | 1035 | goto err; |
@@ -1068,6 +1107,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec) | |||
1068 | switch(w->id) { | 1107 | switch(w->id) { |
1069 | case snd_soc_dapm_switch: | 1108 | case snd_soc_dapm_switch: |
1070 | case snd_soc_dapm_mixer: | 1109 | case snd_soc_dapm_mixer: |
1110 | case snd_soc_dapm_mixer_named_ctl: | ||
1071 | dapm_new_mixer(codec, w); | 1111 | dapm_new_mixer(codec, w); |
1072 | break; | 1112 | break; |
1073 | case snd_soc_dapm_mux: | 1113 | case snd_soc_dapm_mux: |
@@ -1396,6 +1436,76 @@ out: | |||
1396 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double); | 1436 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double); |
1397 | 1437 | ||
1398 | /** | 1438 | /** |
1439 | * snd_soc_dapm_info_pin_switch - Info for a pin switch | ||
1440 | * | ||
1441 | * @kcontrol: mixer control | ||
1442 | * @uinfo: control element information | ||
1443 | * | ||
1444 | * Callback to provide information about a pin switch control. | ||
1445 | */ | ||
1446 | int snd_soc_dapm_info_pin_switch(struct snd_kcontrol *kcontrol, | ||
1447 | struct snd_ctl_elem_info *uinfo) | ||
1448 | { | ||
1449 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1450 | uinfo->count = 1; | ||
1451 | uinfo->value.integer.min = 0; | ||
1452 | uinfo->value.integer.max = 1; | ||
1453 | |||
1454 | return 0; | ||
1455 | } | ||
1456 | EXPORT_SYMBOL_GPL(snd_soc_dapm_info_pin_switch); | ||
1457 | |||
1458 | /** | ||
1459 | * snd_soc_dapm_get_pin_switch - Get information for a pin switch | ||
1460 | * | ||
1461 | * @kcontrol: mixer control | ||
1462 | * @ucontrol: Value | ||
1463 | */ | ||
1464 | int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol, | ||
1465 | struct snd_ctl_elem_value *ucontrol) | ||
1466 | { | ||
1467 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1468 | const char *pin = (const char *)kcontrol->private_value; | ||
1469 | |||
1470 | mutex_lock(&codec->mutex); | ||
1471 | |||
1472 | ucontrol->value.integer.value[0] = | ||
1473 | snd_soc_dapm_get_pin_status(codec, pin); | ||
1474 | |||
1475 | mutex_unlock(&codec->mutex); | ||
1476 | |||
1477 | return 0; | ||
1478 | } | ||
1479 | EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_switch); | ||
1480 | |||
1481 | /** | ||
1482 | * snd_soc_dapm_put_pin_switch - Set information for a pin switch | ||
1483 | * | ||
1484 | * @kcontrol: mixer control | ||
1485 | * @ucontrol: Value | ||
1486 | */ | ||
1487 | int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol, | ||
1488 | struct snd_ctl_elem_value *ucontrol) | ||
1489 | { | ||
1490 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1491 | const char *pin = (const char *)kcontrol->private_value; | ||
1492 | |||
1493 | mutex_lock(&codec->mutex); | ||
1494 | |||
1495 | if (ucontrol->value.integer.value[0]) | ||
1496 | snd_soc_dapm_enable_pin(codec, pin); | ||
1497 | else | ||
1498 | snd_soc_dapm_disable_pin(codec, pin); | ||
1499 | |||
1500 | snd_soc_dapm_sync(codec); | ||
1501 | |||
1502 | mutex_unlock(&codec->mutex); | ||
1503 | |||
1504 | return 0; | ||
1505 | } | ||
1506 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_pin_switch); | ||
1507 | |||
1508 | /** | ||
1399 | * snd_soc_dapm_new_control - create new dapm control | 1509 | * snd_soc_dapm_new_control - create new dapm control |
1400 | * @codec: audio codec | 1510 | * @codec: audio codec |
1401 | * @widget: widget template | 1511 | * @widget: widget template |
@@ -1527,8 +1637,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event); | |||
1527 | int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev, | 1637 | int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev, |
1528 | enum snd_soc_bias_level level) | 1638 | enum snd_soc_bias_level level) |
1529 | { | 1639 | { |
1530 | struct snd_soc_codec *codec = socdev->codec; | ||
1531 | struct snd_soc_card *card = socdev->card; | 1640 | struct snd_soc_card *card = socdev->card; |
1641 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1532 | int ret = 0; | 1642 | int ret = 0; |
1533 | 1643 | ||
1534 | if (card->set_bias_level) | 1644 | if (card->set_bias_level) |
@@ -1549,7 +1659,7 @@ int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev, | |||
1549 | * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to | 1659 | * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to |
1550 | * do any widget power switching. | 1660 | * do any widget power switching. |
1551 | */ | 1661 | */ |
1552 | int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, char *pin) | 1662 | int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, const char *pin) |
1553 | { | 1663 | { |
1554 | return snd_soc_dapm_set_pin(codec, pin, 1); | 1664 | return snd_soc_dapm_set_pin(codec, pin, 1); |
1555 | } | 1665 | } |
@@ -1564,7 +1674,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin); | |||
1564 | * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to | 1674 | * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to |
1565 | * do any widget power switching. | 1675 | * do any widget power switching. |
1566 | */ | 1676 | */ |
1567 | int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, char *pin) | 1677 | int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, const char *pin) |
1568 | { | 1678 | { |
1569 | return snd_soc_dapm_set_pin(codec, pin, 0); | 1679 | return snd_soc_dapm_set_pin(codec, pin, 0); |
1570 | } | 1680 | } |
@@ -1584,7 +1694,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin); | |||
1584 | * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to | 1694 | * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to |
1585 | * do any widget power switching. | 1695 | * do any widget power switching. |
1586 | */ | 1696 | */ |
1587 | int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, char *pin) | 1697 | int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, const char *pin) |
1588 | { | 1698 | { |
1589 | return snd_soc_dapm_set_pin(codec, pin, 0); | 1699 | return snd_soc_dapm_set_pin(codec, pin, 0); |
1590 | } | 1700 | } |
@@ -1599,7 +1709,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin); | |||
1599 | * | 1709 | * |
1600 | * Returns 1 for connected otherwise 0. | 1710 | * Returns 1 for connected otherwise 0. |
1601 | */ | 1711 | */ |
1602 | int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, char *pin) | 1712 | int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, const char *pin) |
1603 | { | 1713 | { |
1604 | struct snd_soc_dapm_widget *w; | 1714 | struct snd_soc_dapm_widget *w; |
1605 | 1715 | ||
@@ -1620,7 +1730,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_status); | |||
1620 | */ | 1730 | */ |
1621 | void snd_soc_dapm_free(struct snd_soc_device *socdev) | 1731 | void snd_soc_dapm_free(struct snd_soc_device *socdev) |
1622 | { | 1732 | { |
1623 | struct snd_soc_codec *codec = socdev->codec; | 1733 | struct snd_soc_codec *codec = socdev->card->codec; |
1624 | 1734 | ||
1625 | snd_soc_dapm_sys_remove(socdev->dev); | 1735 | snd_soc_dapm_sys_remove(socdev->dev); |
1626 | dapm_free_widgets(codec); | 1736 | dapm_free_widgets(codec); |
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c new file mode 100644 index 000000000000..28346fb2e70c --- /dev/null +++ b/sound/soc/soc-jack.c | |||
@@ -0,0 +1,267 @@ | |||
1 | /* | ||
2 | * soc-jack.c -- ALSA SoC jack handling | ||
3 | * | ||
4 | * Copyright 2008 Wolfson Microelectronics PLC. | ||
5 | * | ||
6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <sound/jack.h> | ||
15 | #include <sound/soc.h> | ||
16 | #include <sound/soc-dapm.h> | ||
17 | #include <linux/gpio.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/workqueue.h> | ||
20 | #include <linux/delay.h> | ||
21 | |||
22 | /** | ||
23 | * snd_soc_jack_new - Create a new jack | ||
24 | * @card: ASoC card | ||
25 | * @id: an identifying string for this jack | ||
26 | * @type: a bitmask of enum snd_jack_type values that can be detected by | ||
27 | * this jack | ||
28 | * @jack: structure to use for the jack | ||
29 | * | ||
30 | * Creates a new jack object. | ||
31 | * | ||
32 | * Returns zero if successful, or a negative error code on failure. | ||
33 | * On success jack will be initialised. | ||
34 | */ | ||
35 | int snd_soc_jack_new(struct snd_soc_card *card, const char *id, int type, | ||
36 | struct snd_soc_jack *jack) | ||
37 | { | ||
38 | jack->card = card; | ||
39 | INIT_LIST_HEAD(&jack->pins); | ||
40 | |||
41 | return snd_jack_new(card->codec->card, id, type, &jack->jack); | ||
42 | } | ||
43 | EXPORT_SYMBOL_GPL(snd_soc_jack_new); | ||
44 | |||
45 | /** | ||
46 | * snd_soc_jack_report - Report the current status for a jack | ||
47 | * | ||
48 | * @jack: the jack | ||
49 | * @status: a bitmask of enum snd_jack_type values that are currently detected. | ||
50 | * @mask: a bitmask of enum snd_jack_type values that being reported. | ||
51 | * | ||
52 | * If configured using snd_soc_jack_add_pins() then the associated | ||
53 | * DAPM pins will be enabled or disabled as appropriate and DAPM | ||
54 | * synchronised. | ||
55 | * | ||
56 | * Note: This function uses mutexes and should be called from a | ||
57 | * context which can sleep (such as a workqueue). | ||
58 | */ | ||
59 | void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask) | ||
60 | { | ||
61 | struct snd_soc_codec *codec = jack->card->codec; | ||
62 | struct snd_soc_jack_pin *pin; | ||
63 | int enable; | ||
64 | int oldstatus; | ||
65 | |||
66 | if (!jack) { | ||
67 | WARN_ON_ONCE(!jack); | ||
68 | return; | ||
69 | } | ||
70 | |||
71 | mutex_lock(&codec->mutex); | ||
72 | |||
73 | oldstatus = jack->status; | ||
74 | |||
75 | jack->status &= ~mask; | ||
76 | jack->status |= status; | ||
77 | |||
78 | /* The DAPM sync is expensive enough to be worth skipping */ | ||
79 | if (jack->status == oldstatus) | ||
80 | goto out; | ||
81 | |||
82 | list_for_each_entry(pin, &jack->pins, list) { | ||
83 | enable = pin->mask & status; | ||
84 | |||
85 | if (pin->invert) | ||
86 | enable = !enable; | ||
87 | |||
88 | if (enable) | ||
89 | snd_soc_dapm_enable_pin(codec, pin->pin); | ||
90 | else | ||
91 | snd_soc_dapm_disable_pin(codec, pin->pin); | ||
92 | } | ||
93 | |||
94 | snd_soc_dapm_sync(codec); | ||
95 | |||
96 | snd_jack_report(jack->jack, status); | ||
97 | |||
98 | out: | ||
99 | mutex_unlock(&codec->mutex); | ||
100 | } | ||
101 | EXPORT_SYMBOL_GPL(snd_soc_jack_report); | ||
102 | |||
103 | /** | ||
104 | * snd_soc_jack_add_pins - Associate DAPM pins with an ASoC jack | ||
105 | * | ||
106 | * @jack: ASoC jack | ||
107 | * @count: Number of pins | ||
108 | * @pins: Array of pins | ||
109 | * | ||
110 | * After this function has been called the DAPM pins specified in the | ||
111 | * pins array will have their status updated to reflect the current | ||
112 | * state of the jack whenever the jack status is updated. | ||
113 | */ | ||
114 | int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count, | ||
115 | struct snd_soc_jack_pin *pins) | ||
116 | { | ||
117 | int i; | ||
118 | |||
119 | for (i = 0; i < count; i++) { | ||
120 | if (!pins[i].pin) { | ||
121 | printk(KERN_ERR "No name for pin %d\n", i); | ||
122 | return -EINVAL; | ||
123 | } | ||
124 | if (!pins[i].mask) { | ||
125 | printk(KERN_ERR "No mask for pin %d (%s)\n", i, | ||
126 | pins[i].pin); | ||
127 | return -EINVAL; | ||
128 | } | ||
129 | |||
130 | INIT_LIST_HEAD(&pins[i].list); | ||
131 | list_add(&(pins[i].list), &jack->pins); | ||
132 | } | ||
133 | |||
134 | /* Update to reflect the last reported status; canned jack | ||
135 | * implementations are likely to set their state before the | ||
136 | * card has an opportunity to associate pins. | ||
137 | */ | ||
138 | snd_soc_jack_report(jack, 0, 0); | ||
139 | |||
140 | return 0; | ||
141 | } | ||
142 | EXPORT_SYMBOL_GPL(snd_soc_jack_add_pins); | ||
143 | |||
144 | #ifdef CONFIG_GPIOLIB | ||
145 | /* gpio detect */ | ||
146 | static void snd_soc_jack_gpio_detect(struct snd_soc_jack_gpio *gpio) | ||
147 | { | ||
148 | struct snd_soc_jack *jack = gpio->jack; | ||
149 | int enable; | ||
150 | int report; | ||
151 | |||
152 | if (gpio->debounce_time > 0) | ||
153 | mdelay(gpio->debounce_time); | ||
154 | |||
155 | enable = gpio_get_value(gpio->gpio); | ||
156 | if (gpio->invert) | ||
157 | enable = !enable; | ||
158 | |||
159 | if (enable) | ||
160 | report = gpio->report; | ||
161 | else | ||
162 | report = 0; | ||
163 | |||
164 | snd_soc_jack_report(jack, report, gpio->report); | ||
165 | } | ||
166 | |||
167 | /* irq handler for gpio pin */ | ||
168 | static irqreturn_t gpio_handler(int irq, void *data) | ||
169 | { | ||
170 | struct snd_soc_jack_gpio *gpio = data; | ||
171 | |||
172 | schedule_work(&gpio->work); | ||
173 | |||
174 | return IRQ_HANDLED; | ||
175 | } | ||
176 | |||
177 | /* gpio work */ | ||
178 | static void gpio_work(struct work_struct *work) | ||
179 | { | ||
180 | struct snd_soc_jack_gpio *gpio; | ||
181 | |||
182 | gpio = container_of(work, struct snd_soc_jack_gpio, work); | ||
183 | snd_soc_jack_gpio_detect(gpio); | ||
184 | } | ||
185 | |||
186 | /** | ||
187 | * snd_soc_jack_add_gpios - Associate GPIO pins with an ASoC jack | ||
188 | * | ||
189 | * @jack: ASoC jack | ||
190 | * @count: number of pins | ||
191 | * @gpios: array of gpio pins | ||
192 | * | ||
193 | * This function will request gpio, set data direction and request irq | ||
194 | * for each gpio in the array. | ||
195 | */ | ||
196 | int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count, | ||
197 | struct snd_soc_jack_gpio *gpios) | ||
198 | { | ||
199 | int i, ret; | ||
200 | |||
201 | for (i = 0; i < count; i++) { | ||
202 | if (!gpio_is_valid(gpios[i].gpio)) { | ||
203 | printk(KERN_ERR "Invalid gpio %d\n", | ||
204 | gpios[i].gpio); | ||
205 | ret = -EINVAL; | ||
206 | goto undo; | ||
207 | } | ||
208 | if (!gpios[i].name) { | ||
209 | printk(KERN_ERR "No name for gpio %d\n", | ||
210 | gpios[i].gpio); | ||
211 | ret = -EINVAL; | ||
212 | goto undo; | ||
213 | } | ||
214 | |||
215 | ret = gpio_request(gpios[i].gpio, gpios[i].name); | ||
216 | if (ret) | ||
217 | goto undo; | ||
218 | |||
219 | ret = gpio_direction_input(gpios[i].gpio); | ||
220 | if (ret) | ||
221 | goto err; | ||
222 | |||
223 | ret = request_irq(gpio_to_irq(gpios[i].gpio), | ||
224 | gpio_handler, | ||
225 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, | ||
226 | jack->card->dev->driver->name, | ||
227 | &gpios[i]); | ||
228 | if (ret) | ||
229 | goto err; | ||
230 | |||
231 | INIT_WORK(&gpios[i].work, gpio_work); | ||
232 | gpios[i].jack = jack; | ||
233 | } | ||
234 | |||
235 | return 0; | ||
236 | |||
237 | err: | ||
238 | gpio_free(gpios[i].gpio); | ||
239 | undo: | ||
240 | snd_soc_jack_free_gpios(jack, i, gpios); | ||
241 | |||
242 | return ret; | ||
243 | } | ||
244 | EXPORT_SYMBOL_GPL(snd_soc_jack_add_gpios); | ||
245 | |||
246 | /** | ||
247 | * snd_soc_jack_free_gpios - Release GPIO pins' resources of an ASoC jack | ||
248 | * | ||
249 | * @jack: ASoC jack | ||
250 | * @count: number of pins | ||
251 | * @gpios: array of gpio pins | ||
252 | * | ||
253 | * Release gpio and irq resources for gpio pins associated with an ASoC jack. | ||
254 | */ | ||
255 | void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count, | ||
256 | struct snd_soc_jack_gpio *gpios) | ||
257 | { | ||
258 | int i; | ||
259 | |||
260 | for (i = 0; i < count; i++) { | ||
261 | free_irq(gpio_to_irq(gpios[i].gpio), &gpios[i]); | ||
262 | gpio_free(gpios[i].gpio); | ||
263 | gpios[i].jack = NULL; | ||
264 | } | ||
265 | } | ||
266 | EXPORT_SYMBOL_GPL(snd_soc_jack_free_gpios); | ||
267 | #endif /* CONFIG_GPIOLIB */ | ||
diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c index f87933e48812..574af56ba8a6 100644 --- a/sound/sparc/amd7930.c +++ b/sound/sparc/amd7930.c | |||
@@ -954,7 +954,8 @@ static int __devinit snd_amd7930_create(struct snd_card *card, | |||
954 | amd->regs = of_ioremap(&op->resource[0], 0, | 954 | amd->regs = of_ioremap(&op->resource[0], 0, |
955 | resource_size(&op->resource[0]), "amd7930"); | 955 | resource_size(&op->resource[0]), "amd7930"); |
956 | if (!amd->regs) { | 956 | if (!amd->regs) { |
957 | snd_printk("amd7930-%d: Unable to map chip registers.\n", dev); | 957 | snd_printk(KERN_ERR |
958 | "amd7930-%d: Unable to map chip registers.\n", dev); | ||
958 | return -EIO; | 959 | return -EIO; |
959 | } | 960 | } |
960 | 961 | ||
@@ -962,7 +963,7 @@ static int __devinit snd_amd7930_create(struct snd_card *card, | |||
962 | 963 | ||
963 | if (request_irq(irq, snd_amd7930_interrupt, | 964 | if (request_irq(irq, snd_amd7930_interrupt, |
964 | IRQF_DISABLED | IRQF_SHARED, "amd7930", amd)) { | 965 | IRQF_DISABLED | IRQF_SHARED, "amd7930", amd)) { |
965 | snd_printk("amd7930-%d: Unable to grab IRQ %d\n", | 966 | snd_printk(KERN_ERR "amd7930-%d: Unable to grab IRQ %d\n", |
966 | dev, irq); | 967 | dev, irq); |
967 | snd_amd7930_free(amd); | 968 | snd_amd7930_free(amd); |
968 | return -EBUSY; | 969 | return -EBUSY; |
@@ -1018,9 +1019,10 @@ static int __devinit amd7930_sbus_probe(struct of_device *op, const struct of_de | |||
1018 | return -ENOENT; | 1019 | return -ENOENT; |
1019 | } | 1020 | } |
1020 | 1021 | ||
1021 | card = snd_card_new(index[dev_num], id[dev_num], THIS_MODULE, 0); | 1022 | err = snd_card_create(index[dev_num], id[dev_num], THIS_MODULE, 0, |
1022 | if (card == NULL) | 1023 | &card); |
1023 | return -ENOMEM; | 1024 | if (err < 0) |
1025 | return err; | ||
1024 | 1026 | ||
1025 | strcpy(card->driver, "AMD7930"); | 1027 | strcpy(card->driver, "AMD7930"); |
1026 | strcpy(card->shortname, "Sun AMD7930"); | 1028 | strcpy(card->shortname, "Sun AMD7930"); |
diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c index 41c387587474..7d93fa705ccf 100644 --- a/sound/sparc/cs4231.c +++ b/sound/sparc/cs4231.c | |||
@@ -1563,6 +1563,7 @@ static int __init cs4231_attach_begin(struct snd_card **rcard) | |||
1563 | { | 1563 | { |
1564 | struct snd_card *card; | 1564 | struct snd_card *card; |
1565 | struct snd_cs4231 *chip; | 1565 | struct snd_cs4231 *chip; |
1566 | int err; | ||
1566 | 1567 | ||
1567 | *rcard = NULL; | 1568 | *rcard = NULL; |
1568 | 1569 | ||
@@ -1574,10 +1575,10 @@ static int __init cs4231_attach_begin(struct snd_card **rcard) | |||
1574 | return -ENOENT; | 1575 | return -ENOENT; |
1575 | } | 1576 | } |
1576 | 1577 | ||
1577 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, | 1578 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, |
1578 | sizeof(struct snd_cs4231)); | 1579 | sizeof(struct snd_cs4231), &card); |
1579 | if (card == NULL) | 1580 | if (err < 0) |
1580 | return -ENOMEM; | 1581 | return err; |
1581 | 1582 | ||
1582 | strcpy(card->driver, "CS4231"); | 1583 | strcpy(card->driver, "CS4231"); |
1583 | strcpy(card->shortname, "Sun CS4231"); | 1584 | strcpy(card->shortname, "Sun CS4231"); |
diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c index 23ed6f04a718..af95ff1e126c 100644 --- a/sound/sparc/dbri.c +++ b/sound/sparc/dbri.c | |||
@@ -2612,10 +2612,10 @@ static int __devinit dbri_probe(struct of_device *op, const struct of_device_id | |||
2612 | return -ENODEV; | 2612 | return -ENODEV; |
2613 | } | 2613 | } |
2614 | 2614 | ||
2615 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, | 2615 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, |
2616 | sizeof(struct snd_dbri)); | 2616 | sizeof(struct snd_dbri), &card); |
2617 | if (card == NULL) | 2617 | if (err < 0) |
2618 | return -ENOMEM; | 2618 | return err; |
2619 | 2619 | ||
2620 | strcpy(card->driver, "DBRI"); | 2620 | strcpy(card->driver, "DBRI"); |
2621 | strcpy(card->shortname, "Sun DBRI"); | 2621 | strcpy(card->shortname, "Sun DBRI"); |
diff --git a/sound/spi/at73c213.c b/sound/spi/at73c213.c index 09802e8a6fb8..4c7b051f9d17 100644 --- a/sound/spi/at73c213.c +++ b/sound/spi/at73c213.c | |||
@@ -965,12 +965,11 @@ static int __devinit snd_at73c213_probe(struct spi_device *spi) | |||
965 | return PTR_ERR(board->dac_clk); | 965 | return PTR_ERR(board->dac_clk); |
966 | } | 966 | } |
967 | 967 | ||
968 | retval = -ENOMEM; | ||
969 | |||
970 | /* Allocate "card" using some unused identifiers. */ | 968 | /* Allocate "card" using some unused identifiers. */ |
971 | snprintf(id, sizeof id, "at73c213_%d", board->ssc_id); | 969 | snprintf(id, sizeof id, "at73c213_%d", board->ssc_id); |
972 | card = snd_card_new(-1, id, THIS_MODULE, sizeof(struct snd_at73c213)); | 970 | retval = snd_card_create(-1, id, THIS_MODULE, |
973 | if (!card) | 971 | sizeof(struct snd_at73c213), &card); |
972 | if (retval < 0) | ||
974 | goto out; | 973 | goto out; |
975 | 974 | ||
976 | chip = card->private_data; | 975 | chip = card->private_data; |
diff --git a/sound/synth/emux/emux_hwdep.c b/sound/synth/emux/emux_hwdep.c index 0a5391436add..ff0b2a8fd25b 100644 --- a/sound/synth/emux/emux_hwdep.c +++ b/sound/synth/emux/emux_hwdep.c | |||
@@ -24,25 +24,6 @@ | |||
24 | #include <asm/uaccess.h> | 24 | #include <asm/uaccess.h> |
25 | #include "emux_voice.h" | 25 | #include "emux_voice.h" |
26 | 26 | ||
27 | /* | ||
28 | * open the hwdep device | ||
29 | */ | ||
30 | static int | ||
31 | snd_emux_hwdep_open(struct snd_hwdep *hw, struct file *file) | ||
32 | { | ||
33 | return 0; | ||
34 | } | ||
35 | |||
36 | |||
37 | /* | ||
38 | * close the device | ||
39 | */ | ||
40 | static int | ||
41 | snd_emux_hwdep_release(struct snd_hwdep *hw, struct file *file) | ||
42 | { | ||
43 | return 0; | ||
44 | } | ||
45 | |||
46 | 27 | ||
47 | #define TMP_CLIENT_ID 0x1001 | 28 | #define TMP_CLIENT_ID 0x1001 |
48 | 29 | ||
@@ -146,8 +127,6 @@ snd_emux_init_hwdep(struct snd_emux *emu) | |||
146 | emu->hwdep = hw; | 127 | emu->hwdep = hw; |
147 | strcpy(hw->name, SNDRV_EMUX_HWDEP_NAME); | 128 | strcpy(hw->name, SNDRV_EMUX_HWDEP_NAME); |
148 | hw->iface = SNDRV_HWDEP_IFACE_EMUX_WAVETABLE; | 129 | hw->iface = SNDRV_HWDEP_IFACE_EMUX_WAVETABLE; |
149 | hw->ops.open = snd_emux_hwdep_open; | ||
150 | hw->ops.release = snd_emux_hwdep_release; | ||
151 | hw->ops.ioctl = snd_emux_hwdep_ioctl; | 130 | hw->ops.ioctl = snd_emux_hwdep_ioctl; |
152 | hw->exclusive = 1; | 131 | hw->exclusive = 1; |
153 | hw->private_data = emu; | 132 | hw->private_data = emu; |
diff --git a/sound/synth/emux/emux_oss.c b/sound/synth/emux/emux_oss.c index 5c47b6c09264..87e42206c4ef 100644 --- a/sound/synth/emux/emux_oss.c +++ b/sound/synth/emux/emux_oss.c | |||
@@ -132,7 +132,7 @@ snd_emux_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure) | |||
132 | p = snd_emux_create_port(emu, tmpname, 32, | 132 | p = snd_emux_create_port(emu, tmpname, 32, |
133 | 1, &callback); | 133 | 1, &callback); |
134 | if (p == NULL) { | 134 | if (p == NULL) { |
135 | snd_printk("can't create port\n"); | 135 | snd_printk(KERN_ERR "can't create port\n"); |
136 | snd_emux_dec_count(emu); | 136 | snd_emux_dec_count(emu); |
137 | mutex_unlock(&emu->register_mutex); | 137 | mutex_unlock(&emu->register_mutex); |
138 | return -ENOMEM; | 138 | return -ENOMEM; |
diff --git a/sound/synth/emux/emux_seq.c b/sound/synth/emux/emux_seq.c index 335aa2ce2574..ca5f7effb4df 100644 --- a/sound/synth/emux/emux_seq.c +++ b/sound/synth/emux/emux_seq.c | |||
@@ -74,15 +74,15 @@ snd_emux_init_seq(struct snd_emux *emu, struct snd_card *card, int index) | |||
74 | emu->client = snd_seq_create_kernel_client(card, index, | 74 | emu->client = snd_seq_create_kernel_client(card, index, |
75 | "%s WaveTable", emu->name); | 75 | "%s WaveTable", emu->name); |
76 | if (emu->client < 0) { | 76 | if (emu->client < 0) { |
77 | snd_printk("can't create client\n"); | 77 | snd_printk(KERN_ERR "can't create client\n"); |
78 | return -ENODEV; | 78 | return -ENODEV; |
79 | } | 79 | } |
80 | 80 | ||
81 | if (emu->num_ports < 0) { | 81 | if (emu->num_ports < 0) { |
82 | snd_printk("seqports must be greater than zero\n"); | 82 | snd_printk(KERN_WARNING "seqports must be greater than zero\n"); |
83 | emu->num_ports = 1; | 83 | emu->num_ports = 1; |
84 | } else if (emu->num_ports >= SNDRV_EMUX_MAX_PORTS) { | 84 | } else if (emu->num_ports >= SNDRV_EMUX_MAX_PORTS) { |
85 | snd_printk("too many ports." | 85 | snd_printk(KERN_WARNING "too many ports." |
86 | "limited max. ports %d\n", SNDRV_EMUX_MAX_PORTS); | 86 | "limited max. ports %d\n", SNDRV_EMUX_MAX_PORTS); |
87 | emu->num_ports = SNDRV_EMUX_MAX_PORTS; | 87 | emu->num_ports = SNDRV_EMUX_MAX_PORTS; |
88 | } | 88 | } |
@@ -100,7 +100,7 @@ snd_emux_init_seq(struct snd_emux *emu, struct snd_card *card, int index) | |||
100 | p = snd_emux_create_port(emu, tmpname, MIDI_CHANNELS, | 100 | p = snd_emux_create_port(emu, tmpname, MIDI_CHANNELS, |
101 | 0, &pinfo); | 101 | 0, &pinfo); |
102 | if (p == NULL) { | 102 | if (p == NULL) { |
103 | snd_printk("can't create port\n"); | 103 | snd_printk(KERN_ERR "can't create port\n"); |
104 | return -ENOMEM; | 104 | return -ENOMEM; |
105 | } | 105 | } |
106 | 106 | ||
@@ -147,12 +147,12 @@ snd_emux_create_port(struct snd_emux *emu, char *name, | |||
147 | 147 | ||
148 | /* Allocate structures for this channel */ | 148 | /* Allocate structures for this channel */ |
149 | if ((p = kzalloc(sizeof(*p), GFP_KERNEL)) == NULL) { | 149 | if ((p = kzalloc(sizeof(*p), GFP_KERNEL)) == NULL) { |
150 | snd_printk("no memory\n"); | 150 | snd_printk(KERN_ERR "no memory\n"); |
151 | return NULL; | 151 | return NULL; |
152 | } | 152 | } |
153 | p->chset.channels = kcalloc(max_channels, sizeof(struct snd_midi_channel), GFP_KERNEL); | 153 | p->chset.channels = kcalloc(max_channels, sizeof(struct snd_midi_channel), GFP_KERNEL); |
154 | if (p->chset.channels == NULL) { | 154 | if (p->chset.channels == NULL) { |
155 | snd_printk("no memory\n"); | 155 | snd_printk(KERN_ERR "no memory\n"); |
156 | kfree(p); | 156 | kfree(p); |
157 | return NULL; | 157 | return NULL; |
158 | } | 158 | } |
@@ -376,12 +376,12 @@ int snd_emux_init_virmidi(struct snd_emux *emu, struct snd_card *card) | |||
376 | goto __error; | 376 | goto __error; |
377 | } | 377 | } |
378 | emu->vmidi[i] = rmidi; | 378 | emu->vmidi[i] = rmidi; |
379 | //snd_printk("virmidi %d ok\n", i); | 379 | /* snd_printk(KERN_DEBUG "virmidi %d ok\n", i); */ |
380 | } | 380 | } |
381 | return 0; | 381 | return 0; |
382 | 382 | ||
383 | __error: | 383 | __error: |
384 | //snd_printk("error init..\n"); | 384 | /* snd_printk(KERN_DEBUG "error init..\n"); */ |
385 | snd_emux_delete_virmidi(emu); | 385 | snd_emux_delete_virmidi(emu); |
386 | return -ENOMEM; | 386 | return -ENOMEM; |
387 | } | 387 | } |
diff --git a/sound/synth/emux/emux_synth.c b/sound/synth/emux/emux_synth.c index 2cc6f6f79065..3e921b386fd5 100644 --- a/sound/synth/emux/emux_synth.c +++ b/sound/synth/emux/emux_synth.c | |||
@@ -956,7 +956,8 @@ void snd_emux_lock_voice(struct snd_emux *emu, int voice) | |||
956 | if (emu->voices[voice].state == SNDRV_EMUX_ST_OFF) | 956 | if (emu->voices[voice].state == SNDRV_EMUX_ST_OFF) |
957 | emu->voices[voice].state = SNDRV_EMUX_ST_LOCKED; | 957 | emu->voices[voice].state = SNDRV_EMUX_ST_LOCKED; |
958 | else | 958 | else |
959 | snd_printk("invalid voice for lock %d (state = %x)\n", | 959 | snd_printk(KERN_WARNING |
960 | "invalid voice for lock %d (state = %x)\n", | ||
960 | voice, emu->voices[voice].state); | 961 | voice, emu->voices[voice].state); |
961 | spin_unlock_irqrestore(&emu->voice_lock, flags); | 962 | spin_unlock_irqrestore(&emu->voice_lock, flags); |
962 | } | 963 | } |
@@ -973,7 +974,8 @@ void snd_emux_unlock_voice(struct snd_emux *emu, int voice) | |||
973 | if (emu->voices[voice].state == SNDRV_EMUX_ST_LOCKED) | 974 | if (emu->voices[voice].state == SNDRV_EMUX_ST_LOCKED) |
974 | emu->voices[voice].state = SNDRV_EMUX_ST_OFF; | 975 | emu->voices[voice].state = SNDRV_EMUX_ST_OFF; |
975 | else | 976 | else |
976 | snd_printk("invalid voice for unlock %d (state = %x)\n", | 977 | snd_printk(KERN_WARNING |
978 | "invalid voice for unlock %d (state = %x)\n", | ||
977 | voice, emu->voices[voice].state); | 979 | voice, emu->voices[voice].state); |
978 | spin_unlock_irqrestore(&emu->voice_lock, flags); | 980 | spin_unlock_irqrestore(&emu->voice_lock, flags); |
979 | } | 981 | } |
diff --git a/sound/synth/emux/soundfont.c b/sound/synth/emux/soundfont.c index 36d53bd317ed..63c8f45c0c22 100644 --- a/sound/synth/emux/soundfont.c +++ b/sound/synth/emux/soundfont.c | |||
@@ -133,7 +133,7 @@ snd_soundfont_load(struct snd_sf_list *sflist, const void __user *data, | |||
133 | int rc; | 133 | int rc; |
134 | 134 | ||
135 | if (count < (long)sizeof(patch)) { | 135 | if (count < (long)sizeof(patch)) { |
136 | snd_printk("patch record too small %ld\n", count); | 136 | snd_printk(KERN_ERR "patch record too small %ld\n", count); |
137 | return -EINVAL; | 137 | return -EINVAL; |
138 | } | 138 | } |
139 | if (copy_from_user(&patch, data, sizeof(patch))) | 139 | if (copy_from_user(&patch, data, sizeof(patch))) |
@@ -143,15 +143,16 @@ snd_soundfont_load(struct snd_sf_list *sflist, const void __user *data, | |||
143 | data += sizeof(patch); | 143 | data += sizeof(patch); |
144 | 144 | ||
145 | if (patch.key != SNDRV_OSS_SOUNDFONT_PATCH) { | 145 | if (patch.key != SNDRV_OSS_SOUNDFONT_PATCH) { |
146 | snd_printk("'The wrong kind of patch' %x\n", patch.key); | 146 | snd_printk(KERN_ERR "The wrong kind of patch %x\n", patch.key); |
147 | return -EINVAL; | 147 | return -EINVAL; |
148 | } | 148 | } |
149 | if (count < patch.len) { | 149 | if (count < patch.len) { |
150 | snd_printk("Patch too short %ld, need %d\n", count, patch.len); | 150 | snd_printk(KERN_ERR "Patch too short %ld, need %d\n", |
151 | count, patch.len); | ||
151 | return -EINVAL; | 152 | return -EINVAL; |
152 | } | 153 | } |
153 | if (patch.len < 0) { | 154 | if (patch.len < 0) { |
154 | snd_printk("poor length %d\n", patch.len); | 155 | snd_printk(KERN_ERR "poor length %d\n", patch.len); |
155 | return -EINVAL; | 156 | return -EINVAL; |
156 | } | 157 | } |
157 | 158 | ||
@@ -195,7 +196,8 @@ snd_soundfont_load(struct snd_sf_list *sflist, const void __user *data, | |||
195 | case SNDRV_SFNT_REMOVE_INFO: | 196 | case SNDRV_SFNT_REMOVE_INFO: |
196 | /* patch must be opened */ | 197 | /* patch must be opened */ |
197 | if (!sflist->currsf) { | 198 | if (!sflist->currsf) { |
198 | snd_printk("soundfont: remove_info: patch not opened\n"); | 199 | snd_printk(KERN_ERR "soundfont: remove_info: " |
200 | "patch not opened\n"); | ||
199 | rc = -EINVAL; | 201 | rc = -EINVAL; |
200 | } else { | 202 | } else { |
201 | int bank, instr; | 203 | int bank, instr; |
@@ -531,7 +533,7 @@ load_info(struct snd_sf_list *sflist, const void __user *data, long count) | |||
531 | return -EINVAL; | 533 | return -EINVAL; |
532 | 534 | ||
533 | if (count < (long)sizeof(hdr)) { | 535 | if (count < (long)sizeof(hdr)) { |
534 | printk("Soundfont error: invalid patch zone length\n"); | 536 | printk(KERN_ERR "Soundfont error: invalid patch zone length\n"); |
535 | return -EINVAL; | 537 | return -EINVAL; |
536 | } | 538 | } |
537 | if (copy_from_user((char*)&hdr, data, sizeof(hdr))) | 539 | if (copy_from_user((char*)&hdr, data, sizeof(hdr))) |
@@ -541,12 +543,14 @@ load_info(struct snd_sf_list *sflist, const void __user *data, long count) | |||
541 | count -= sizeof(hdr); | 543 | count -= sizeof(hdr); |
542 | 544 | ||
543 | if (hdr.nvoices <= 0 || hdr.nvoices >= 100) { | 545 | if (hdr.nvoices <= 0 || hdr.nvoices >= 100) { |
544 | printk("Soundfont error: Illegal voice number %d\n", hdr.nvoices); | 546 | printk(KERN_ERR "Soundfont error: Illegal voice number %d\n", |
547 | hdr.nvoices); | ||
545 | return -EINVAL; | 548 | return -EINVAL; |
546 | } | 549 | } |
547 | 550 | ||
548 | if (count < (long)sizeof(struct soundfont_voice_info) * hdr.nvoices) { | 551 | if (count < (long)sizeof(struct soundfont_voice_info) * hdr.nvoices) { |
549 | printk("Soundfont Error: patch length(%ld) is smaller than nvoices(%d)\n", | 552 | printk(KERN_ERR "Soundfont Error: " |
553 | "patch length(%ld) is smaller than nvoices(%d)\n", | ||
550 | count, hdr.nvoices); | 554 | count, hdr.nvoices); |
551 | return -EINVAL; | 555 | return -EINVAL; |
552 | } | 556 | } |
@@ -952,7 +956,7 @@ load_guspatch(struct snd_sf_list *sflist, const char __user *data, | |||
952 | int rc; | 956 | int rc; |
953 | 957 | ||
954 | if (count < (long)sizeof(patch)) { | 958 | if (count < (long)sizeof(patch)) { |
955 | snd_printk("patch record too small %ld\n", count); | 959 | snd_printk(KERN_ERR "patch record too small %ld\n", count); |
956 | return -EINVAL; | 960 | return -EINVAL; |
957 | } | 961 | } |
958 | if (copy_from_user(&patch, data, sizeof(patch))) | 962 | if (copy_from_user(&patch, data, sizeof(patch))) |
@@ -1034,7 +1038,8 @@ load_guspatch(struct snd_sf_list *sflist, const char __user *data, | |||
1034 | /* panning position; -128 - 127 => 0-127 */ | 1038 | /* panning position; -128 - 127 => 0-127 */ |
1035 | zone->v.pan = (patch.panning + 128) / 2; | 1039 | zone->v.pan = (patch.panning + 128) / 2; |
1036 | #if 0 | 1040 | #if 0 |
1037 | snd_printk("gus: basefrq=%d (ofs=%d) root=%d,tune=%d, range:%d-%d\n", | 1041 | snd_printk(KERN_DEBUG |
1042 | "gus: basefrq=%d (ofs=%d) root=%d,tune=%d, range:%d-%d\n", | ||
1038 | (int)patch.base_freq, zone->v.rate_offset, | 1043 | (int)patch.base_freq, zone->v.rate_offset, |
1039 | zone->v.root, zone->v.tune, zone->v.low, zone->v.high); | 1044 | zone->v.root, zone->v.tune, zone->v.low, zone->v.high); |
1040 | #endif | 1045 | #endif |
@@ -1068,7 +1073,8 @@ load_guspatch(struct snd_sf_list *sflist, const char __user *data, | |||
1068 | zone->v.parm.volrelease = 0x8000 | snd_sf_calc_parm_decay(release); | 1073 | zone->v.parm.volrelease = 0x8000 | snd_sf_calc_parm_decay(release); |
1069 | zone->v.attenuation = calc_gus_attenuation(patch.env_offset[0]); | 1074 | zone->v.attenuation = calc_gus_attenuation(patch.env_offset[0]); |
1070 | #if 0 | 1075 | #if 0 |
1071 | snd_printk("gus: atkhld=%x, dcysus=%x, volrel=%x, att=%d\n", | 1076 | snd_printk(KERN_DEBUG |
1077 | "gus: atkhld=%x, dcysus=%x, volrel=%x, att=%d\n", | ||
1072 | zone->v.parm.volatkhld, | 1078 | zone->v.parm.volatkhld, |
1073 | zone->v.parm.voldcysus, | 1079 | zone->v.parm.voldcysus, |
1074 | zone->v.parm.volrelease, | 1080 | zone->v.parm.volrelease, |
diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig index 4f0eac9bff1e..523aec188ccf 100644 --- a/sound/usb/Kconfig +++ b/sound/usb/Kconfig | |||
@@ -48,7 +48,10 @@ config SND_USB_CAIAQ | |||
48 | * Native Instruments Kore Controller | 48 | * Native Instruments Kore Controller |
49 | * Native Instruments Kore Controller 2 | 49 | * Native Instruments Kore Controller 2 |
50 | * Native Instruments Audio Kontrol 1 | 50 | * Native Instruments Audio Kontrol 1 |
51 | * Native Instruments Audio 4 DJ | ||
51 | * Native Instruments Audio 8 DJ | 52 | * Native Instruments Audio 8 DJ |
53 | * Native Instruments Guitar Rig Session I/O | ||
54 | * Native Instruments Guitar Rig mobile | ||
52 | 55 | ||
53 | To compile this driver as a module, choose M here: the module | 56 | To compile this driver as a module, choose M here: the module |
54 | will be called snd-usb-caiaq. | 57 | will be called snd-usb-caiaq. |
diff --git a/sound/usb/caiaq/caiaq-audio.c b/sound/usb/caiaq/caiaq-audio.c index b3a603325835..08d51e0c9fea 100644 --- a/sound/usb/caiaq/caiaq-audio.c +++ b/sound/usb/caiaq/caiaq-audio.c | |||
@@ -114,6 +114,7 @@ static int stream_start(struct snd_usb_caiaqdev *dev) | |||
114 | dev->output_panic = 0; | 114 | dev->output_panic = 0; |
115 | dev->first_packet = 1; | 115 | dev->first_packet = 1; |
116 | dev->streaming = 1; | 116 | dev->streaming = 1; |
117 | dev->warned = 0; | ||
117 | 118 | ||
118 | for (i = 0; i < N_URBS; i++) { | 119 | for (i = 0; i < N_URBS; i++) { |
119 | ret = usb_submit_urb(dev->data_urbs_in[i], GFP_ATOMIC); | 120 | ret = usb_submit_urb(dev->data_urbs_in[i], GFP_ATOMIC); |
@@ -376,6 +377,9 @@ static void read_in_urb_mode2(struct snd_usb_caiaqdev *dev, | |||
376 | 377 | ||
377 | for (stream = 0; stream < dev->n_streams; stream++, i++) { | 378 | for (stream = 0; stream < dev->n_streams; stream++, i++) { |
378 | sub = dev->sub_capture[stream]; | 379 | sub = dev->sub_capture[stream]; |
380 | if (dev->input_panic) | ||
381 | usb_buf[i] = 0; | ||
382 | |||
379 | if (sub) { | 383 | if (sub) { |
380 | struct snd_pcm_runtime *rt = sub->runtime; | 384 | struct snd_pcm_runtime *rt = sub->runtime; |
381 | char *audio_buf = rt->dma_area; | 385 | char *audio_buf = rt->dma_area; |
@@ -397,6 +401,9 @@ static void read_in_urb(struct snd_usb_caiaqdev *dev, | |||
397 | if (!dev->streaming) | 401 | if (!dev->streaming) |
398 | return; | 402 | return; |
399 | 403 | ||
404 | if (iso->actual_length < dev->bpp) | ||
405 | return; | ||
406 | |||
400 | switch (dev->spec.data_alignment) { | 407 | switch (dev->spec.data_alignment) { |
401 | case 0: | 408 | case 0: |
402 | read_in_urb_mode0(dev, urb, iso); | 409 | read_in_urb_mode0(dev, urb, iso); |
@@ -406,10 +413,11 @@ static void read_in_urb(struct snd_usb_caiaqdev *dev, | |||
406 | break; | 413 | break; |
407 | } | 414 | } |
408 | 415 | ||
409 | if (dev->input_panic || dev->output_panic) { | 416 | if ((dev->input_panic || dev->output_panic) && !dev->warned) { |
410 | debug("streaming error detected %s %s\n", | 417 | debug("streaming error detected %s %s\n", |
411 | dev->input_panic ? "(input)" : "", | 418 | dev->input_panic ? "(input)" : "", |
412 | dev->output_panic ? "(output)" : ""); | 419 | dev->output_panic ? "(output)" : ""); |
420 | dev->warned = 1; | ||
413 | } | 421 | } |
414 | } | 422 | } |
415 | 423 | ||
@@ -638,9 +646,10 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev) | |||
638 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1): | 646 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1): |
639 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3): | 647 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3): |
640 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_SESSIONIO): | 648 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_SESSIONIO): |
641 | dev->samplerates |= SNDRV_PCM_RATE_88200; | 649 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_GUITARRIGMOBILE): |
642 | dev->samplerates |= SNDRV_PCM_RATE_192000; | 650 | dev->samplerates |= SNDRV_PCM_RATE_192000; |
643 | break; | 651 | /* fall thru */ |
652 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ): | ||
644 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ): | 653 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ): |
645 | dev->samplerates |= SNDRV_PCM_RATE_88200; | 654 | dev->samplerates |= SNDRV_PCM_RATE_88200; |
646 | break; | 655 | break; |
diff --git a/sound/usb/caiaq/caiaq-control.c b/sound/usb/caiaq/caiaq-control.c index ccd763dd7167..e92c2bbf4fe9 100644 --- a/sound/usb/caiaq/caiaq-control.c +++ b/sound/usb/caiaq/caiaq-control.c | |||
@@ -39,12 +39,12 @@ static int control_info(struct snd_kcontrol *kcontrol, | |||
39 | struct snd_usb_caiaqdev *dev = caiaqdev(chip->card); | 39 | struct snd_usb_caiaqdev *dev = caiaqdev(chip->card); |
40 | int pos = kcontrol->private_value; | 40 | int pos = kcontrol->private_value; |
41 | int is_intval = pos & CNT_INTVAL; | 41 | int is_intval = pos & CNT_INTVAL; |
42 | unsigned int id = dev->chip.usb_id; | ||
42 | 43 | ||
43 | uinfo->count = 1; | 44 | uinfo->count = 1; |
44 | pos &= ~CNT_INTVAL; | 45 | pos &= ~CNT_INTVAL; |
45 | 46 | ||
46 | if (dev->chip.usb_id == | 47 | if (id == USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ) |
47 | USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ) | ||
48 | && (pos == 0)) { | 48 | && (pos == 0)) { |
49 | /* current input mode of A8DJ */ | 49 | /* current input mode of A8DJ */ |
50 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | 50 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
@@ -53,6 +53,15 @@ static int control_info(struct snd_kcontrol *kcontrol, | |||
53 | return 0; | 53 | return 0; |
54 | } | 54 | } |
55 | 55 | ||
56 | if (id == USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ) | ||
57 | && (pos == 0)) { | ||
58 | /* current input mode of A4DJ */ | ||
59 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
60 | uinfo->value.integer.min = 0; | ||
61 | uinfo->value.integer.max = 1; | ||
62 | return 0; | ||
63 | } | ||
64 | |||
56 | if (is_intval) { | 65 | if (is_intval) { |
57 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | 66 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
58 | uinfo->value.integer.min = 0; | 67 | uinfo->value.integer.min = 0; |
@@ -73,6 +82,14 @@ static int control_get(struct snd_kcontrol *kcontrol, | |||
73 | struct snd_usb_caiaqdev *dev = caiaqdev(chip->card); | 82 | struct snd_usb_caiaqdev *dev = caiaqdev(chip->card); |
74 | int pos = kcontrol->private_value; | 83 | int pos = kcontrol->private_value; |
75 | 84 | ||
85 | if (dev->chip.usb_id == | ||
86 | USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ)) { | ||
87 | /* A4DJ has only one control */ | ||
88 | /* do not expose hardware input mode 0 */ | ||
89 | ucontrol->value.integer.value[0] = dev->control_state[0] - 1; | ||
90 | return 0; | ||
91 | } | ||
92 | |||
76 | if (pos & CNT_INTVAL) | 93 | if (pos & CNT_INTVAL) |
77 | ucontrol->value.integer.value[0] | 94 | ucontrol->value.integer.value[0] |
78 | = dev->control_state[pos & ~CNT_INTVAL]; | 95 | = dev->control_state[pos & ~CNT_INTVAL]; |
@@ -90,10 +107,20 @@ static int control_put(struct snd_kcontrol *kcontrol, | |||
90 | struct snd_usb_caiaqdev *dev = caiaqdev(chip->card); | 107 | struct snd_usb_caiaqdev *dev = caiaqdev(chip->card); |
91 | int pos = kcontrol->private_value; | 108 | int pos = kcontrol->private_value; |
92 | 109 | ||
110 | if (dev->chip.usb_id == | ||
111 | USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ)) { | ||
112 | /* A4DJ has only one control */ | ||
113 | /* do not expose hardware input mode 0 */ | ||
114 | dev->control_state[0] = ucontrol->value.integer.value[0] + 1; | ||
115 | snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO, | ||
116 | dev->control_state, sizeof(dev->control_state)); | ||
117 | return 1; | ||
118 | } | ||
119 | |||
93 | if (pos & CNT_INTVAL) { | 120 | if (pos & CNT_INTVAL) { |
94 | dev->control_state[pos & ~CNT_INTVAL] | 121 | dev->control_state[pos & ~CNT_INTVAL] |
95 | = ucontrol->value.integer.value[0]; | 122 | = ucontrol->value.integer.value[0]; |
96 | snd_usb_caiaq_send_command(dev, EP1_CMD_DIMM_LEDS, | 123 | snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO, |
97 | dev->control_state, sizeof(dev->control_state)); | 124 | dev->control_state, sizeof(dev->control_state)); |
98 | } else { | 125 | } else { |
99 | if (ucontrol->value.integer.value[0]) | 126 | if (ucontrol->value.integer.value[0]) |
@@ -243,10 +270,13 @@ static struct caiaq_controller a8dj_controller[] = { | |||
243 | { "GND lift for TC Vinyl mode", 24 + 0 }, | 270 | { "GND lift for TC Vinyl mode", 24 + 0 }, |
244 | { "GND lift for TC CD/Line mode", 24 + 1 }, | 271 | { "GND lift for TC CD/Line mode", 24 + 1 }, |
245 | { "GND lift for phono mode", 24 + 2 }, | 272 | { "GND lift for phono mode", 24 + 2 }, |
246 | { "GND lift for TC Vinyl mode", 24 + 3 }, | ||
247 | { "Software lock", 40 } | 273 | { "Software lock", 40 } |
248 | }; | 274 | }; |
249 | 275 | ||
276 | static struct caiaq_controller a4dj_controller[] = { | ||
277 | { "Current input mode", 0 | CNT_INTVAL } | ||
278 | }; | ||
279 | |||
250 | static int __devinit add_controls(struct caiaq_controller *c, int num, | 280 | static int __devinit add_controls(struct caiaq_controller *c, int num, |
251 | struct snd_usb_caiaqdev *dev) | 281 | struct snd_usb_caiaqdev *dev) |
252 | { | 282 | { |
@@ -295,6 +325,10 @@ int __devinit snd_usb_caiaq_control_init(struct snd_usb_caiaqdev *dev) | |||
295 | ret = add_controls(a8dj_controller, | 325 | ret = add_controls(a8dj_controller, |
296 | ARRAY_SIZE(a8dj_controller), dev); | 326 | ARRAY_SIZE(a8dj_controller), dev); |
297 | break; | 327 | break; |
328 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ): | ||
329 | ret = add_controls(a4dj_controller, | ||
330 | ARRAY_SIZE(a4dj_controller), dev); | ||
331 | break; | ||
298 | } | 332 | } |
299 | 333 | ||
300 | return ret; | 334 | return ret; |
diff --git a/sound/usb/caiaq/caiaq-device.c b/sound/usb/caiaq/caiaq-device.c index 41c36b055f6b..cf573a982fdc 100644 --- a/sound/usb/caiaq/caiaq-device.c +++ b/sound/usb/caiaq/caiaq-device.c | |||
@@ -42,15 +42,17 @@ | |||
42 | #endif | 42 | #endif |
43 | 43 | ||
44 | MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); | 44 | MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); |
45 | MODULE_DESCRIPTION("caiaq USB audio, version 1.3.10"); | 45 | MODULE_DESCRIPTION("caiaq USB audio, version 1.3.13"); |
46 | MODULE_LICENSE("GPL"); | 46 | MODULE_LICENSE("GPL"); |
47 | MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2}," | 47 | MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2}," |
48 | "{Native Instruments, RigKontrol3}," | 48 | "{Native Instruments, RigKontrol3}," |
49 | "{Native Instruments, Kore Controller}," | 49 | "{Native Instruments, Kore Controller}," |
50 | "{Native Instruments, Kore Controller 2}," | 50 | "{Native Instruments, Kore Controller 2}," |
51 | "{Native Instruments, Audio Kontrol 1}," | 51 | "{Native Instruments, Audio Kontrol 1}," |
52 | "{Native Instruments, Audio 4 DJ}," | ||
52 | "{Native Instruments, Audio 8 DJ}," | 53 | "{Native Instruments, Audio 8 DJ}," |
53 | "{Native Instruments, Session I/O}}"); | 54 | "{Native Instruments, Session I/O}," |
55 | "{Native Instruments, GuitarRig mobile}"); | ||
54 | 56 | ||
55 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */ | 57 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */ |
56 | static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for this card */ | 58 | static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for this card */ |
@@ -116,6 +118,16 @@ static struct usb_device_id snd_usb_id_table[] = { | |||
116 | .idVendor = USB_VID_NATIVEINSTRUMENTS, | 118 | .idVendor = USB_VID_NATIVEINSTRUMENTS, |
117 | .idProduct = USB_PID_SESSIONIO | 119 | .idProduct = USB_PID_SESSIONIO |
118 | }, | 120 | }, |
121 | { | ||
122 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE, | ||
123 | .idVendor = USB_VID_NATIVEINSTRUMENTS, | ||
124 | .idProduct = USB_PID_GUITARRIGMOBILE | ||
125 | }, | ||
126 | { | ||
127 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE, | ||
128 | .idVendor = USB_VID_NATIVEINSTRUMENTS, | ||
129 | .idProduct = USB_PID_AUDIO4DJ | ||
130 | }, | ||
119 | { /* terminator */ } | 131 | { /* terminator */ } |
120 | }; | 132 | }; |
121 | 133 | ||
@@ -239,6 +251,8 @@ int snd_usb_caiaq_set_audio_params (struct snd_usb_caiaqdev *dev, | |||
239 | 251 | ||
240 | if (dev->audio_parm_answer != 1) | 252 | if (dev->audio_parm_answer != 1) |
241 | debug("unable to set the device's audio params\n"); | 253 | debug("unable to set the device's audio params\n"); |
254 | else | ||
255 | dev->bpp = bpp; | ||
242 | 256 | ||
243 | return dev->audio_parm_answer == 1 ? 0 : -EINVAL; | 257 | return dev->audio_parm_answer == 1 ? 0 : -EINVAL; |
244 | } | 258 | } |
@@ -300,6 +314,12 @@ static void __devinit setup_card(struct snd_usb_caiaqdev *dev) | |||
300 | } | 314 | } |
301 | 315 | ||
302 | break; | 316 | break; |
317 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ): | ||
318 | /* Audio 4 DJ - default input mode to phono */ | ||
319 | dev->control_state[0] = 2; | ||
320 | snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO, | ||
321 | dev->control_state, 1); | ||
322 | break; | ||
303 | } | 323 | } |
304 | 324 | ||
305 | if (dev->spec.num_analog_audio_out + | 325 | if (dev->spec.num_analog_audio_out + |
@@ -336,9 +356,10 @@ static void __devinit setup_card(struct snd_usb_caiaqdev *dev) | |||
336 | log("Unable to set up control system (ret=%d)\n", ret); | 356 | log("Unable to set up control system (ret=%d)\n", ret); |
337 | } | 357 | } |
338 | 358 | ||
339 | static struct snd_card* create_card(struct usb_device* usb_dev) | 359 | static int create_card(struct usb_device* usb_dev, struct snd_card **cardp) |
340 | { | 360 | { |
341 | int devnum; | 361 | int devnum; |
362 | int err; | ||
342 | struct snd_card *card; | 363 | struct snd_card *card; |
343 | struct snd_usb_caiaqdev *dev; | 364 | struct snd_usb_caiaqdev *dev; |
344 | 365 | ||
@@ -347,12 +368,12 @@ static struct snd_card* create_card(struct usb_device* usb_dev) | |||
347 | break; | 368 | break; |
348 | 369 | ||
349 | if (devnum >= SNDRV_CARDS) | 370 | if (devnum >= SNDRV_CARDS) |
350 | return NULL; | 371 | return -ENODEV; |
351 | 372 | ||
352 | card = snd_card_new(index[devnum], id[devnum], THIS_MODULE, | 373 | err = snd_card_create(index[devnum], id[devnum], THIS_MODULE, |
353 | sizeof(struct snd_usb_caiaqdev)); | 374 | sizeof(struct snd_usb_caiaqdev), &card); |
354 | if (!card) | 375 | if (err < 0) |
355 | return NULL; | 376 | return err; |
356 | 377 | ||
357 | dev = caiaqdev(card); | 378 | dev = caiaqdev(card); |
358 | dev->chip.dev = usb_dev; | 379 | dev->chip.dev = usb_dev; |
@@ -362,7 +383,8 @@ static struct snd_card* create_card(struct usb_device* usb_dev) | |||
362 | spin_lock_init(&dev->spinlock); | 383 | spin_lock_init(&dev->spinlock); |
363 | snd_card_set_dev(card, &usb_dev->dev); | 384 | snd_card_set_dev(card, &usb_dev->dev); |
364 | 385 | ||
365 | return card; | 386 | *cardp = card; |
387 | return 0; | ||
366 | } | 388 | } |
367 | 389 | ||
368 | static int __devinit init_card(struct snd_usb_caiaqdev *dev) | 390 | static int __devinit init_card(struct snd_usb_caiaqdev *dev) |
@@ -441,10 +463,10 @@ static int __devinit snd_probe(struct usb_interface *intf, | |||
441 | struct snd_card *card; | 463 | struct snd_card *card; |
442 | struct usb_device *device = interface_to_usbdev(intf); | 464 | struct usb_device *device = interface_to_usbdev(intf); |
443 | 465 | ||
444 | card = create_card(device); | 466 | ret = create_card(device, &card); |
445 | 467 | ||
446 | if (!card) | 468 | if (ret < 0) |
447 | return -ENOMEM; | 469 | return ret; |
448 | 470 | ||
449 | usb_set_intfdata(intf, card); | 471 | usb_set_intfdata(intf, card); |
450 | ret = init_card(caiaqdev(card)); | 472 | ret = init_card(caiaqdev(card)); |
diff --git a/sound/usb/caiaq/caiaq-device.h b/sound/usb/caiaq/caiaq-device.h index ab56e738c5fc..4cce1ad7493d 100644 --- a/sound/usb/caiaq/caiaq-device.h +++ b/sound/usb/caiaq/caiaq-device.h | |||
@@ -10,8 +10,10 @@ | |||
10 | #define USB_PID_KORECONTROLLER 0x4711 | 10 | #define USB_PID_KORECONTROLLER 0x4711 |
11 | #define USB_PID_KORECONTROLLER2 0x4712 | 11 | #define USB_PID_KORECONTROLLER2 0x4712 |
12 | #define USB_PID_AK1 0x0815 | 12 | #define USB_PID_AK1 0x0815 |
13 | #define USB_PID_AUDIO4DJ 0x0839 | ||
13 | #define USB_PID_AUDIO8DJ 0x1978 | 14 | #define USB_PID_AUDIO8DJ 0x1978 |
14 | #define USB_PID_SESSIONIO 0x1915 | 15 | #define USB_PID_SESSIONIO 0x1915 |
16 | #define USB_PID_GUITARRIGMOBILE 0x0d8d | ||
15 | 17 | ||
16 | #define EP1_BUFSIZE 64 | 18 | #define EP1_BUFSIZE 64 |
17 | #define CAIAQ_USB_STR_LEN 0xff | 19 | #define CAIAQ_USB_STR_LEN 0xff |
@@ -87,9 +89,9 @@ struct snd_usb_caiaqdev { | |||
87 | int audio_out_buf_pos[MAX_STREAMS]; | 89 | int audio_out_buf_pos[MAX_STREAMS]; |
88 | int period_in_count[MAX_STREAMS]; | 90 | int period_in_count[MAX_STREAMS]; |
89 | int period_out_count[MAX_STREAMS]; | 91 | int period_out_count[MAX_STREAMS]; |
90 | int input_panic, output_panic; | 92 | int input_panic, output_panic, warned; |
91 | char *audio_in_buf, *audio_out_buf; | 93 | char *audio_in_buf, *audio_out_buf; |
92 | unsigned int samplerates; | 94 | unsigned int samplerates, bpp; |
93 | 95 | ||
94 | struct snd_pcm_substream *sub_playback[MAX_STREAMS]; | 96 | struct snd_pcm_substream *sub_playback[MAX_STREAMS]; |
95 | struct snd_pcm_substream *sub_capture[MAX_STREAMS]; | 97 | struct snd_pcm_substream *sub_capture[MAX_STREAMS]; |
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 19e37451c216..c2db0f959681 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c | |||
@@ -107,7 +107,7 @@ MODULE_PARM_DESC(ignore_ctl_error, | |||
107 | #define MAX_PACKS_HS (MAX_PACKS * 8) /* in high speed mode */ | 107 | #define MAX_PACKS_HS (MAX_PACKS * 8) /* in high speed mode */ |
108 | #define MAX_URBS 8 | 108 | #define MAX_URBS 8 |
109 | #define SYNC_URBS 4 /* always four urbs for sync */ | 109 | #define SYNC_URBS 4 /* always four urbs for sync */ |
110 | #define MIN_PACKS_URB 1 /* minimum 1 packet per urb */ | 110 | #define MAX_QUEUE 24 /* try not to exceed this queue length, in ms */ |
111 | 111 | ||
112 | struct audioformat { | 112 | struct audioformat { |
113 | struct list_head list; | 113 | struct list_head list; |
@@ -525,7 +525,7 @@ static int snd_usb_audio_next_packet_size(struct snd_usb_substream *subs) | |||
525 | /* | 525 | /* |
526 | * Prepare urb for streaming before playback starts or when paused. | 526 | * Prepare urb for streaming before playback starts or when paused. |
527 | * | 527 | * |
528 | * We don't have any data, so we send a frame of silence. | 528 | * We don't have any data, so we send silence. |
529 | */ | 529 | */ |
530 | static int prepare_nodata_playback_urb(struct snd_usb_substream *subs, | 530 | static int prepare_nodata_playback_urb(struct snd_usb_substream *subs, |
531 | struct snd_pcm_runtime *runtime, | 531 | struct snd_pcm_runtime *runtime, |
@@ -537,13 +537,13 @@ static int prepare_nodata_playback_urb(struct snd_usb_substream *subs, | |||
537 | 537 | ||
538 | offs = 0; | 538 | offs = 0; |
539 | urb->dev = ctx->subs->dev; | 539 | urb->dev = ctx->subs->dev; |
540 | urb->number_of_packets = subs->packs_per_ms; | 540 | for (i = 0; i < ctx->packets; ++i) { |
541 | for (i = 0; i < subs->packs_per_ms; ++i) { | ||
542 | counts = snd_usb_audio_next_packet_size(subs); | 541 | counts = snd_usb_audio_next_packet_size(subs); |
543 | urb->iso_frame_desc[i].offset = offs * stride; | 542 | urb->iso_frame_desc[i].offset = offs * stride; |
544 | urb->iso_frame_desc[i].length = counts * stride; | 543 | urb->iso_frame_desc[i].length = counts * stride; |
545 | offs += counts; | 544 | offs += counts; |
546 | } | 545 | } |
546 | urb->number_of_packets = ctx->packets; | ||
547 | urb->transfer_buffer_length = offs * stride; | 547 | urb->transfer_buffer_length = offs * stride; |
548 | memset(urb->transfer_buffer, | 548 | memset(urb->transfer_buffer, |
549 | subs->cur_audiofmt->format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0, | 549 | subs->cur_audiofmt->format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0, |
@@ -1034,9 +1034,9 @@ static void release_substream_urbs(struct snd_usb_substream *subs, int force) | |||
1034 | static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int period_bytes, | 1034 | static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int period_bytes, |
1035 | unsigned int rate, unsigned int frame_bits) | 1035 | unsigned int rate, unsigned int frame_bits) |
1036 | { | 1036 | { |
1037 | unsigned int maxsize, n, i; | 1037 | unsigned int maxsize, i; |
1038 | int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK; | 1038 | int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK; |
1039 | unsigned int npacks[MAX_URBS], urb_packs, total_packs, packs_per_ms; | 1039 | unsigned int urb_packs, total_packs, packs_per_ms; |
1040 | 1040 | ||
1041 | /* calculate the frequency in 16.16 format */ | 1041 | /* calculate the frequency in 16.16 format */ |
1042 | if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) | 1042 | if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) |
@@ -1070,8 +1070,7 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri | |||
1070 | subs->packs_per_ms = packs_per_ms; | 1070 | subs->packs_per_ms = packs_per_ms; |
1071 | 1071 | ||
1072 | if (is_playback) { | 1072 | if (is_playback) { |
1073 | urb_packs = nrpacks; | 1073 | urb_packs = max(nrpacks, 1); |
1074 | urb_packs = max(urb_packs, (unsigned int)MIN_PACKS_URB); | ||
1075 | urb_packs = min(urb_packs, (unsigned int)MAX_PACKS); | 1074 | urb_packs = min(urb_packs, (unsigned int)MAX_PACKS); |
1076 | } else | 1075 | } else |
1077 | urb_packs = 1; | 1076 | urb_packs = 1; |
@@ -1079,7 +1078,7 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri | |||
1079 | 1078 | ||
1080 | /* decide how many packets to be used */ | 1079 | /* decide how many packets to be used */ |
1081 | if (is_playback) { | 1080 | if (is_playback) { |
1082 | unsigned int minsize; | 1081 | unsigned int minsize, maxpacks; |
1083 | /* determine how small a packet can be */ | 1082 | /* determine how small a packet can be */ |
1084 | minsize = (subs->freqn >> (16 - subs->datainterval)) | 1083 | minsize = (subs->freqn >> (16 - subs->datainterval)) |
1085 | * (frame_bits >> 3); | 1084 | * (frame_bits >> 3); |
@@ -1092,8 +1091,13 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri | |||
1092 | total_packs = (total_packs + packs_per_ms - 1) | 1091 | total_packs = (total_packs + packs_per_ms - 1) |
1093 | & ~(packs_per_ms - 1); | 1092 | & ~(packs_per_ms - 1); |
1094 | /* we need at least two URBs for queueing */ | 1093 | /* we need at least two URBs for queueing */ |
1095 | if (total_packs < 2 * MIN_PACKS_URB * packs_per_ms) | 1094 | if (total_packs < 2 * packs_per_ms) { |
1096 | total_packs = 2 * MIN_PACKS_URB * packs_per_ms; | 1095 | total_packs = 2 * packs_per_ms; |
1096 | } else { | ||
1097 | /* and we don't want too long a queue either */ | ||
1098 | maxpacks = max(MAX_QUEUE * packs_per_ms, urb_packs * 2); | ||
1099 | total_packs = min(total_packs, maxpacks); | ||
1100 | } | ||
1097 | } else { | 1101 | } else { |
1098 | total_packs = MAX_URBS * urb_packs; | 1102 | total_packs = MAX_URBS * urb_packs; |
1099 | } | 1103 | } |
@@ -1102,31 +1106,11 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri | |||
1102 | /* too much... */ | 1106 | /* too much... */ |
1103 | subs->nurbs = MAX_URBS; | 1107 | subs->nurbs = MAX_URBS; |
1104 | total_packs = MAX_URBS * urb_packs; | 1108 | total_packs = MAX_URBS * urb_packs; |
1105 | } | 1109 | } else if (subs->nurbs < 2) { |
1106 | n = total_packs; | ||
1107 | for (i = 0; i < subs->nurbs; i++) { | ||
1108 | npacks[i] = n > urb_packs ? urb_packs : n; | ||
1109 | n -= urb_packs; | ||
1110 | } | ||
1111 | if (subs->nurbs <= 1) { | ||
1112 | /* too little - we need at least two packets | 1110 | /* too little - we need at least two packets |
1113 | * to ensure contiguous playback/capture | 1111 | * to ensure contiguous playback/capture |
1114 | */ | 1112 | */ |
1115 | subs->nurbs = 2; | 1113 | subs->nurbs = 2; |
1116 | npacks[0] = (total_packs + 1) / 2; | ||
1117 | npacks[1] = total_packs - npacks[0]; | ||
1118 | } else if (npacks[subs->nurbs-1] < MIN_PACKS_URB * packs_per_ms) { | ||
1119 | /* the last packet is too small.. */ | ||
1120 | if (subs->nurbs > 2) { | ||
1121 | /* merge to the first one */ | ||
1122 | npacks[0] += npacks[subs->nurbs - 1]; | ||
1123 | subs->nurbs--; | ||
1124 | } else { | ||
1125 | /* divide to two */ | ||
1126 | subs->nurbs = 2; | ||
1127 | npacks[0] = (total_packs + 1) / 2; | ||
1128 | npacks[1] = total_packs - npacks[0]; | ||
1129 | } | ||
1130 | } | 1114 | } |
1131 | 1115 | ||
1132 | /* allocate and initialize data urbs */ | 1116 | /* allocate and initialize data urbs */ |
@@ -1134,7 +1118,8 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri | |||
1134 | struct snd_urb_ctx *u = &subs->dataurb[i]; | 1118 | struct snd_urb_ctx *u = &subs->dataurb[i]; |
1135 | u->index = i; | 1119 | u->index = i; |
1136 | u->subs = subs; | 1120 | u->subs = subs; |
1137 | u->packets = npacks[i]; | 1121 | u->packets = (i + 1) * total_packs / subs->nurbs |
1122 | - i * total_packs / subs->nurbs; | ||
1138 | u->buffer_size = maxsize * u->packets; | 1123 | u->buffer_size = maxsize * u->packets; |
1139 | if (subs->fmt_type == USB_FORMAT_TYPE_II) | 1124 | if (subs->fmt_type == USB_FORMAT_TYPE_II) |
1140 | u->packets++; /* for transfer delimiter */ | 1125 | u->packets++; /* for transfer delimiter */ |
@@ -1292,14 +1277,14 @@ static int init_usb_sample_rate(struct usb_device *dev, int iface, | |||
1292 | if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, | 1277 | if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, |
1293 | USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, | 1278 | USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, |
1294 | SAMPLING_FREQ_CONTROL << 8, ep, data, 3, 1000)) < 0) { | 1279 | SAMPLING_FREQ_CONTROL << 8, ep, data, 3, 1000)) < 0) { |
1295 | snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d to ep 0x%x\n", | 1280 | snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d to ep %#x\n", |
1296 | dev->devnum, iface, fmt->altsetting, rate, ep); | 1281 | dev->devnum, iface, fmt->altsetting, rate, ep); |
1297 | return err; | 1282 | return err; |
1298 | } | 1283 | } |
1299 | if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, | 1284 | if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, |
1300 | USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN, | 1285 | USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN, |
1301 | SAMPLING_FREQ_CONTROL << 8, ep, data, 3, 1000)) < 0) { | 1286 | SAMPLING_FREQ_CONTROL << 8, ep, data, 3, 1000)) < 0) { |
1302 | snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq at ep 0x%x\n", | 1287 | snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq at ep %#x\n", |
1303 | dev->devnum, iface, fmt->altsetting, ep); | 1288 | dev->devnum, iface, fmt->altsetting, ep); |
1304 | return 0; /* some devices don't support reading */ | 1289 | return 0; /* some devices don't support reading */ |
1305 | } | 1290 | } |
@@ -1431,9 +1416,11 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) | |||
1431 | subs->cur_audiofmt = fmt; | 1416 | subs->cur_audiofmt = fmt; |
1432 | 1417 | ||
1433 | #if 0 | 1418 | #if 0 |
1434 | printk("setting done: format = %d, rate = %d..%d, channels = %d\n", | 1419 | printk(KERN_DEBUG |
1420 | "setting done: format = %d, rate = %d..%d, channels = %d\n", | ||
1435 | fmt->format, fmt->rate_min, fmt->rate_max, fmt->channels); | 1421 | fmt->format, fmt->rate_min, fmt->rate_max, fmt->channels); |
1436 | printk(" datapipe = 0x%0x, syncpipe = 0x%0x\n", | 1422 | printk(KERN_DEBUG |
1423 | " datapipe = 0x%0x, syncpipe = 0x%0x\n", | ||
1437 | subs->datapipe, subs->syncpipe); | 1424 | subs->datapipe, subs->syncpipe); |
1438 | #endif | 1425 | #endif |
1439 | 1426 | ||
@@ -1468,7 +1455,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, | |||
1468 | channels = params_channels(hw_params); | 1455 | channels = params_channels(hw_params); |
1469 | fmt = find_format(subs, format, rate, channels); | 1456 | fmt = find_format(subs, format, rate, channels); |
1470 | if (!fmt) { | 1457 | if (!fmt) { |
1471 | snd_printd(KERN_DEBUG "cannot set format: format = 0x%x, rate = %d, channels = %d\n", | 1458 | snd_printd(KERN_DEBUG "cannot set format: format = %#x, rate = %d, channels = %d\n", |
1472 | format, rate, channels); | 1459 | format, rate, channels); |
1473 | return -EINVAL; | 1460 | return -EINVAL; |
1474 | } | 1461 | } |
@@ -1795,7 +1782,7 @@ static int check_hw_params_convention(struct snd_usb_substream *subs) | |||
1795 | if (rates[f->format] && rates[f->format] != f->rates) | 1782 | if (rates[f->format] && rates[f->format] != f->rates) |
1796 | goto __out; | 1783 | goto __out; |
1797 | } | 1784 | } |
1798 | channels[f->format] |= (1 << f->channels); | 1785 | channels[f->format] |= 1 << (f->channels - 1); |
1799 | rates[f->format] |= f->rates; | 1786 | rates[f->format] |= f->rates; |
1800 | /* needs knot? */ | 1787 | /* needs knot? */ |
1801 | if (f->rates & SNDRV_PCM_RATE_KNOT) | 1788 | if (f->rates & SNDRV_PCM_RATE_KNOT) |
@@ -1822,7 +1809,7 @@ static int check_hw_params_convention(struct snd_usb_substream *subs) | |||
1822 | continue; | 1809 | continue; |
1823 | for (i = 0; i < 32; i++) { | 1810 | for (i = 0; i < 32; i++) { |
1824 | if (f->rates & (1 << i)) | 1811 | if (f->rates & (1 << i)) |
1825 | channels[i] |= (1 << f->channels); | 1812 | channels[i] |= 1 << (f->channels - 1); |
1826 | } | 1813 | } |
1827 | } | 1814 | } |
1828 | cmaster = 0; | 1815 | cmaster = 0; |
@@ -1919,7 +1906,7 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre | |||
1919 | * in the current code assume the 1ms period. | 1906 | * in the current code assume the 1ms period. |
1920 | */ | 1907 | */ |
1921 | snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, | 1908 | snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, |
1922 | 1000 * MIN_PACKS_URB, | 1909 | 1000, |
1923 | /*(nrpacks * MAX_URBS) * 1000*/ UINT_MAX); | 1910 | /*(nrpacks * MAX_URBS) * 1000*/ UINT_MAX); |
1924 | 1911 | ||
1925 | err = check_hw_params_convention(subs); | 1912 | err = check_hw_params_convention(subs); |
@@ -2160,7 +2147,7 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s | |||
2160 | fp = list_entry(p, struct audioformat, list); | 2147 | fp = list_entry(p, struct audioformat, list); |
2161 | snd_iprintf(buffer, " Interface %d\n", fp->iface); | 2148 | snd_iprintf(buffer, " Interface %d\n", fp->iface); |
2162 | snd_iprintf(buffer, " Altset %d\n", fp->altsetting); | 2149 | snd_iprintf(buffer, " Altset %d\n", fp->altsetting); |
2163 | snd_iprintf(buffer, " Format: 0x%x\n", fp->format); | 2150 | snd_iprintf(buffer, " Format: %#x\n", fp->format); |
2164 | snd_iprintf(buffer, " Channels: %d\n", fp->channels); | 2151 | snd_iprintf(buffer, " Channels: %d\n", fp->channels); |
2165 | snd_iprintf(buffer, " Endpoint: %d %s (%s)\n", | 2152 | snd_iprintf(buffer, " Endpoint: %d %s (%s)\n", |
2166 | fp->endpoint & USB_ENDPOINT_NUMBER_MASK, | 2153 | fp->endpoint & USB_ENDPOINT_NUMBER_MASK, |
@@ -2180,7 +2167,7 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s | |||
2180 | snd_iprintf(buffer, "\n"); | 2167 | snd_iprintf(buffer, "\n"); |
2181 | } | 2168 | } |
2182 | // snd_iprintf(buffer, " Max Packet Size = %d\n", fp->maxpacksize); | 2169 | // snd_iprintf(buffer, " Max Packet Size = %d\n", fp->maxpacksize); |
2183 | // snd_iprintf(buffer, " EP Attribute = 0x%x\n", fp->attributes); | 2170 | // snd_iprintf(buffer, " EP Attribute = %#x\n", fp->attributes); |
2184 | } | 2171 | } |
2185 | } | 2172 | } |
2186 | 2173 | ||
@@ -2621,7 +2608,7 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip, struct audioformat | |||
2621 | fp->format = SNDRV_PCM_FORMAT_MPEG; | 2608 | fp->format = SNDRV_PCM_FORMAT_MPEG; |
2622 | break; | 2609 | break; |
2623 | default: | 2610 | default: |
2624 | snd_printd(KERN_INFO "%d:%u:%d : unknown format tag 0x%x is detected. processed as MPEG.\n", | 2611 | snd_printd(KERN_INFO "%d:%u:%d : unknown format tag %#x is detected. processed as MPEG.\n", |
2625 | chip->dev->devnum, fp->iface, fp->altsetting, format); | 2612 | chip->dev->devnum, fp->iface, fp->altsetting, format); |
2626 | fp->format = SNDRV_PCM_FORMAT_MPEG; | 2613 | fp->format = SNDRV_PCM_FORMAT_MPEG; |
2627 | break; | 2614 | break; |
@@ -2819,7 +2806,7 @@ static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) | |||
2819 | continue; | 2806 | continue; |
2820 | } | 2807 | } |
2821 | 2808 | ||
2822 | snd_printdd(KERN_INFO "%d:%u:%d: add audio endpoint 0x%x\n", dev->devnum, iface_no, altno, fp->endpoint); | 2809 | snd_printdd(KERN_INFO "%d:%u:%d: add audio endpoint %#x\n", dev->devnum, iface_no, altno, fp->endpoint); |
2823 | err = add_audio_endpoint(chip, stream, fp); | 2810 | err = add_audio_endpoint(chip, stream, fp); |
2824 | if (err < 0) { | 2811 | if (err < 0) { |
2825 | kfree(fp->rate_table); | 2812 | kfree(fp->rate_table); |
@@ -3466,10 +3453,10 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, | |||
3466 | return -ENXIO; | 3453 | return -ENXIO; |
3467 | } | 3454 | } |
3468 | 3455 | ||
3469 | card = snd_card_new(index[idx], id[idx], THIS_MODULE, 0); | 3456 | err = snd_card_create(index[idx], id[idx], THIS_MODULE, 0, &card); |
3470 | if (card == NULL) { | 3457 | if (err < 0) { |
3471 | snd_printk(KERN_ERR "cannot create card instance %d\n", idx); | 3458 | snd_printk(KERN_ERR "cannot create card instance %d\n", idx); |
3472 | return -ENOMEM; | 3459 | return err; |
3473 | } | 3460 | } |
3474 | 3461 | ||
3475 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | 3462 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); |
@@ -3766,7 +3753,7 @@ static int usb_audio_resume(struct usb_interface *intf) | |||
3766 | 3753 | ||
3767 | static int __init snd_usb_audio_init(void) | 3754 | static int __init snd_usb_audio_init(void) |
3768 | { | 3755 | { |
3769 | if (nrpacks < MIN_PACKS_URB || nrpacks > MAX_PACKS) { | 3756 | if (nrpacks < 1 || nrpacks > MAX_PACKS) { |
3770 | printk(KERN_WARNING "invalid nrpacks value.\n"); | 3757 | printk(KERN_WARNING "invalid nrpacks value.\n"); |
3771 | return -EINVAL; | 3758 | return -EINVAL; |
3772 | } | 3759 | } |
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c index 00397c8a765b..ecb58e7a6245 100644 --- a/sound/usb/usbmixer.c +++ b/sound/usb/usbmixer.c | |||
@@ -66,6 +66,7 @@ static const struct rc_config { | |||
66 | { USB_ID(0x041e, 0x3000), 0, 1, 2, 1, 18, 0x0013 }, /* Extigy */ | 66 | { USB_ID(0x041e, 0x3000), 0, 1, 2, 1, 18, 0x0013 }, /* Extigy */ |
67 | { USB_ID(0x041e, 0x3020), 2, 1, 6, 6, 18, 0x0013 }, /* Audigy 2 NX */ | 67 | { USB_ID(0x041e, 0x3020), 2, 1, 6, 6, 18, 0x0013 }, /* Audigy 2 NX */ |
68 | { USB_ID(0x041e, 0x3040), 2, 2, 6, 6, 2, 0x6e91 }, /* Live! 24-bit */ | 68 | { USB_ID(0x041e, 0x3040), 2, 2, 6, 6, 2, 0x6e91 }, /* Live! 24-bit */ |
69 | { USB_ID(0x041e, 0x3048), 2, 2, 6, 6, 2, 0x6e91 }, /* Toshiba SB0500 */ | ||
69 | }; | 70 | }; |
70 | 71 | ||
71 | struct usb_mixer_interface { | 72 | struct usb_mixer_interface { |
@@ -78,7 +79,6 @@ struct usb_mixer_interface { | |||
78 | 79 | ||
79 | /* Sound Blaster remote control stuff */ | 80 | /* Sound Blaster remote control stuff */ |
80 | const struct rc_config *rc_cfg; | 81 | const struct rc_config *rc_cfg; |
81 | unsigned long rc_hwdep_open; | ||
82 | u32 rc_code; | 82 | u32 rc_code; |
83 | wait_queue_head_t rc_waitq; | 83 | wait_queue_head_t rc_waitq; |
84 | struct urb *rc_urb; | 84 | struct urb *rc_urb; |
@@ -110,6 +110,8 @@ struct mixer_build { | |||
110 | const struct usbmix_selector_map *selector_map; | 110 | const struct usbmix_selector_map *selector_map; |
111 | }; | 111 | }; |
112 | 112 | ||
113 | #define MAX_CHANNELS 10 /* max logical channels */ | ||
114 | |||
113 | struct usb_mixer_elem_info { | 115 | struct usb_mixer_elem_info { |
114 | struct usb_mixer_interface *mixer; | 116 | struct usb_mixer_interface *mixer; |
115 | struct usb_mixer_elem_info *next_id_elem; /* list of controls with same id */ | 117 | struct usb_mixer_elem_info *next_id_elem; /* list of controls with same id */ |
@@ -120,6 +122,8 @@ struct usb_mixer_elem_info { | |||
120 | int channels; | 122 | int channels; |
121 | int val_type; | 123 | int val_type; |
122 | int min, max, res; | 124 | int min, max, res; |
125 | int cached; | ||
126 | int cache_val[MAX_CHANNELS]; | ||
123 | u8 initialized; | 127 | u8 initialized; |
124 | }; | 128 | }; |
125 | 129 | ||
@@ -181,8 +185,6 @@ enum { | |||
181 | USB_PROC_DCR_RELEASE = 6, | 185 | USB_PROC_DCR_RELEASE = 6, |
182 | }; | 186 | }; |
183 | 187 | ||
184 | #define MAX_CHANNELS 10 /* max logical channels */ | ||
185 | |||
186 | 188 | ||
187 | /* | 189 | /* |
188 | * manual mapping of mixer names | 190 | * manual mapping of mixer names |
@@ -219,7 +221,10 @@ static int check_ignored_ctl(struct mixer_build *state, int unitid, int control) | |||
219 | for (p = state->map; p->id; p++) { | 221 | for (p = state->map; p->id; p++) { |
220 | if (p->id == unitid && ! p->name && | 222 | if (p->id == unitid && ! p->name && |
221 | (! control || ! p->control || control == p->control)) { | 223 | (! control || ! p->control || control == p->control)) { |
222 | // printk("ignored control %d:%d\n", unitid, control); | 224 | /* |
225 | printk(KERN_DEBUG "ignored control %d:%d\n", | ||
226 | unitid, control); | ||
227 | */ | ||
223 | return 1; | 228 | return 1; |
224 | } | 229 | } |
225 | } | 230 | } |
@@ -376,11 +381,35 @@ static int get_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int * | |||
376 | } | 381 | } |
377 | 382 | ||
378 | /* channel = 0: master, 1 = first channel */ | 383 | /* channel = 0: master, 1 = first channel */ |
379 | static inline int get_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, int *value) | 384 | static inline int get_cur_mix_raw(struct usb_mixer_elem_info *cval, |
385 | int channel, int *value) | ||
380 | { | 386 | { |
381 | return get_ctl_value(cval, GET_CUR, (cval->control << 8) | channel, value); | 387 | return get_ctl_value(cval, GET_CUR, (cval->control << 8) | channel, value); |
382 | } | 388 | } |
383 | 389 | ||
390 | static int get_cur_mix_value(struct usb_mixer_elem_info *cval, | ||
391 | int channel, int index, int *value) | ||
392 | { | ||
393 | int err; | ||
394 | |||
395 | if (cval->cached & (1 << channel)) { | ||
396 | *value = cval->cache_val[index]; | ||
397 | return 0; | ||
398 | } | ||
399 | err = get_cur_mix_raw(cval, channel, value); | ||
400 | if (err < 0) { | ||
401 | if (!cval->mixer->ignore_ctl_error) | ||
402 | snd_printd(KERN_ERR "cannot get current value for " | ||
403 | "control %d ch %d: err = %d\n", | ||
404 | cval->control, channel, err); | ||
405 | return err; | ||
406 | } | ||
407 | cval->cached |= 1 << channel; | ||
408 | cval->cache_val[index] = *value; | ||
409 | return 0; | ||
410 | } | ||
411 | |||
412 | |||
384 | /* | 413 | /* |
385 | * set a mixer value | 414 | * set a mixer value |
386 | */ | 415 | */ |
@@ -412,9 +441,17 @@ static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int v | |||
412 | return set_ctl_value(cval, SET_CUR, validx, value); | 441 | return set_ctl_value(cval, SET_CUR, validx, value); |
413 | } | 442 | } |
414 | 443 | ||
415 | static inline int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, int value) | 444 | static int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, |
445 | int index, int value) | ||
416 | { | 446 | { |
417 | return set_ctl_value(cval, SET_CUR, (cval->control << 8) | channel, value); | 447 | int err; |
448 | err = set_ctl_value(cval, SET_CUR, (cval->control << 8) | channel, | ||
449 | value); | ||
450 | if (err < 0) | ||
451 | return err; | ||
452 | cval->cached |= 1 << channel; | ||
453 | cval->cache_val[index] = value; | ||
454 | return 0; | ||
418 | } | 455 | } |
419 | 456 | ||
420 | /* | 457 | /* |
@@ -718,7 +755,7 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min) | |||
718 | if (cval->min + cval->res < cval->max) { | 755 | if (cval->min + cval->res < cval->max) { |
719 | int last_valid_res = cval->res; | 756 | int last_valid_res = cval->res; |
720 | int saved, test, check; | 757 | int saved, test, check; |
721 | get_cur_mix_value(cval, minchn, &saved); | 758 | get_cur_mix_raw(cval, minchn, &saved); |
722 | for (;;) { | 759 | for (;;) { |
723 | test = saved; | 760 | test = saved; |
724 | if (test < cval->max) | 761 | if (test < cval->max) |
@@ -726,8 +763,8 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min) | |||
726 | else | 763 | else |
727 | test -= cval->res; | 764 | test -= cval->res; |
728 | if (test < cval->min || test > cval->max || | 765 | if (test < cval->min || test > cval->max || |
729 | set_cur_mix_value(cval, minchn, test) || | 766 | set_cur_mix_value(cval, minchn, 0, test) || |
730 | get_cur_mix_value(cval, minchn, &check)) { | 767 | get_cur_mix_raw(cval, minchn, &check)) { |
731 | cval->res = last_valid_res; | 768 | cval->res = last_valid_res; |
732 | break; | 769 | break; |
733 | } | 770 | } |
@@ -735,7 +772,7 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min) | |||
735 | break; | 772 | break; |
736 | cval->res *= 2; | 773 | cval->res *= 2; |
737 | } | 774 | } |
738 | set_cur_mix_value(cval, minchn, saved); | 775 | set_cur_mix_value(cval, minchn, 0, saved); |
739 | } | 776 | } |
740 | 777 | ||
741 | cval->initialized = 1; | 778 | cval->initialized = 1; |
@@ -775,35 +812,25 @@ static int mixer_ctl_feature_get(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
775 | struct usb_mixer_elem_info *cval = kcontrol->private_data; | 812 | struct usb_mixer_elem_info *cval = kcontrol->private_data; |
776 | int c, cnt, val, err; | 813 | int c, cnt, val, err; |
777 | 814 | ||
815 | ucontrol->value.integer.value[0] = cval->min; | ||
778 | if (cval->cmask) { | 816 | if (cval->cmask) { |
779 | cnt = 0; | 817 | cnt = 0; |
780 | for (c = 0; c < MAX_CHANNELS; c++) { | 818 | for (c = 0; c < MAX_CHANNELS; c++) { |
781 | if (cval->cmask & (1 << c)) { | 819 | if (!(cval->cmask & (1 << c))) |
782 | err = get_cur_mix_value(cval, c + 1, &val); | 820 | continue; |
783 | if (err < 0) { | 821 | err = get_cur_mix_value(cval, c + 1, cnt, &val); |
784 | if (cval->mixer->ignore_ctl_error) { | 822 | if (err < 0) |
785 | ucontrol->value.integer.value[0] = cval->min; | 823 | return cval->mixer->ignore_ctl_error ? 0 : err; |
786 | return 0; | 824 | val = get_relative_value(cval, val); |
787 | } | 825 | ucontrol->value.integer.value[cnt] = val; |
788 | snd_printd(KERN_ERR "cannot get current value for control %d ch %d: err = %d\n", cval->control, c + 1, err); | 826 | cnt++; |
789 | return err; | ||
790 | } | ||
791 | val = get_relative_value(cval, val); | ||
792 | ucontrol->value.integer.value[cnt] = val; | ||
793 | cnt++; | ||
794 | } | ||
795 | } | 827 | } |
828 | return 0; | ||
796 | } else { | 829 | } else { |
797 | /* master channel */ | 830 | /* master channel */ |
798 | err = get_cur_mix_value(cval, 0, &val); | 831 | err = get_cur_mix_value(cval, 0, 0, &val); |
799 | if (err < 0) { | 832 | if (err < 0) |
800 | if (cval->mixer->ignore_ctl_error) { | 833 | return cval->mixer->ignore_ctl_error ? 0 : err; |
801 | ucontrol->value.integer.value[0] = cval->min; | ||
802 | return 0; | ||
803 | } | ||
804 | snd_printd(KERN_ERR "cannot get current value for control %d master ch: err = %d\n", cval->control, err); | ||
805 | return err; | ||
806 | } | ||
807 | val = get_relative_value(cval, val); | 834 | val = get_relative_value(cval, val); |
808 | ucontrol->value.integer.value[0] = val; | 835 | ucontrol->value.integer.value[0] = val; |
809 | } | 836 | } |
@@ -820,34 +847,28 @@ static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
820 | if (cval->cmask) { | 847 | if (cval->cmask) { |
821 | cnt = 0; | 848 | cnt = 0; |
822 | for (c = 0; c < MAX_CHANNELS; c++) { | 849 | for (c = 0; c < MAX_CHANNELS; c++) { |
823 | if (cval->cmask & (1 << c)) { | 850 | if (!(cval->cmask & (1 << c))) |
824 | err = get_cur_mix_value(cval, c + 1, &oval); | 851 | continue; |
825 | if (err < 0) { | 852 | err = get_cur_mix_value(cval, c + 1, cnt, &oval); |
826 | if (cval->mixer->ignore_ctl_error) | 853 | if (err < 0) |
827 | return 0; | 854 | return cval->mixer->ignore_ctl_error ? 0 : err; |
828 | return err; | 855 | val = ucontrol->value.integer.value[cnt]; |
829 | } | 856 | val = get_abs_value(cval, val); |
830 | val = ucontrol->value.integer.value[cnt]; | 857 | if (oval != val) { |
831 | val = get_abs_value(cval, val); | 858 | set_cur_mix_value(cval, c + 1, cnt, val); |
832 | if (oval != val) { | 859 | changed = 1; |
833 | set_cur_mix_value(cval, c + 1, val); | ||
834 | changed = 1; | ||
835 | } | ||
836 | get_cur_mix_value(cval, c + 1, &val); | ||
837 | cnt++; | ||
838 | } | 860 | } |
861 | cnt++; | ||
839 | } | 862 | } |
840 | } else { | 863 | } else { |
841 | /* master channel */ | 864 | /* master channel */ |
842 | err = get_cur_mix_value(cval, 0, &oval); | 865 | err = get_cur_mix_value(cval, 0, 0, &oval); |
843 | if (err < 0 && cval->mixer->ignore_ctl_error) | ||
844 | return 0; | ||
845 | if (err < 0) | 866 | if (err < 0) |
846 | return err; | 867 | return cval->mixer->ignore_ctl_error ? 0 : err; |
847 | val = ucontrol->value.integer.value[0]; | 868 | val = ucontrol->value.integer.value[0]; |
848 | val = get_abs_value(cval, val); | 869 | val = get_abs_value(cval, val); |
849 | if (val != oval) { | 870 | if (val != oval) { |
850 | set_cur_mix_value(cval, 0, val); | 871 | set_cur_mix_value(cval, 0, 0, val); |
851 | changed = 1; | 872 | changed = 1; |
852 | } | 873 | } |
853 | } | 874 | } |
@@ -1706,7 +1727,8 @@ static void snd_usb_mixer_memory_change(struct usb_mixer_interface *mixer, | |||
1706 | break; | 1727 | break; |
1707 | /* live24ext: 4 = line-in jack */ | 1728 | /* live24ext: 4 = line-in jack */ |
1708 | case 3: /* hp-out jack (may actuate Mute) */ | 1729 | case 3: /* hp-out jack (may actuate Mute) */ |
1709 | if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040)) | 1730 | if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) || |
1731 | mixer->chip->usb_id == USB_ID(0x041e, 0x3048)) | ||
1710 | snd_usb_mixer_notify_id(mixer, mixer->rc_cfg->mute_mixer_id); | 1732 | snd_usb_mixer_notify_id(mixer, mixer->rc_cfg->mute_mixer_id); |
1711 | break; | 1733 | break; |
1712 | default: | 1734 | default: |
@@ -1797,24 +1819,6 @@ static void snd_usb_soundblaster_remote_complete(struct urb *urb) | |||
1797 | wake_up(&mixer->rc_waitq); | 1819 | wake_up(&mixer->rc_waitq); |
1798 | } | 1820 | } |
1799 | 1821 | ||
1800 | static int snd_usb_sbrc_hwdep_open(struct snd_hwdep *hw, struct file *file) | ||
1801 | { | ||
1802 | struct usb_mixer_interface *mixer = hw->private_data; | ||
1803 | |||
1804 | if (test_and_set_bit(0, &mixer->rc_hwdep_open)) | ||
1805 | return -EBUSY; | ||
1806 | return 0; | ||
1807 | } | ||
1808 | |||
1809 | static int snd_usb_sbrc_hwdep_release(struct snd_hwdep *hw, struct file *file) | ||
1810 | { | ||
1811 | struct usb_mixer_interface *mixer = hw->private_data; | ||
1812 | |||
1813 | clear_bit(0, &mixer->rc_hwdep_open); | ||
1814 | smp_mb__after_clear_bit(); | ||
1815 | return 0; | ||
1816 | } | ||
1817 | |||
1818 | static long snd_usb_sbrc_hwdep_read(struct snd_hwdep *hw, char __user *buf, | 1822 | static long snd_usb_sbrc_hwdep_read(struct snd_hwdep *hw, char __user *buf, |
1819 | long count, loff_t *offset) | 1823 | long count, loff_t *offset) |
1820 | { | 1824 | { |
@@ -1867,9 +1871,8 @@ static int snd_usb_soundblaster_remote_init(struct usb_mixer_interface *mixer) | |||
1867 | hwdep->iface = SNDRV_HWDEP_IFACE_SB_RC; | 1871 | hwdep->iface = SNDRV_HWDEP_IFACE_SB_RC; |
1868 | hwdep->private_data = mixer; | 1872 | hwdep->private_data = mixer; |
1869 | hwdep->ops.read = snd_usb_sbrc_hwdep_read; | 1873 | hwdep->ops.read = snd_usb_sbrc_hwdep_read; |
1870 | hwdep->ops.open = snd_usb_sbrc_hwdep_open; | ||
1871 | hwdep->ops.release = snd_usb_sbrc_hwdep_release; | ||
1872 | hwdep->ops.poll = snd_usb_sbrc_hwdep_poll; | 1874 | hwdep->ops.poll = snd_usb_sbrc_hwdep_poll; |
1875 | hwdep->exclusive = 1; | ||
1873 | 1876 | ||
1874 | mixer->rc_urb = usb_alloc_urb(0, GFP_KERNEL); | 1877 | mixer->rc_urb = usb_alloc_urb(0, GFP_KERNEL); |
1875 | if (!mixer->rc_urb) | 1878 | if (!mixer->rc_urb) |
@@ -1956,8 +1959,9 @@ static int snd_audigy2nx_controls_create(struct usb_mixer_interface *mixer) | |||
1956 | int i, err; | 1959 | int i, err; |
1957 | 1960 | ||
1958 | for (i = 0; i < ARRAY_SIZE(snd_audigy2nx_controls); ++i) { | 1961 | for (i = 0; i < ARRAY_SIZE(snd_audigy2nx_controls); ++i) { |
1959 | if (i > 1 && /* Live24ext has 2 LEDs only */ | 1962 | if (i > 1 && /* Live24ext has 2 LEDs only */ |
1960 | mixer->chip->usb_id == USB_ID(0x041e, 0x3040)) | 1963 | (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) || |
1964 | mixer->chip->usb_id == USB_ID(0x041e, 0x3048))) | ||
1961 | break; | 1965 | break; |
1962 | err = snd_ctl_add(mixer->chip->card, | 1966 | err = snd_ctl_add(mixer->chip->card, |
1963 | snd_ctl_new1(&snd_audigy2nx_controls[i], mixer)); | 1967 | snd_ctl_new1(&snd_audigy2nx_controls[i], mixer)); |
@@ -1994,7 +1998,8 @@ static void snd_audigy2nx_proc_read(struct snd_info_entry *entry, | |||
1994 | snd_iprintf(buffer, "%s jacks\n\n", mixer->chip->card->shortname); | 1998 | snd_iprintf(buffer, "%s jacks\n\n", mixer->chip->card->shortname); |
1995 | if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020)) | 1999 | if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020)) |
1996 | jacks = jacks_audigy2nx; | 2000 | jacks = jacks_audigy2nx; |
1997 | else if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040)) | 2001 | else if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) || |
2002 | mixer->chip->usb_id == USB_ID(0x041e, 0x3048)) | ||
1998 | jacks = jacks_live24ext; | 2003 | jacks = jacks_live24ext; |
1999 | else | 2004 | else |
2000 | return; | 2005 | return; |
@@ -2044,7 +2049,8 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, | |||
2044 | goto _error; | 2049 | goto _error; |
2045 | 2050 | ||
2046 | if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020) || | 2051 | if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020) || |
2047 | mixer->chip->usb_id == USB_ID(0x041e, 0x3040)) { | 2052 | mixer->chip->usb_id == USB_ID(0x041e, 0x3040) || |
2053 | mixer->chip->usb_id == USB_ID(0x041e, 0x3048)) { | ||
2048 | struct snd_info_entry *entry; | 2054 | struct snd_info_entry *entry; |
2049 | 2055 | ||
2050 | if ((err = snd_audigy2nx_controls_create(mixer)) < 0) | 2056 | if ((err = snd_audigy2nx_controls_create(mixer)) < 0) |
diff --git a/sound/usb/usbmixer_maps.c b/sound/usb/usbmixer_maps.c index d755be0ad811..3e5d66cf1f5a 100644 --- a/sound/usb/usbmixer_maps.c +++ b/sound/usb/usbmixer_maps.c | |||
@@ -261,6 +261,22 @@ static struct usbmix_name_map aureon_51_2_map[] = { | |||
261 | {} /* terminator */ | 261 | {} /* terminator */ |
262 | }; | 262 | }; |
263 | 263 | ||
264 | static struct usbmix_name_map scratch_live_map[] = { | ||
265 | /* 1: IT Line 1 (USB streaming) */ | ||
266 | /* 2: OT Line 1 (Speaker) */ | ||
267 | /* 3: IT Line 1 (Line connector) */ | ||
268 | { 4, "Line 1 In" }, /* FU */ | ||
269 | /* 5: OT Line 1 (USB streaming) */ | ||
270 | /* 6: IT Line 2 (USB streaming) */ | ||
271 | /* 7: OT Line 2 (Speaker) */ | ||
272 | /* 8: IT Line 2 (Line connector) */ | ||
273 | { 9, "Line 2 In" }, /* FU */ | ||
274 | /* 10: OT Line 2 (USB streaming) */ | ||
275 | /* 11: IT Mic (Line connector) */ | ||
276 | /* 12: OT Mic (USB streaming) */ | ||
277 | { 0 } /* terminator */ | ||
278 | }; | ||
279 | |||
264 | /* | 280 | /* |
265 | * Control map entries | 281 | * Control map entries |
266 | */ | 282 | */ |
@@ -285,6 +301,11 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = { | |||
285 | .map = live24ext_map, | 301 | .map = live24ext_map, |
286 | }, | 302 | }, |
287 | { | 303 | { |
304 | .id = USB_ID(0x041e, 0x3048), | ||
305 | .map = audigy2nx_map, | ||
306 | .selector_map = audigy2nx_selectors, | ||
307 | }, | ||
308 | { | ||
288 | /* Hercules DJ Console (Windows Edition) */ | 309 | /* Hercules DJ Console (Windows Edition) */ |
289 | .id = USB_ID(0x06f8, 0xb000), | 310 | .id = USB_ID(0x06f8, 0xb000), |
290 | .ignore_ctl_error = 1, | 311 | .ignore_ctl_error = 1, |
@@ -311,6 +332,11 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = { | |||
311 | .id = USB_ID(0x0ccd, 0x0028), | 332 | .id = USB_ID(0x0ccd, 0x0028), |
312 | .map = aureon_51_2_map, | 333 | .map = aureon_51_2_map, |
313 | }, | 334 | }, |
335 | { | ||
336 | .id = USB_ID(0x13e5, 0x0001), | ||
337 | .map = scratch_live_map, | ||
338 | .ignore_ctl_error = 1, | ||
339 | }, | ||
314 | { 0 } /* terminator */ | 340 | { 0 } /* terminator */ |
315 | }; | 341 | }; |
316 | 342 | ||
diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h index 5d8ef09b9dcc..647ef5029651 100644 --- a/sound/usb/usbquirks.h +++ b/sound/usb/usbquirks.h | |||
@@ -39,6 +39,16 @@ | |||
39 | .idProduct = prod, \ | 39 | .idProduct = prod, \ |
40 | .bInterfaceClass = USB_CLASS_VENDOR_SPEC | 40 | .bInterfaceClass = USB_CLASS_VENDOR_SPEC |
41 | 41 | ||
42 | /* Creative/Toshiba Multimedia Center SB-0500 */ | ||
43 | { | ||
44 | USB_DEVICE(0x041e, 0x3048), | ||
45 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
46 | .vendor_name = "Toshiba", | ||
47 | .product_name = "SB-0500", | ||
48 | .ifnum = QUIRK_NO_INTERFACE | ||
49 | } | ||
50 | }, | ||
51 | |||
42 | /* Creative/E-Mu devices */ | 52 | /* Creative/E-Mu devices */ |
43 | { | 53 | { |
44 | USB_DEVICE(0x041e, 0x3010), | 54 | USB_DEVICE(0x041e, 0x3010), |
diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c index 73e59f4403a4..98276aafefe6 100644 --- a/sound/usb/usx2y/us122l.c +++ b/sound/usb/usx2y/us122l.c | |||
@@ -478,19 +478,21 @@ static bool us122l_create_card(struct snd_card *card) | |||
478 | return true; | 478 | return true; |
479 | } | 479 | } |
480 | 480 | ||
481 | static struct snd_card *usx2y_create_card(struct usb_device *device) | 481 | static int usx2y_create_card(struct usb_device *device, struct snd_card **cardp) |
482 | { | 482 | { |
483 | int dev; | 483 | int dev; |
484 | struct snd_card *card; | 484 | struct snd_card *card; |
485 | int err; | ||
486 | |||
485 | for (dev = 0; dev < SNDRV_CARDS; ++dev) | 487 | for (dev = 0; dev < SNDRV_CARDS; ++dev) |
486 | if (enable[dev] && !snd_us122l_card_used[dev]) | 488 | if (enable[dev] && !snd_us122l_card_used[dev]) |
487 | break; | 489 | break; |
488 | if (dev >= SNDRV_CARDS) | 490 | if (dev >= SNDRV_CARDS) |
489 | return NULL; | 491 | return -ENODEV; |
490 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, | 492 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, |
491 | sizeof(struct us122l)); | 493 | sizeof(struct us122l), &card); |
492 | if (!card) | 494 | if (err < 0) |
493 | return NULL; | 495 | return err; |
494 | snd_us122l_card_used[US122L(card)->chip.index = dev] = 1; | 496 | snd_us122l_card_used[US122L(card)->chip.index = dev] = 1; |
495 | 497 | ||
496 | US122L(card)->chip.dev = device; | 498 | US122L(card)->chip.dev = device; |
@@ -509,46 +511,57 @@ static struct snd_card *usx2y_create_card(struct usb_device *device) | |||
509 | US122L(card)->chip.dev->devnum | 511 | US122L(card)->chip.dev->devnum |
510 | ); | 512 | ); |
511 | snd_card_set_dev(card, &device->dev); | 513 | snd_card_set_dev(card, &device->dev); |
512 | return card; | 514 | *cardp = card; |
515 | return 0; | ||
513 | } | 516 | } |
514 | 517 | ||
515 | static void *us122l_usb_probe(struct usb_interface *intf, | 518 | static int us122l_usb_probe(struct usb_interface *intf, |
516 | const struct usb_device_id *device_id) | 519 | const struct usb_device_id *device_id, |
520 | struct snd_card **cardp) | ||
517 | { | 521 | { |
518 | struct usb_device *device = interface_to_usbdev(intf); | 522 | struct usb_device *device = interface_to_usbdev(intf); |
519 | struct snd_card *card = usx2y_create_card(device); | 523 | struct snd_card *card; |
524 | int err; | ||
520 | 525 | ||
521 | if (!card) | 526 | err = usx2y_create_card(device, &card); |
522 | return NULL; | 527 | if (err < 0) |
528 | return err; | ||
523 | 529 | ||
524 | if (!us122l_create_card(card) || | 530 | if (!us122l_create_card(card)) { |
525 | snd_card_register(card) < 0) { | ||
526 | snd_card_free(card); | 531 | snd_card_free(card); |
527 | return NULL; | 532 | return -EINVAL; |
533 | } | ||
534 | |||
535 | err = snd_card_register(card); | ||
536 | if (err < 0) { | ||
537 | snd_card_free(card); | ||
538 | return err; | ||
528 | } | 539 | } |
529 | 540 | ||
530 | usb_get_dev(device); | 541 | usb_get_dev(device); |
531 | return card; | 542 | *cardp = card; |
543 | return 0; | ||
532 | } | 544 | } |
533 | 545 | ||
534 | static int snd_us122l_probe(struct usb_interface *intf, | 546 | static int snd_us122l_probe(struct usb_interface *intf, |
535 | const struct usb_device_id *id) | 547 | const struct usb_device_id *id) |
536 | { | 548 | { |
537 | struct snd_card *card; | 549 | struct snd_card *card; |
550 | int err; | ||
551 | |||
538 | snd_printdd(KERN_DEBUG"%p:%i\n", | 552 | snd_printdd(KERN_DEBUG"%p:%i\n", |
539 | intf, intf->cur_altsetting->desc.bInterfaceNumber); | 553 | intf, intf->cur_altsetting->desc.bInterfaceNumber); |
540 | if (intf->cur_altsetting->desc.bInterfaceNumber != 1) | 554 | if (intf->cur_altsetting->desc.bInterfaceNumber != 1) |
541 | return 0; | 555 | return 0; |
542 | 556 | ||
543 | card = us122l_usb_probe(usb_get_intf(intf), id); | 557 | err = us122l_usb_probe(usb_get_intf(intf), id, &card); |
544 | 558 | if (err < 0) { | |
545 | if (card) { | 559 | usb_put_intf(intf); |
546 | usb_set_intfdata(intf, card); | 560 | return err; |
547 | return 0; | ||
548 | } | 561 | } |
549 | 562 | ||
550 | usb_put_intf(intf); | 563 | usb_set_intfdata(intf, card); |
551 | return -EIO; | 564 | return 0; |
552 | } | 565 | } |
553 | 566 | ||
554 | static void snd_us122l_disconnect(struct usb_interface *intf) | 567 | static void snd_us122l_disconnect(struct usb_interface *intf) |
diff --git a/sound/usb/usx2y/usX2Yhwdep.c b/sound/usb/usx2y/usX2Yhwdep.c index 1558a5c4094f..4af8740db717 100644 --- a/sound/usb/usx2y/usX2Yhwdep.c +++ b/sound/usb/usx2y/usX2Yhwdep.c | |||
@@ -30,9 +30,6 @@ | |||
30 | #include "usbusx2y.h" | 30 | #include "usbusx2y.h" |
31 | #include "usX2Yhwdep.h" | 31 | #include "usX2Yhwdep.h" |
32 | 32 | ||
33 | int usX2Y_hwdep_pcm_new(struct snd_card *card); | ||
34 | |||
35 | |||
36 | static int snd_us428ctls_vm_fault(struct vm_area_struct *area, | 33 | static int snd_us428ctls_vm_fault(struct vm_area_struct *area, |
37 | struct vm_fault *vmf) | 34 | struct vm_fault *vmf) |
38 | { | 35 | { |
@@ -106,16 +103,6 @@ static unsigned int snd_us428ctls_poll(struct snd_hwdep *hw, struct file *file, | |||
106 | } | 103 | } |
107 | 104 | ||
108 | 105 | ||
109 | static int snd_usX2Y_hwdep_open(struct snd_hwdep *hw, struct file *file) | ||
110 | { | ||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | static int snd_usX2Y_hwdep_release(struct snd_hwdep *hw, struct file *file) | ||
115 | { | ||
116 | return 0; | ||
117 | } | ||
118 | |||
119 | static int snd_usX2Y_hwdep_dsp_status(struct snd_hwdep *hw, | 106 | static int snd_usX2Y_hwdep_dsp_status(struct snd_hwdep *hw, |
120 | struct snd_hwdep_dsp_status *info) | 107 | struct snd_hwdep_dsp_status *info) |
121 | { | 108 | { |
@@ -267,8 +254,6 @@ int usX2Y_hwdep_new(struct snd_card *card, struct usb_device* device) | |||
267 | 254 | ||
268 | hw->iface = SNDRV_HWDEP_IFACE_USX2Y; | 255 | hw->iface = SNDRV_HWDEP_IFACE_USX2Y; |
269 | hw->private_data = usX2Y(card); | 256 | hw->private_data = usX2Y(card); |
270 | hw->ops.open = snd_usX2Y_hwdep_open; | ||
271 | hw->ops.release = snd_usX2Y_hwdep_release; | ||
272 | hw->ops.dsp_status = snd_usX2Y_hwdep_dsp_status; | 257 | hw->ops.dsp_status = snd_usX2Y_hwdep_dsp_status; |
273 | hw->ops.dsp_load = snd_usX2Y_hwdep_dsp_load; | 258 | hw->ops.dsp_load = snd_usX2Y_hwdep_dsp_load; |
274 | hw->ops.mmap = snd_us428ctls_mmap; | 259 | hw->ops.mmap = snd_us428ctls_mmap; |
diff --git a/sound/usb/usx2y/usb_stream.c b/sound/usb/usx2y/usb_stream.c index 70b96355ca4c..24393dafcb6e 100644 --- a/sound/usb/usx2y/usb_stream.c +++ b/sound/usb/usx2y/usb_stream.c | |||
@@ -557,7 +557,7 @@ static void stream_start(struct usb_stream_kernel *sk, | |||
557 | s->idle_insize -= max_diff - max_diff_0; | 557 | s->idle_insize -= max_diff - max_diff_0; |
558 | s->idle_insize += urb_size - s->period_size; | 558 | s->idle_insize += urb_size - s->period_size; |
559 | if (s->idle_insize < 0) { | 559 | if (s->idle_insize < 0) { |
560 | snd_printk("%i %i %i\n", | 560 | snd_printk(KERN_WARNING "%i %i %i\n", |
561 | s->idle_insize, urb_size, s->period_size); | 561 | s->idle_insize, urb_size, s->period_size); |
562 | return; | 562 | return; |
563 | } else if (s->idle_insize == 0) { | 563 | } else if (s->idle_insize == 0) { |
diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c index 11639bd72a51..5ce0da23ee96 100644 --- a/sound/usb/usx2y/usbusx2y.c +++ b/sound/usb/usx2y/usbusx2y.c | |||
@@ -227,9 +227,9 @@ static void i_usX2Y_In04Int(struct urb *urb) | |||
227 | 227 | ||
228 | if (usX2Y->US04) { | 228 | if (usX2Y->US04) { |
229 | if (0 == usX2Y->US04->submitted) | 229 | if (0 == usX2Y->US04->submitted) |
230 | do | 230 | do { |
231 | err = usb_submit_urb(usX2Y->US04->urb[usX2Y->US04->submitted++], GFP_ATOMIC); | 231 | err = usb_submit_urb(usX2Y->US04->urb[usX2Y->US04->submitted++], GFP_ATOMIC); |
232 | while (!err && usX2Y->US04->submitted < usX2Y->US04->len); | 232 | } while (!err && usX2Y->US04->submitted < usX2Y->US04->len); |
233 | } else | 233 | } else |
234 | if (us428ctls && us428ctls->p4outLast >= 0 && us428ctls->p4outLast < N_us428_p4out_BUFS) { | 234 | if (us428ctls && us428ctls->p4outLast >= 0 && us428ctls->p4outLast < N_us428_p4out_BUFS) { |
235 | if (us428ctls->p4outLast != us428ctls->p4outSent) { | 235 | if (us428ctls->p4outLast != us428ctls->p4outSent) { |
@@ -333,18 +333,21 @@ static struct usb_device_id snd_usX2Y_usb_id_table[] = { | |||
333 | { /* terminator */ } | 333 | { /* terminator */ } |
334 | }; | 334 | }; |
335 | 335 | ||
336 | static struct snd_card *usX2Y_create_card(struct usb_device *device) | 336 | static int usX2Y_create_card(struct usb_device *device, struct snd_card **cardp) |
337 | { | 337 | { |
338 | int dev; | 338 | int dev; |
339 | struct snd_card * card; | 339 | struct snd_card * card; |
340 | int err; | ||
341 | |||
340 | for (dev = 0; dev < SNDRV_CARDS; ++dev) | 342 | for (dev = 0; dev < SNDRV_CARDS; ++dev) |
341 | if (enable[dev] && !snd_usX2Y_card_used[dev]) | 343 | if (enable[dev] && !snd_usX2Y_card_used[dev]) |
342 | break; | 344 | break; |
343 | if (dev >= SNDRV_CARDS) | 345 | if (dev >= SNDRV_CARDS) |
344 | return NULL; | 346 | return -ENODEV; |
345 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(struct usX2Ydev)); | 347 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, |
346 | if (!card) | 348 | sizeof(struct usX2Ydev), &card); |
347 | return NULL; | 349 | if (err < 0) |
350 | return err; | ||
348 | snd_usX2Y_card_used[usX2Y(card)->chip.index = dev] = 1; | 351 | snd_usX2Y_card_used[usX2Y(card)->chip.index = dev] = 1; |
349 | card->private_free = snd_usX2Y_card_private_free; | 352 | card->private_free = snd_usX2Y_card_private_free; |
350 | usX2Y(card)->chip.dev = device; | 353 | usX2Y(card)->chip.dev = device; |
@@ -362,26 +365,36 @@ static struct snd_card *usX2Y_create_card(struct usb_device *device) | |||
362 | usX2Y(card)->chip.dev->bus->busnum, usX2Y(card)->chip.dev->devnum | 365 | usX2Y(card)->chip.dev->bus->busnum, usX2Y(card)->chip.dev->devnum |
363 | ); | 366 | ); |
364 | snd_card_set_dev(card, &device->dev); | 367 | snd_card_set_dev(card, &device->dev); |
365 | return card; | 368 | *cardp = card; |
369 | return 0; | ||
366 | } | 370 | } |
367 | 371 | ||
368 | 372 | ||
369 | static void *usX2Y_usb_probe(struct usb_device *device, struct usb_interface *intf, const struct usb_device_id *device_id) | 373 | static int usX2Y_usb_probe(struct usb_device *device, |
374 | struct usb_interface *intf, | ||
375 | const struct usb_device_id *device_id, | ||
376 | struct snd_card **cardp) | ||
370 | { | 377 | { |
371 | int err; | 378 | int err; |
372 | struct snd_card * card; | 379 | struct snd_card * card; |
380 | |||
381 | *cardp = NULL; | ||
373 | if (le16_to_cpu(device->descriptor.idVendor) != 0x1604 || | 382 | if (le16_to_cpu(device->descriptor.idVendor) != 0x1604 || |
374 | (le16_to_cpu(device->descriptor.idProduct) != USB_ID_US122 && | 383 | (le16_to_cpu(device->descriptor.idProduct) != USB_ID_US122 && |
375 | le16_to_cpu(device->descriptor.idProduct) != USB_ID_US224 && | 384 | le16_to_cpu(device->descriptor.idProduct) != USB_ID_US224 && |
376 | le16_to_cpu(device->descriptor.idProduct) != USB_ID_US428) || | 385 | le16_to_cpu(device->descriptor.idProduct) != USB_ID_US428)) |
377 | !(card = usX2Y_create_card(device))) | 386 | return -EINVAL; |
378 | return NULL; | 387 | |
388 | err = usX2Y_create_card(device, &card); | ||
389 | if (err < 0) | ||
390 | return err; | ||
379 | if ((err = usX2Y_hwdep_new(card, device)) < 0 || | 391 | if ((err = usX2Y_hwdep_new(card, device)) < 0 || |
380 | (err = snd_card_register(card)) < 0) { | 392 | (err = snd_card_register(card)) < 0) { |
381 | snd_card_free(card); | 393 | snd_card_free(card); |
382 | return NULL; | 394 | return err; |
383 | } | 395 | } |
384 | return card; | 396 | *cardp = card; |
397 | return 0; | ||
385 | } | 398 | } |
386 | 399 | ||
387 | /* | 400 | /* |
@@ -389,13 +402,14 @@ static void *usX2Y_usb_probe(struct usb_device *device, struct usb_interface *in | |||
389 | */ | 402 | */ |
390 | static int snd_usX2Y_probe(struct usb_interface *intf, const struct usb_device_id *id) | 403 | static int snd_usX2Y_probe(struct usb_interface *intf, const struct usb_device_id *id) |
391 | { | 404 | { |
392 | void *chip; | 405 | struct snd_card *card; |
393 | chip = usX2Y_usb_probe(interface_to_usbdev(intf), intf, id); | 406 | int err; |
394 | if (chip) { | 407 | |
395 | usb_set_intfdata(intf, chip); | 408 | err = usX2Y_usb_probe(interface_to_usbdev(intf), intf, id, &card); |
396 | return 0; | 409 | if (err < 0) |
397 | } else | 410 | return err; |
398 | return -EIO; | 411 | dev_set_drvdata(&intf->dev, card); |
412 | return 0; | ||
399 | } | 413 | } |
400 | 414 | ||
401 | static void snd_usX2Y_disconnect(struct usb_interface *intf) | 415 | static void snd_usX2Y_disconnect(struct usb_interface *intf) |
diff --git a/sound/usb/usx2y/usx2yhwdeppcm.h b/sound/usb/usx2y/usx2yhwdeppcm.h index c3382fdc386b..9c4fb84b2aa0 100644 --- a/sound/usb/usx2y/usx2yhwdeppcm.h +++ b/sound/usb/usx2y/usx2yhwdeppcm.h | |||
@@ -18,3 +18,5 @@ struct snd_usX2Y_hwdep_pcm_shm { | |||
18 | volatile unsigned captured_iso_frames; | 18 | volatile unsigned captured_iso_frames; |
19 | int capture_iso_start; | 19 | int capture_iso_start; |
20 | }; | 20 | }; |
21 | |||
22 | int usX2Y_hwdep_pcm_new(struct snd_card *card); | ||