diff options
Diffstat (limited to 'sound')
303 files changed, 10501 insertions, 5648 deletions
diff --git a/sound/Kconfig b/sound/Kconfig index e48b9b37d228..b2a2db47aff5 100644 --- a/sound/Kconfig +++ b/sound/Kconfig | |||
@@ -63,6 +63,10 @@ source "sound/aoa/Kconfig" | |||
63 | 63 | ||
64 | source "sound/arm/Kconfig" | 64 | source "sound/arm/Kconfig" |
65 | 65 | ||
66 | if SPI | ||
67 | source "sound/spi/Kconfig" | ||
68 | endif | ||
69 | |||
66 | source "sound/mips/Kconfig" | 70 | source "sound/mips/Kconfig" |
67 | 71 | ||
68 | source "sound/sh/Kconfig" | 72 | source "sound/sh/Kconfig" |
diff --git a/sound/Makefile b/sound/Makefile index 3ead922bd9c6..c76d70716fa5 100644 --- a/sound/Makefile +++ b/sound/Makefile | |||
@@ -5,7 +5,8 @@ obj-$(CONFIG_SOUND) += soundcore.o | |||
5 | obj-$(CONFIG_SOUND_PRIME) += sound_firmware.o | 5 | 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/ sparc/ parisc/ pcmcia/ mips/ soc/ | 8 | obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ sh/ synth/ usb/ \ |
9 | sparc/ spi/ parisc/ pcmcia/ mips/ soc/ | ||
9 | obj-$(CONFIG_SND_AOA) += aoa/ | 10 | obj-$(CONFIG_SND_AOA) += aoa/ |
10 | 11 | ||
11 | # 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/codecs/snd-aoa-codec-onyx.c b/sound/aoa/codecs/snd-aoa-codec-onyx.c index 028852374f21..71e3f9360658 100644 --- a/sound/aoa/codecs/snd-aoa-codec-onyx.c +++ b/sound/aoa/codecs/snd-aoa-codec-onyx.c | |||
@@ -297,15 +297,7 @@ static struct snd_kcontrol_new capture_source_control = { | |||
297 | .put = onyx_snd_capture_source_put, | 297 | .put = onyx_snd_capture_source_put, |
298 | }; | 298 | }; |
299 | 299 | ||
300 | static int onyx_snd_mute_info(struct snd_kcontrol *kcontrol, | 300 | #define onyx_snd_mute_info snd_ctl_boolean_stereo_info |
301 | struct snd_ctl_elem_info *uinfo) | ||
302 | { | ||
303 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
304 | uinfo->count = 2; | ||
305 | uinfo->value.integer.min = 0; | ||
306 | uinfo->value.integer.max = 1; | ||
307 | return 0; | ||
308 | } | ||
309 | 301 | ||
310 | static int onyx_snd_mute_get(struct snd_kcontrol *kcontrol, | 302 | static int onyx_snd_mute_get(struct snd_kcontrol *kcontrol, |
311 | struct snd_ctl_elem_value *ucontrol) | 303 | struct snd_ctl_elem_value *ucontrol) |
@@ -359,15 +351,7 @@ static struct snd_kcontrol_new mute_control = { | |||
359 | }; | 351 | }; |
360 | 352 | ||
361 | 353 | ||
362 | static int onyx_snd_single_bit_info(struct snd_kcontrol *kcontrol, | 354 | #define onyx_snd_single_bit_info snd_ctl_boolean_mono_info |
363 | struct snd_ctl_elem_info *uinfo) | ||
364 | { | ||
365 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
366 | uinfo->count = 1; | ||
367 | uinfo->value.integer.min = 0; | ||
368 | uinfo->value.integer.max = 1; | ||
369 | return 0; | ||
370 | } | ||
371 | 355 | ||
372 | #define FLAG_POLARITY_INVERT 1 | 356 | #define FLAG_POLARITY_INVERT 1 |
373 | #define FLAG_SPDIFLOCK 2 | 357 | #define FLAG_SPDIFLOCK 2 |
diff --git a/sound/aoa/codecs/snd-aoa-codec-tas.c b/sound/aoa/codecs/snd-aoa-codec-tas.c index 2f771f57c76f..70c341684794 100644 --- a/sound/aoa/codecs/snd-aoa-codec-tas.c +++ b/sound/aoa/codecs/snd-aoa-codec-tas.c | |||
@@ -272,15 +272,7 @@ static struct snd_kcontrol_new volume_control = { | |||
272 | .put = tas_snd_vol_put, | 272 | .put = tas_snd_vol_put, |
273 | }; | 273 | }; |
274 | 274 | ||
275 | static int tas_snd_mute_info(struct snd_kcontrol *kcontrol, | 275 | #define tas_snd_mute_info snd_ctl_boolean_stereo_info |
276 | struct snd_ctl_elem_info *uinfo) | ||
277 | { | ||
278 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
279 | uinfo->count = 2; | ||
280 | uinfo->value.integer.min = 0; | ||
281 | uinfo->value.integer.max = 1; | ||
282 | return 0; | ||
283 | } | ||
284 | 276 | ||
285 | static int tas_snd_mute_get(struct snd_kcontrol *kcontrol, | 277 | static int tas_snd_mute_get(struct snd_kcontrol *kcontrol, |
286 | struct snd_ctl_elem_value *ucontrol) | 278 | struct snd_ctl_elem_value *ucontrol) |
@@ -431,15 +423,7 @@ static struct snd_kcontrol_new drc_range_control = { | |||
431 | .put = tas_snd_drc_range_put, | 423 | .put = tas_snd_drc_range_put, |
432 | }; | 424 | }; |
433 | 425 | ||
434 | static int tas_snd_drc_switch_info(struct snd_kcontrol *kcontrol, | 426 | #define tas_snd_drc_switch_info snd_ctl_boolean_mono_info |
435 | struct snd_ctl_elem_info *uinfo) | ||
436 | { | ||
437 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
438 | uinfo->count = 1; | ||
439 | uinfo->value.integer.min = 0; | ||
440 | uinfo->value.integer.max = 1; | ||
441 | return 0; | ||
442 | } | ||
443 | 427 | ||
444 | static int tas_snd_drc_switch_get(struct snd_kcontrol *kcontrol, | 428 | static int tas_snd_drc_switch_get(struct snd_kcontrol *kcontrol, |
445 | struct snd_ctl_elem_value *ucontrol) | 429 | struct snd_ctl_elem_value *ucontrol) |
@@ -743,6 +727,7 @@ static int tas_switch_clock(struct codec_info_item *cii, enum clock_switch clock | |||
743 | return 0; | 727 | return 0; |
744 | } | 728 | } |
745 | 729 | ||
730 | #ifdef CONFIG_PM | ||
746 | /* we are controlled via i2c and assume that is always up | 731 | /* we are controlled via i2c and assume that is always up |
747 | * If that wasn't the case, we'd have to suspend once | 732 | * If that wasn't the case, we'd have to suspend once |
748 | * our i2c device is suspended, and then take note of that! */ | 733 | * our i2c device is suspended, and then take note of that! */ |
@@ -768,7 +753,6 @@ static int tas_resume(struct tas *tas) | |||
768 | return 0; | 753 | return 0; |
769 | } | 754 | } |
770 | 755 | ||
771 | #ifdef CONFIG_PM | ||
772 | static int _tas_suspend(struct codec_info_item *cii, pm_message_t state) | 756 | static int _tas_suspend(struct codec_info_item *cii, pm_message_t state) |
773 | { | 757 | { |
774 | return tas_suspend(cii->codec_data); | 758 | return tas_suspend(cii->codec_data); |
@@ -778,7 +762,10 @@ static int _tas_resume(struct codec_info_item *cii) | |||
778 | { | 762 | { |
779 | return tas_resume(cii->codec_data); | 763 | return tas_resume(cii->codec_data); |
780 | } | 764 | } |
781 | #endif | 765 | #else /* CONFIG_PM */ |
766 | #define _tas_suspend NULL | ||
767 | #define _tas_resume NULL | ||
768 | #endif /* CONFIG_PM */ | ||
782 | 769 | ||
783 | static struct codec_info tas_codec_info = { | 770 | static struct codec_info tas_codec_info = { |
784 | .transfers = tas_transfers, | 771 | .transfers = tas_transfers, |
@@ -791,10 +778,8 @@ static struct codec_info tas_codec_info = { | |||
791 | .owner = THIS_MODULE, | 778 | .owner = THIS_MODULE, |
792 | .usable = tas_usable, | 779 | .usable = tas_usable, |
793 | .switch_clock = tas_switch_clock, | 780 | .switch_clock = tas_switch_clock, |
794 | #ifdef CONFIG_PM | ||
795 | .suspend = _tas_suspend, | 781 | .suspend = _tas_suspend, |
796 | .resume = _tas_resume, | 782 | .resume = _tas_resume, |
797 | #endif | ||
798 | }; | 783 | }; |
799 | 784 | ||
800 | static int tas_init_codec(struct aoa_codec *codec) | 785 | static int tas_init_codec(struct aoa_codec *codec) |
diff --git a/sound/aoa/fabrics/snd-aoa-fabric-layout.c b/sound/aoa/fabrics/snd-aoa-fabric-layout.c index 98806283d1b2..8b2ba99d7f8a 100644 --- a/sound/aoa/fabrics/snd-aoa-fabric-layout.c +++ b/sound/aoa/fabrics/snd-aoa-fabric-layout.c | |||
@@ -582,15 +582,7 @@ static int layouts_list_items; | |||
582 | * make the fabric handle all the card stuff, etc... */ | 582 | * make the fabric handle all the card stuff, etc... */ |
583 | static struct layout_dev *layout_device; | 583 | static struct layout_dev *layout_device; |
584 | 584 | ||
585 | static int control_info(struct snd_kcontrol *kcontrol, | 585 | #define control_info snd_ctl_boolean_mono_info |
586 | struct snd_ctl_elem_info *uinfo) | ||
587 | { | ||
588 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
589 | uinfo->count = 1; | ||
590 | uinfo->value.integer.min = 0; | ||
591 | uinfo->value.integer.max = 1; | ||
592 | return 0; | ||
593 | } | ||
594 | 586 | ||
595 | #define AMP_CONTROL(n, description) \ | 587 | #define AMP_CONTROL(n, description) \ |
596 | static int n##_control_get(struct snd_kcontrol *kcontrol, \ | 588 | static int n##_control_get(struct snd_kcontrol *kcontrol, \ |
diff --git a/sound/arm/sa11xx-uda1341.c b/sound/arm/sa11xx-uda1341.c index e7ed868fa7c0..81c64b09d359 100644 --- a/sound/arm/sa11xx-uda1341.c +++ b/sound/arm/sa11xx-uda1341.c | |||
@@ -79,12 +79,6 @@ | |||
79 | #include <asm/mach-types.h> | 79 | #include <asm/mach-types.h> |
80 | #include <asm/dma.h> | 80 | #include <asm/dma.h> |
81 | 81 | ||
82 | #ifdef CONFIG_H3600_HAL | ||
83 | #include <asm/semaphore.h> | ||
84 | #include <asm/uaccess.h> | ||
85 | #include <asm/arch/h3600_hal.h> | ||
86 | #endif | ||
87 | |||
88 | #include <sound/core.h> | 82 | #include <sound/core.h> |
89 | #include <sound/pcm.h> | 83 | #include <sound/pcm.h> |
90 | #include <sound/initval.h> | 84 | #include <sound/initval.h> |
@@ -100,9 +94,6 @@ | |||
100 | * We use DMA stuff from 2.4.18-rmk3-hh24 here to be able to compile this | 94 | * We use DMA stuff from 2.4.18-rmk3-hh24 here to be able to compile this |
101 | * module for Familiar 0.6.1 | 95 | * module for Familiar 0.6.1 |
102 | */ | 96 | */ |
103 | #ifdef CONFIG_H3600_HAL | ||
104 | #define HH_VERSION 1 | ||
105 | #endif | ||
106 | 97 | ||
107 | /* {{{ Type definitions */ | 98 | /* {{{ Type definitions */ |
108 | 99 | ||
@@ -238,11 +229,8 @@ static void sa11xx_uda1341_set_samplerate(struct sa11xx_uda1341 *sa11xx_uda1341, | |||
238 | rate = 8000; | 229 | rate = 8000; |
239 | 230 | ||
240 | /* Set the external clock generator */ | 231 | /* Set the external clock generator */ |
241 | #ifdef CONFIG_H3600_HAL | 232 | |
242 | h3600_audio_clock(rate); | ||
243 | #else | ||
244 | sa11xx_uda1341_set_audio_clock(rate); | 233 | sa11xx_uda1341_set_audio_clock(rate); |
245 | #endif | ||
246 | 234 | ||
247 | /* Select the clock divisor */ | 235 | /* Select the clock divisor */ |
248 | switch (rate) { | 236 | switch (rate) { |
@@ -307,13 +295,10 @@ static void sa11xx_uda1341_audio_init(struct sa11xx_uda1341 *sa11xx_uda1341) | |||
307 | local_irq_restore(flags); | 295 | local_irq_restore(flags); |
308 | 296 | ||
309 | /* Enable the audio power */ | 297 | /* Enable the audio power */ |
310 | #ifdef CONFIG_H3600_HAL | 298 | |
311 | h3600_audio_power(AUDIO_RATE_DEFAULT); | ||
312 | #else | ||
313 | clr_sa11xx_uda1341_egpio(IPAQ_EGPIO_CODEC_NRESET); | 299 | clr_sa11xx_uda1341_egpio(IPAQ_EGPIO_CODEC_NRESET); |
314 | set_sa11xx_uda1341_egpio(IPAQ_EGPIO_AUDIO_ON); | 300 | set_sa11xx_uda1341_egpio(IPAQ_EGPIO_AUDIO_ON); |
315 | set_sa11xx_uda1341_egpio(IPAQ_EGPIO_QMUTE); | 301 | set_sa11xx_uda1341_egpio(IPAQ_EGPIO_QMUTE); |
316 | #endif | ||
317 | 302 | ||
318 | /* Wait for the UDA1341 to wake up */ | 303 | /* Wait for the UDA1341 to wake up */ |
319 | mdelay(1); //FIXME - was removed by Perex - Why? | 304 | mdelay(1); //FIXME - was removed by Perex - Why? |
@@ -331,21 +316,13 @@ static void sa11xx_uda1341_audio_init(struct sa11xx_uda1341 *sa11xx_uda1341) | |||
331 | /* make the left and right channels unswapped (flip the WS latch) */ | 316 | /* make the left and right channels unswapped (flip the WS latch) */ |
332 | Ser4SSDR = 0; | 317 | Ser4SSDR = 0; |
333 | 318 | ||
334 | #ifdef CONFIG_H3600_HAL | 319 | clr_sa11xx_uda1341_egpio(IPAQ_EGPIO_QMUTE); |
335 | h3600_audio_mute(0); | ||
336 | #else | ||
337 | clr_sa11xx_uda1341_egpio(IPAQ_EGPIO_QMUTE); | ||
338 | #endif | ||
339 | } | 320 | } |
340 | 321 | ||
341 | static void sa11xx_uda1341_audio_shutdown(struct sa11xx_uda1341 *sa11xx_uda1341) | 322 | static void sa11xx_uda1341_audio_shutdown(struct sa11xx_uda1341 *sa11xx_uda1341) |
342 | { | 323 | { |
343 | /* mute on */ | 324 | /* mute on */ |
344 | #ifdef CONFIG_H3600_HAL | ||
345 | h3600_audio_mute(1); | ||
346 | #else | ||
347 | set_sa11xx_uda1341_egpio(IPAQ_EGPIO_QMUTE); | 325 | set_sa11xx_uda1341_egpio(IPAQ_EGPIO_QMUTE); |
348 | #endif | ||
349 | 326 | ||
350 | /* disable the audio power and all signals leading to the audio chip */ | 327 | /* disable the audio power and all signals leading to the audio chip */ |
351 | l3_close(sa11xx_uda1341->uda1341); | 328 | l3_close(sa11xx_uda1341->uda1341); |
@@ -354,13 +331,9 @@ static void sa11xx_uda1341_audio_shutdown(struct sa11xx_uda1341 *sa11xx_uda1341) | |||
354 | 331 | ||
355 | /* power off and mute off */ | 332 | /* power off and mute off */ |
356 | /* FIXME - is muting off necesary??? */ | 333 | /* FIXME - is muting off necesary??? */ |
357 | #ifdef CONFIG_H3600_HAL | 334 | |
358 | h3600_audio_power(0); | ||
359 | h3600_audio_mute(0); | ||
360 | #else | ||
361 | clr_sa11xx_uda1341_egpio(IPAQ_EGPIO_AUDIO_ON); | 335 | clr_sa11xx_uda1341_egpio(IPAQ_EGPIO_AUDIO_ON); |
362 | clr_sa11xx_uda1341_egpio(IPAQ_EGPIO_QMUTE); | 336 | clr_sa11xx_uda1341_egpio(IPAQ_EGPIO_QMUTE); |
363 | #endif | ||
364 | } | 337 | } |
365 | 338 | ||
366 | /* }}} */ | 339 | /* }}} */ |
diff --git a/sound/core/Makefile b/sound/core/Makefile index 5a01c76d02e8..267039a97bd5 100644 --- a/sound/core/Makefile +++ b/sound/core/Makefile | |||
@@ -1,20 +1,17 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 1999,2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 1999,2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-objs := sound.o init.o memory.o info.o control.o misc.o device.o | 6 | snd-y := sound.o init.o memory.o info.o control.o misc.o device.o |
7 | ifeq ($(CONFIG_ISA_DMA_API),y) | 7 | snd-$(CONFIG_ISA_DMA_API) += isadma.o |
8 | snd-objs += isadma.o | 8 | snd-$(CONFIG_SND_OSSEMUL) += sound_oss.o info_oss.o |
9 | endif | ||
10 | ifeq ($(CONFIG_SND_OSSEMUL),y) | ||
11 | snd-objs += sound_oss.o info_oss.o | ||
12 | endif | ||
13 | 9 | ||
14 | snd-pcm-objs := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \ | 10 | snd-pcm-objs := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \ |
15 | pcm_memory.o | 11 | pcm_memory.o |
16 | 12 | ||
17 | snd-page-alloc-objs := memalloc.o sgbuf.o | 13 | snd-page-alloc-y := memalloc.o |
14 | snd-page-alloc-$(CONFIG_HAS_DMA) += sgbuf.o | ||
18 | 15 | ||
19 | snd-rawmidi-objs := rawmidi.o | 16 | snd-rawmidi-objs := rawmidi.o |
20 | snd-timer-objs := timer.o | 17 | snd-timer-objs := timer.o |
diff --git a/sound/core/control.c b/sound/core/control.c index 1f1ab9c1b668..4c3aa8e10378 100644 --- a/sound/core/control.c +++ b/sound/core/control.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Routines for driver control interface | 2 | * Routines for driver control interface |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -716,8 +716,6 @@ int snd_ctl_elem_read(struct snd_card *card, struct snd_ctl_elem_value *control) | |||
716 | return result; | 716 | return result; |
717 | } | 717 | } |
718 | 718 | ||
719 | EXPORT_SYMBOL(snd_ctl_elem_read); | ||
720 | |||
721 | static int snd_ctl_elem_read_user(struct snd_card *card, | 719 | static int snd_ctl_elem_read_user(struct snd_card *card, |
722 | struct snd_ctl_elem_value __user *_control) | 720 | struct snd_ctl_elem_value __user *_control) |
723 | { | 721 | { |
@@ -781,8 +779,6 @@ int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file, | |||
781 | return result; | 779 | return result; |
782 | } | 780 | } |
783 | 781 | ||
784 | EXPORT_SYMBOL(snd_ctl_elem_write); | ||
785 | |||
786 | static int snd_ctl_elem_write_user(struct snd_ctl_file *file, | 782 | static int snd_ctl_elem_write_user(struct snd_ctl_file *file, |
787 | struct snd_ctl_elem_value __user *_control) | 783 | struct snd_ctl_elem_value __user *_control) |
788 | { | 784 | { |
@@ -1486,3 +1482,30 @@ int snd_ctl_create(struct snd_card *card) | |||
1486 | snd_assert(card != NULL, return -ENXIO); | 1482 | snd_assert(card != NULL, return -ENXIO); |
1487 | return snd_device_new(card, SNDRV_DEV_CONTROL, card, &ops); | 1483 | return snd_device_new(card, SNDRV_DEV_CONTROL, card, &ops); |
1488 | } | 1484 | } |
1485 | |||
1486 | /* | ||
1487 | * Frequently used control callbacks | ||
1488 | */ | ||
1489 | int snd_ctl_boolean_mono_info(struct snd_kcontrol *kcontrol, | ||
1490 | struct snd_ctl_elem_info *uinfo) | ||
1491 | { | ||
1492 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1493 | uinfo->count = 1; | ||
1494 | uinfo->value.integer.min = 0; | ||
1495 | uinfo->value.integer.max = 1; | ||
1496 | return 0; | ||
1497 | } | ||
1498 | |||
1499 | EXPORT_SYMBOL(snd_ctl_boolean_mono_info); | ||
1500 | |||
1501 | int snd_ctl_boolean_stereo_info(struct snd_kcontrol *kcontrol, | ||
1502 | struct snd_ctl_elem_info *uinfo) | ||
1503 | { | ||
1504 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1505 | uinfo->count = 2; | ||
1506 | uinfo->value.integer.min = 0; | ||
1507 | uinfo->value.integer.max = 1; | ||
1508 | return 0; | ||
1509 | } | ||
1510 | |||
1511 | EXPORT_SYMBOL(snd_ctl_boolean_stereo_info); | ||
diff --git a/sound/core/device.c b/sound/core/device.c index 5858b02b0b1d..ea1a0621eefb 100644 --- a/sound/core/device.c +++ b/sound/core/device.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Device management routines | 2 | * Device management routines |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c index 51ad95b7c894..bfd9d182b8a3 100644 --- a/sound/core/hwdep.c +++ b/sound/core/hwdep.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Hardware dependent layer | 2 | * Hardware dependent layer |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -31,7 +31,7 @@ | |||
31 | #include <sound/hwdep.h> | 31 | #include <sound/hwdep.h> |
32 | #include <sound/info.h> | 32 | #include <sound/info.h> |
33 | 33 | ||
34 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 34 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
35 | MODULE_DESCRIPTION("Hardware dependent layer"); | 35 | MODULE_DESCRIPTION("Hardware dependent layer"); |
36 | MODULE_LICENSE("GPL"); | 36 | MODULE_LICENSE("GPL"); |
37 | 37 | ||
diff --git a/sound/core/info.c b/sound/core/info.c index bf6dbf99528b..1ffd29bb4cd0 100644 --- a/sound/core/info.c +++ b/sound/core/info.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Information interface for ALSA driver | 2 | * Information interface for ALSA driver |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
diff --git a/sound/core/info_oss.c b/sound/core/info_oss.c index a444bfe2cf74..435c9399f7a9 100644 --- a/sound/core/info_oss.c +++ b/sound/core/info_oss.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Information interface for ALSA driver | 2 | * Information interface for ALSA driver |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
diff --git a/sound/core/init.c b/sound/core/init.c index f2fe35737186..2cb7099eb1e1 100644 --- a/sound/core/init.c +++ b/sound/core/init.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Initialization routines | 2 | * Initialization routines |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
diff --git a/sound/core/isadma.c b/sound/core/isadma.c index d52398727f0a..eb173cef4f05 100644 --- a/sound/core/isadma.c +++ b/sound/core/isadma.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * ISA DMA support functions | 2 | * ISA DMA support functions |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c index 9b5656d8bcca..9b4992eab479 100644 --- a/sound/core/memalloc.c +++ b/sound/core/memalloc.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Takashi Iwai <tiwai@suse.de> | 3 | * Takashi Iwai <tiwai@suse.de> |
4 | * | 4 | * |
5 | * Generic memory allocators | 5 | * Generic memory allocators |
@@ -38,7 +38,7 @@ | |||
38 | #endif | 38 | #endif |
39 | 39 | ||
40 | 40 | ||
41 | MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>, Jaroslav Kysela <perex@suse.cz>"); | 41 | MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>, Jaroslav Kysela <perex@perex.cz>"); |
42 | MODULE_DESCRIPTION("Memory allocator for ALSA system."); | 42 | MODULE_DESCRIPTION("Memory allocator for ALSA system."); |
43 | MODULE_LICENSE("GPL"); | 43 | MODULE_LICENSE("GPL"); |
44 | 44 | ||
@@ -206,6 +206,7 @@ void snd_free_pages(void *ptr, size_t size) | |||
206 | * | 206 | * |
207 | */ | 207 | */ |
208 | 208 | ||
209 | #ifdef CONFIG_HAS_DMA | ||
209 | /* allocate the coherent DMA pages */ | 210 | /* allocate the coherent DMA pages */ |
210 | static void *snd_malloc_dev_pages(struct device *dev, size_t size, dma_addr_t *dma) | 211 | static void *snd_malloc_dev_pages(struct device *dev, size_t size, dma_addr_t *dma) |
211 | { | 212 | { |
@@ -239,6 +240,7 @@ static void snd_free_dev_pages(struct device *dev, size_t size, void *ptr, | |||
239 | dec_snd_pages(pg); | 240 | dec_snd_pages(pg); |
240 | dma_free_coherent(dev, PAGE_SIZE << pg, ptr, dma); | 241 | dma_free_coherent(dev, PAGE_SIZE << pg, ptr, dma); |
241 | } | 242 | } |
243 | #endif /* CONFIG_HAS_DMA */ | ||
242 | 244 | ||
243 | #ifdef CONFIG_SBUS | 245 | #ifdef CONFIG_SBUS |
244 | 246 | ||
@@ -312,12 +314,14 @@ int snd_dma_alloc_pages(int type, struct device *device, size_t size, | |||
312 | dmab->area = snd_malloc_sbus_pages(device, size, &dmab->addr); | 314 | dmab->area = snd_malloc_sbus_pages(device, size, &dmab->addr); |
313 | break; | 315 | break; |
314 | #endif | 316 | #endif |
317 | #ifdef CONFIG_HAS_DMA | ||
315 | case SNDRV_DMA_TYPE_DEV: | 318 | case SNDRV_DMA_TYPE_DEV: |
316 | dmab->area = snd_malloc_dev_pages(device, size, &dmab->addr); | 319 | dmab->area = snd_malloc_dev_pages(device, size, &dmab->addr); |
317 | break; | 320 | break; |
318 | case SNDRV_DMA_TYPE_DEV_SG: | 321 | case SNDRV_DMA_TYPE_DEV_SG: |
319 | snd_malloc_sgbuf_pages(device, size, dmab, NULL); | 322 | snd_malloc_sgbuf_pages(device, size, dmab, NULL); |
320 | break; | 323 | break; |
324 | #endif | ||
321 | default: | 325 | default: |
322 | printk(KERN_ERR "snd-malloc: invalid device type %d\n", type); | 326 | printk(KERN_ERR "snd-malloc: invalid device type %d\n", type); |
323 | dmab->area = NULL; | 327 | dmab->area = NULL; |
@@ -383,12 +387,14 @@ void snd_dma_free_pages(struct snd_dma_buffer *dmab) | |||
383 | snd_free_sbus_pages(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr); | 387 | snd_free_sbus_pages(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr); |
384 | break; | 388 | break; |
385 | #endif | 389 | #endif |
390 | #ifdef CONFIG_HAS_DMA | ||
386 | case SNDRV_DMA_TYPE_DEV: | 391 | case SNDRV_DMA_TYPE_DEV: |
387 | snd_free_dev_pages(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr); | 392 | snd_free_dev_pages(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr); |
388 | break; | 393 | break; |
389 | case SNDRV_DMA_TYPE_DEV_SG: | 394 | case SNDRV_DMA_TYPE_DEV_SG: |
390 | snd_free_sgbuf_pages(dmab); | 395 | snd_free_sgbuf_pages(dmab); |
391 | break; | 396 | break; |
397 | #endif | ||
392 | default: | 398 | default: |
393 | printk(KERN_ERR "snd-malloc: invalid device type %d\n", dmab->dev.type); | 399 | printk(KERN_ERR "snd-malloc: invalid device type %d\n", dmab->dev.type); |
394 | } | 400 | } |
diff --git a/sound/core/memory.c b/sound/core/memory.c index 93537ab7c2ac..25b0f056563e 100644 --- a/sound/core/memory.c +++ b/sound/core/memory.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * | 3 | * |
4 | * Misc memory accessors | 4 | * Misc memory accessors |
5 | * | 5 | * |
diff --git a/sound/core/misc.c b/sound/core/misc.c index f78cd000e88d..6cabab8cc537 100644 --- a/sound/core/misc.c +++ b/sound/core/misc.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Misc and compatibility things | 2 | * Misc and compatibility things |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
diff --git a/sound/core/oss/Makefile b/sound/core/oss/Makefile index e6d5a045ba27..10a79453245f 100644 --- a/sound/core/oss/Makefile +++ b/sound/core/oss/Makefile | |||
@@ -1,12 +1,13 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-mixer-oss-objs := mixer_oss.o | 6 | snd-mixer-oss-objs := mixer_oss.o |
7 | 7 | ||
8 | snd-pcm-oss-objs := pcm_oss.o pcm_plugin.o \ | 8 | snd-pcm-oss-y := pcm_oss.o |
9 | io.o copy.o linear.o mulaw.o route.o rate.o | 9 | snd-pcm-oss-$(CONFIG_SND_PCM_OSS_PLUGINS) += pcm_plugin.o \ |
10 | io.o copy.o linear.o mulaw.o route.o rate.o | ||
10 | 11 | ||
11 | obj-$(CONFIG_SND_MIXER_OSS) += snd-mixer-oss.o | 12 | obj-$(CONFIG_SND_MIXER_OSS) += snd-mixer-oss.o |
12 | obj-$(CONFIG_SND_PCM_OSS) += snd-pcm-oss.o | 13 | obj-$(CONFIG_SND_PCM_OSS) += snd-pcm-oss.o |
diff --git a/sound/core/oss/copy.c b/sound/core/oss/copy.c index 6658facc5cda..d6a04c2d5a75 100644 --- a/sound/core/oss/copy.c +++ b/sound/core/oss/copy.c | |||
@@ -20,9 +20,6 @@ | |||
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <sound/driver.h> | 22 | #include <sound/driver.h> |
23 | |||
24 | #ifdef CONFIG_SND_PCM_OSS_PLUGINS | ||
25 | |||
26 | #include <linux/time.h> | 23 | #include <linux/time.h> |
27 | #include <sound/core.h> | 24 | #include <sound/core.h> |
28 | #include <sound/pcm.h> | 25 | #include <sound/pcm.h> |
@@ -88,5 +85,3 @@ int snd_pcm_plugin_build_copy(struct snd_pcm_substream *plug, | |||
88 | *r_plugin = plugin; | 85 | *r_plugin = plugin; |
89 | return 0; | 86 | return 0; |
90 | } | 87 | } |
91 | |||
92 | #endif | ||
diff --git a/sound/core/oss/io.c b/sound/core/oss/io.c index b6e7ce30e5a3..3ece39fc48db 100644 --- a/sound/core/oss/io.c +++ b/sound/core/oss/io.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * PCM I/O Plug-In Interface | 2 | * PCM I/O Plug-In Interface |
3 | * Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This library is free software; you can redistribute it and/or modify | 6 | * This library is free software; you can redistribute it and/or modify |
@@ -20,9 +20,6 @@ | |||
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <sound/driver.h> | 22 | #include <sound/driver.h> |
23 | |||
24 | #ifdef CONFIG_SND_PCM_OSS_PLUGINS | ||
25 | |||
26 | #include <linux/time.h> | 23 | #include <linux/time.h> |
27 | #include <sound/core.h> | 24 | #include <sound/core.h> |
28 | #include <sound/pcm.h> | 25 | #include <sound/pcm.h> |
@@ -135,5 +132,3 @@ int snd_pcm_plugin_build_io(struct snd_pcm_substream *plug, | |||
135 | *r_plugin = plugin; | 132 | *r_plugin = plugin; |
136 | return 0; | 133 | return 0; |
137 | } | 134 | } |
138 | |||
139 | #endif | ||
diff --git a/sound/core/oss/linear.c b/sound/core/oss/linear.c index 5b1bcdc64779..06f96a3e86f6 100644 --- a/sound/core/oss/linear.c +++ b/sound/core/oss/linear.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Linear conversion Plug-In | 2 | * Linear conversion Plug-In |
3 | * Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz>, | 3 | * Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>, |
4 | * Abramo Bagnara <abramo@alsa-project.org> | 4 | * Abramo Bagnara <abramo@alsa-project.org> |
5 | * | 5 | * |
6 | * | 6 | * |
@@ -21,9 +21,6 @@ | |||
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <sound/driver.h> | 23 | #include <sound/driver.h> |
24 | |||
25 | #ifdef CONFIG_SND_PCM_OSS_PLUGINS | ||
26 | |||
27 | #include <linux/time.h> | 24 | #include <linux/time.h> |
28 | #include <sound/core.h> | 25 | #include <sound/core.h> |
29 | #include <sound/pcm.h> | 26 | #include <sound/pcm.h> |
@@ -34,19 +31,34 @@ | |||
34 | */ | 31 | */ |
35 | 32 | ||
36 | struct linear_priv { | 33 | struct linear_priv { |
37 | int conv; | 34 | int cvt_endian; /* need endian conversion? */ |
35 | unsigned int src_ofs; /* byte offset in source format */ | ||
36 | unsigned int dst_ofs; /* byte soffset in destination format */ | ||
37 | unsigned int copy_ofs; /* byte offset in temporary u32 data */ | ||
38 | unsigned int dst_bytes; /* byte size of destination format */ | ||
39 | unsigned int copy_bytes; /* bytes to copy per conversion */ | ||
40 | unsigned int flip; /* MSB flip for signeness, done after endian conv */ | ||
38 | }; | 41 | }; |
39 | 42 | ||
43 | static inline void do_convert(struct linear_priv *data, | ||
44 | unsigned char *dst, unsigned char *src) | ||
45 | { | ||
46 | unsigned int tmp = 0; | ||
47 | unsigned char *p = (unsigned char *)&tmp; | ||
48 | |||
49 | memcpy(p + data->copy_ofs, src + data->src_ofs, data->copy_bytes); | ||
50 | if (data->cvt_endian) | ||
51 | tmp = swab32(tmp); | ||
52 | tmp ^= data->flip; | ||
53 | memcpy(dst, p + data->dst_ofs, data->dst_bytes); | ||
54 | } | ||
55 | |||
40 | static void convert(struct snd_pcm_plugin *plugin, | 56 | static void convert(struct snd_pcm_plugin *plugin, |
41 | const struct snd_pcm_plugin_channel *src_channels, | 57 | const struct snd_pcm_plugin_channel *src_channels, |
42 | struct snd_pcm_plugin_channel *dst_channels, | 58 | struct snd_pcm_plugin_channel *dst_channels, |
43 | snd_pcm_uframes_t frames) | 59 | snd_pcm_uframes_t frames) |
44 | { | 60 | { |
45 | #define CONV_LABELS | ||
46 | #include "plugin_ops.h" | ||
47 | #undef CONV_LABELS | ||
48 | struct linear_priv *data = (struct linear_priv *)plugin->extra_data; | 61 | struct linear_priv *data = (struct linear_priv *)plugin->extra_data; |
49 | void *conv = conv_labels[data->conv]; | ||
50 | int channel; | 62 | int channel; |
51 | int nchannels = plugin->src_format.channels; | 63 | int nchannels = plugin->src_format.channels; |
52 | for (channel = 0; channel < nchannels; ++channel) { | 64 | for (channel = 0; channel < nchannels; ++channel) { |
@@ -67,11 +79,7 @@ static void convert(struct snd_pcm_plugin *plugin, | |||
67 | dst_step = dst_channels[channel].area.step / 8; | 79 | dst_step = dst_channels[channel].area.step / 8; |
68 | frames1 = frames; | 80 | frames1 = frames; |
69 | while (frames1-- > 0) { | 81 | while (frames1-- > 0) { |
70 | goto *conv; | 82 | do_convert(data, dst, src); |
71 | #define CONV_END after | ||
72 | #include "plugin_ops.h" | ||
73 | #undef CONV_END | ||
74 | after: | ||
75 | src += src_step; | 83 | src += src_step; |
76 | dst += dst_step; | 84 | dst += dst_step; |
77 | } | 85 | } |
@@ -106,29 +114,36 @@ static snd_pcm_sframes_t linear_transfer(struct snd_pcm_plugin *plugin, | |||
106 | return frames; | 114 | return frames; |
107 | } | 115 | } |
108 | 116 | ||
109 | static int conv_index(int src_format, int dst_format) | 117 | static void init_data(struct linear_priv *data, int src_format, int dst_format) |
110 | { | 118 | { |
111 | int src_endian, dst_endian, sign, src_width, dst_width; | 119 | int src_le, dst_le, src_bytes, dst_bytes; |
112 | 120 | ||
113 | sign = (snd_pcm_format_signed(src_format) != | 121 | src_bytes = snd_pcm_format_width(src_format) / 8; |
114 | snd_pcm_format_signed(dst_format)); | 122 | dst_bytes = snd_pcm_format_width(dst_format) / 8; |
115 | #ifdef SNDRV_LITTLE_ENDIAN | 123 | src_le = snd_pcm_format_little_endian(src_format) > 0; |
116 | src_endian = snd_pcm_format_big_endian(src_format); | 124 | dst_le = snd_pcm_format_little_endian(dst_format) > 0; |
117 | dst_endian = snd_pcm_format_big_endian(dst_format); | 125 | |
118 | #else | 126 | data->dst_bytes = dst_bytes; |
119 | src_endian = snd_pcm_format_little_endian(src_format); | 127 | data->cvt_endian = src_le != dst_le; |
120 | dst_endian = snd_pcm_format_little_endian(dst_format); | 128 | data->copy_bytes = src_bytes < dst_bytes ? src_bytes : dst_bytes; |
121 | #endif | 129 | if (src_le) { |
122 | 130 | data->copy_ofs = 4 - data->copy_bytes; | |
123 | if (src_endian < 0) | 131 | data->src_ofs = src_bytes - data->copy_bytes; |
124 | src_endian = 0; | 132 | } else |
125 | if (dst_endian < 0) | 133 | data->src_ofs = snd_pcm_format_physical_width(src_format) / 8 - |
126 | dst_endian = 0; | 134 | src_bytes; |
127 | 135 | if (dst_le) | |
128 | src_width = snd_pcm_format_width(src_format) / 8 - 1; | 136 | data->dst_ofs = 4 - data->dst_bytes; |
129 | dst_width = snd_pcm_format_width(dst_format) / 8 - 1; | 137 | else |
130 | 138 | data->dst_ofs = snd_pcm_format_physical_width(dst_format) / 8 - | |
131 | return src_width * 32 + src_endian * 16 + sign * 8 + dst_width * 2 + dst_endian; | 139 | dst_bytes; |
140 | if (snd_pcm_format_signed(src_format) != | ||
141 | snd_pcm_format_signed(dst_format)) { | ||
142 | if (dst_le) | ||
143 | data->flip = cpu_to_le32(0x80000000); | ||
144 | else | ||
145 | data->flip = cpu_to_be32(0x80000000); | ||
146 | } | ||
132 | } | 147 | } |
133 | 148 | ||
134 | int snd_pcm_plugin_build_linear(struct snd_pcm_substream *plug, | 149 | int snd_pcm_plugin_build_linear(struct snd_pcm_substream *plug, |
@@ -154,10 +169,8 @@ int snd_pcm_plugin_build_linear(struct snd_pcm_substream *plug, | |||
154 | if (err < 0) | 169 | if (err < 0) |
155 | return err; | 170 | return err; |
156 | data = (struct linear_priv *)plugin->extra_data; | 171 | data = (struct linear_priv *)plugin->extra_data; |
157 | data->conv = conv_index(src_format->format, dst_format->format); | 172 | init_data(data, src_format->format, dst_format->format); |
158 | plugin->transfer = linear_transfer; | 173 | plugin->transfer = linear_transfer; |
159 | *r_plugin = plugin; | 174 | *r_plugin = plugin; |
160 | return 0; | 175 | return 0; |
161 | } | 176 | } |
162 | |||
163 | #endif | ||
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index fccad8f0a6bb..3ace4a5680ba 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * OSS emulation layer for the mixer interface | 2 | * OSS emulation layer for the mixer interface |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -33,7 +33,7 @@ | |||
33 | 33 | ||
34 | #define OSS_ALSAEMULVER _SIOR ('M', 249, int) | 34 | #define OSS_ALSAEMULVER _SIOR ('M', 249, int) |
35 | 35 | ||
36 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 36 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
37 | MODULE_DESCRIPTION("Mixer OSS emulation for ALSA."); | 37 | MODULE_DESCRIPTION("Mixer OSS emulation for ALSA."); |
38 | MODULE_LICENSE("GPL"); | 38 | MODULE_LICENSE("GPL"); |
39 | MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_MIXER); | 39 | MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_MIXER); |
diff --git a/sound/core/oss/mulaw.c b/sound/core/oss/mulaw.c index 2eb18807e6d0..848db82529ed 100644 --- a/sound/core/oss/mulaw.c +++ b/sound/core/oss/mulaw.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Mu-Law conversion Plug-In Interface | 2 | * Mu-Law conversion Plug-In Interface |
3 | * Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz> |
4 | * Uros Bizjak <uros@kss-loka.si> | 4 | * Uros Bizjak <uros@kss-loka.si> |
5 | * | 5 | * |
6 | * Based on reference implementation by Sun Microsystems, Inc. | 6 | * Based on reference implementation by Sun Microsystems, Inc. |
@@ -22,9 +22,6 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <sound/driver.h> | 24 | #include <sound/driver.h> |
25 | |||
26 | #ifdef CONFIG_SND_PCM_OSS_PLUGINS | ||
27 | |||
28 | #include <linux/time.h> | 25 | #include <linux/time.h> |
29 | #include <sound/core.h> | 26 | #include <sound/core.h> |
30 | #include <sound/pcm.h> | 27 | #include <sound/pcm.h> |
@@ -149,19 +146,32 @@ typedef void (*mulaw_f)(struct snd_pcm_plugin *plugin, | |||
149 | 146 | ||
150 | struct mulaw_priv { | 147 | struct mulaw_priv { |
151 | mulaw_f func; | 148 | mulaw_f func; |
152 | int conv; | 149 | int cvt_endian; /* need endian conversion? */ |
150 | unsigned int native_ofs; /* byte offset in native format */ | ||
151 | unsigned int copy_ofs; /* byte offset in s16 format */ | ||
152 | unsigned int native_bytes; /* byte size of the native format */ | ||
153 | unsigned int copy_bytes; /* bytes to copy per conversion */ | ||
154 | u16 flip; /* MSB flip for signedness, done after endian conversion */ | ||
153 | }; | 155 | }; |
154 | 156 | ||
157 | static inline void cvt_s16_to_native(struct mulaw_priv *data, | ||
158 | unsigned char *dst, u16 sample) | ||
159 | { | ||
160 | sample ^= data->flip; | ||
161 | if (data->cvt_endian) | ||
162 | sample = swab16(sample); | ||
163 | if (data->native_bytes > data->copy_bytes) | ||
164 | memset(dst, 0, data->native_bytes); | ||
165 | memcpy(dst + data->native_ofs, (char *)&sample + data->copy_ofs, | ||
166 | data->copy_bytes); | ||
167 | } | ||
168 | |||
155 | static void mulaw_decode(struct snd_pcm_plugin *plugin, | 169 | static void mulaw_decode(struct snd_pcm_plugin *plugin, |
156 | const struct snd_pcm_plugin_channel *src_channels, | 170 | const struct snd_pcm_plugin_channel *src_channels, |
157 | struct snd_pcm_plugin_channel *dst_channels, | 171 | struct snd_pcm_plugin_channel *dst_channels, |
158 | snd_pcm_uframes_t frames) | 172 | snd_pcm_uframes_t frames) |
159 | { | 173 | { |
160 | #define PUT_S16_LABELS | ||
161 | #include "plugin_ops.h" | ||
162 | #undef PUT_S16_LABELS | ||
163 | struct mulaw_priv *data = (struct mulaw_priv *)plugin->extra_data; | 174 | struct mulaw_priv *data = (struct mulaw_priv *)plugin->extra_data; |
164 | void *put = put_s16_labels[data->conv]; | ||
165 | int channel; | 175 | int channel; |
166 | int nchannels = plugin->src_format.channels; | 176 | int nchannels = plugin->src_format.channels; |
167 | for (channel = 0; channel < nchannels; ++channel) { | 177 | for (channel = 0; channel < nchannels; ++channel) { |
@@ -183,30 +193,33 @@ static void mulaw_decode(struct snd_pcm_plugin *plugin, | |||
183 | frames1 = frames; | 193 | frames1 = frames; |
184 | while (frames1-- > 0) { | 194 | while (frames1-- > 0) { |
185 | signed short sample = ulaw2linear(*src); | 195 | signed short sample = ulaw2linear(*src); |
186 | goto *put; | 196 | cvt_s16_to_native(data, dst, sample); |
187 | #define PUT_S16_END after | ||
188 | #include "plugin_ops.h" | ||
189 | #undef PUT_S16_END | ||
190 | after: | ||
191 | src += src_step; | 197 | src += src_step; |
192 | dst += dst_step; | 198 | dst += dst_step; |
193 | } | 199 | } |
194 | } | 200 | } |
195 | } | 201 | } |
196 | 202 | ||
203 | static inline signed short cvt_native_to_s16(struct mulaw_priv *data, | ||
204 | unsigned char *src) | ||
205 | { | ||
206 | u16 sample = 0; | ||
207 | memcpy((char *)&sample + data->copy_ofs, src + data->native_ofs, | ||
208 | data->copy_bytes); | ||
209 | if (data->cvt_endian) | ||
210 | sample = swab16(sample); | ||
211 | sample ^= data->flip; | ||
212 | return (signed short)sample; | ||
213 | } | ||
214 | |||
197 | static void mulaw_encode(struct snd_pcm_plugin *plugin, | 215 | static void mulaw_encode(struct snd_pcm_plugin *plugin, |
198 | const struct snd_pcm_plugin_channel *src_channels, | 216 | const struct snd_pcm_plugin_channel *src_channels, |
199 | struct snd_pcm_plugin_channel *dst_channels, | 217 | struct snd_pcm_plugin_channel *dst_channels, |
200 | snd_pcm_uframes_t frames) | 218 | snd_pcm_uframes_t frames) |
201 | { | 219 | { |
202 | #define GET_S16_LABELS | ||
203 | #include "plugin_ops.h" | ||
204 | #undef GET_S16_LABELS | ||
205 | struct mulaw_priv *data = (struct mulaw_priv *)plugin->extra_data; | 220 | struct mulaw_priv *data = (struct mulaw_priv *)plugin->extra_data; |
206 | void *get = get_s16_labels[data->conv]; | ||
207 | int channel; | 221 | int channel; |
208 | int nchannels = plugin->src_format.channels; | 222 | int nchannels = plugin->src_format.channels; |
209 | signed short sample = 0; | ||
210 | for (channel = 0; channel < nchannels; ++channel) { | 223 | for (channel = 0; channel < nchannels; ++channel) { |
211 | char *src; | 224 | char *src; |
212 | char *dst; | 225 | char *dst; |
@@ -225,11 +238,7 @@ static void mulaw_encode(struct snd_pcm_plugin *plugin, | |||
225 | dst_step = dst_channels[channel].area.step / 8; | 238 | dst_step = dst_channels[channel].area.step / 8; |
226 | frames1 = frames; | 239 | frames1 = frames; |
227 | while (frames1-- > 0) { | 240 | while (frames1-- > 0) { |
228 | goto *get; | 241 | signed short sample = cvt_native_to_s16(data, src); |
229 | #define GET_S16_END after | ||
230 | #include "plugin_ops.h" | ||
231 | #undef GET_S16_END | ||
232 | after: | ||
233 | *dst = linear2ulaw(sample); | 242 | *dst = linear2ulaw(sample); |
234 | src += src_step; | 243 | src += src_step; |
235 | dst += dst_step; | 244 | dst += dst_step; |
@@ -265,23 +274,25 @@ static snd_pcm_sframes_t mulaw_transfer(struct snd_pcm_plugin *plugin, | |||
265 | return frames; | 274 | return frames; |
266 | } | 275 | } |
267 | 276 | ||
268 | static int getput_index(int format) | 277 | static void init_data(struct mulaw_priv *data, int format) |
269 | { | 278 | { |
270 | int sign, width, endian; | ||
271 | sign = !snd_pcm_format_signed(format); | ||
272 | width = snd_pcm_format_width(format) / 8 - 1; | ||
273 | if (width < 0 || width > 3) { | ||
274 | snd_printk(KERN_ERR "snd-pcm-oss: invalid format %d\n", format); | ||
275 | width = 0; | ||
276 | } | ||
277 | #ifdef SNDRV_LITTLE_ENDIAN | 279 | #ifdef SNDRV_LITTLE_ENDIAN |
278 | endian = snd_pcm_format_big_endian(format); | 280 | data->cvt_endian = snd_pcm_format_big_endian(format) > 0; |
279 | #else | 281 | #else |
280 | endian = snd_pcm_format_little_endian(format); | 282 | data->cvt_endian = snd_pcm_format_little_endian(format) > 0; |
281 | #endif | 283 | #endif |
282 | if (endian < 0) | 284 | if (!snd_pcm_format_signed(format)) |
283 | endian = 0; | 285 | data->flip = 0x8000; |
284 | return width * 4 + endian * 2 + sign; | 286 | data->native_bytes = snd_pcm_format_physical_width(format) / 8; |
287 | data->copy_bytes = data->native_bytes < 2 ? 1 : 2; | ||
288 | if (snd_pcm_format_little_endian(format)) { | ||
289 | data->native_ofs = data->native_bytes - data->copy_bytes; | ||
290 | data->copy_ofs = 2 - data->copy_bytes; | ||
291 | } else { | ||
292 | /* S24 in 4bytes need an 1 byte offset */ | ||
293 | data->native_ofs = data->native_bytes - | ||
294 | snd_pcm_format_width(format) / 8; | ||
295 | } | ||
285 | } | 296 | } |
286 | 297 | ||
287 | int snd_pcm_plugin_build_mulaw(struct snd_pcm_substream *plug, | 298 | int snd_pcm_plugin_build_mulaw(struct snd_pcm_substream *plug, |
@@ -322,11 +333,8 @@ int snd_pcm_plugin_build_mulaw(struct snd_pcm_substream *plug, | |||
322 | return err; | 333 | return err; |
323 | data = (struct mulaw_priv *)plugin->extra_data; | 334 | data = (struct mulaw_priv *)plugin->extra_data; |
324 | data->func = func; | 335 | data->func = func; |
325 | data->conv = getput_index(format->format); | 336 | init_data(data, format->format); |
326 | snd_assert(data->conv >= 0 && data->conv < 4*2*2, return -EINVAL); | ||
327 | plugin->transfer = mulaw_transfer; | 337 | plugin->transfer = mulaw_transfer; |
328 | *r_plugin = plugin; | 338 | *r_plugin = plugin; |
329 | return 0; | 339 | return 0; |
330 | } | 340 | } |
331 | |||
332 | #endif | ||
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index fc11572c48cf..d0c4ceb9f0b4 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Digital Audio (PCM) abstract layer / OSS compatible | 2 | * Digital Audio (PCM) abstract layer / OSS compatible |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -48,7 +48,7 @@ static int dsp_map[SNDRV_CARDS]; | |||
48 | static int adsp_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1}; | 48 | static int adsp_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1}; |
49 | static int nonblock_open = 1; | 49 | static int nonblock_open = 1; |
50 | 50 | ||
51 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Abramo Bagnara <abramo@alsa-project.org>"); | 51 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Abramo Bagnara <abramo@alsa-project.org>"); |
52 | MODULE_DESCRIPTION("PCM OSS emulation for ALSA."); | 52 | MODULE_DESCRIPTION("PCM OSS emulation for ALSA."); |
53 | MODULE_LICENSE("GPL"); | 53 | MODULE_LICENSE("GPL"); |
54 | module_param_array(dsp_map, int, NULL, 0444); | 54 | module_param_array(dsp_map, int, NULL, 0444); |
@@ -633,6 +633,22 @@ static long snd_pcm_alsa_frames(struct snd_pcm_substream *substream, long bytes) | |||
633 | return bytes_to_frames(runtime, (buffer_size * bytes) / runtime->oss.buffer_bytes); | 633 | return bytes_to_frames(runtime, (buffer_size * bytes) / runtime->oss.buffer_bytes); |
634 | } | 634 | } |
635 | 635 | ||
636 | /* define extended formats in the recent OSS versions (if any) */ | ||
637 | /* linear formats */ | ||
638 | #define AFMT_S32_LE 0x00001000 | ||
639 | #define AFMT_S32_BE 0x00002000 | ||
640 | #define AFMT_S24_LE 0x00008000 | ||
641 | #define AFMT_S24_BE 0x00010000 | ||
642 | #define AFMT_S24_PACKED 0x00040000 | ||
643 | |||
644 | /* other supported formats */ | ||
645 | #define AFMT_FLOAT 0x00004000 | ||
646 | #define AFMT_SPDIF_RAW 0x00020000 | ||
647 | |||
648 | /* unsupported formats */ | ||
649 | #define AFMT_AC3 0x00000400 | ||
650 | #define AFMT_VORBIS 0x00000800 | ||
651 | |||
636 | static int snd_pcm_oss_format_from(int format) | 652 | static int snd_pcm_oss_format_from(int format) |
637 | { | 653 | { |
638 | switch (format) { | 654 | switch (format) { |
@@ -646,6 +662,13 @@ static int snd_pcm_oss_format_from(int format) | |||
646 | case AFMT_U16_LE: return SNDRV_PCM_FORMAT_U16_LE; | 662 | case AFMT_U16_LE: return SNDRV_PCM_FORMAT_U16_LE; |
647 | case AFMT_U16_BE: return SNDRV_PCM_FORMAT_U16_BE; | 663 | case AFMT_U16_BE: return SNDRV_PCM_FORMAT_U16_BE; |
648 | case AFMT_MPEG: return SNDRV_PCM_FORMAT_MPEG; | 664 | case AFMT_MPEG: return SNDRV_PCM_FORMAT_MPEG; |
665 | case AFMT_S32_LE: return SNDRV_PCM_FORMAT_S32_LE; | ||
666 | case AFMT_S32_BE: return SNDRV_PCM_FORMAT_S32_BE; | ||
667 | case AFMT_S24_LE: return SNDRV_PCM_FORMAT_S24_LE; | ||
668 | case AFMT_S24_BE: return SNDRV_PCM_FORMAT_S24_BE; | ||
669 | case AFMT_S24_PACKED: return SNDRV_PCM_FORMAT_S24_3LE; | ||
670 | case AFMT_FLOAT: return SNDRV_PCM_FORMAT_FLOAT; | ||
671 | case AFMT_SPDIF_RAW: return SNDRV_PCM_FORMAT_IEC958_SUBFRAME; | ||
649 | default: return SNDRV_PCM_FORMAT_U8; | 672 | default: return SNDRV_PCM_FORMAT_U8; |
650 | } | 673 | } |
651 | } | 674 | } |
@@ -663,6 +686,13 @@ static int snd_pcm_oss_format_to(int format) | |||
663 | case SNDRV_PCM_FORMAT_U16_LE: return AFMT_U16_LE; | 686 | case SNDRV_PCM_FORMAT_U16_LE: return AFMT_U16_LE; |
664 | case SNDRV_PCM_FORMAT_U16_BE: return AFMT_U16_BE; | 687 | case SNDRV_PCM_FORMAT_U16_BE: return AFMT_U16_BE; |
665 | case SNDRV_PCM_FORMAT_MPEG: return AFMT_MPEG; | 688 | case SNDRV_PCM_FORMAT_MPEG: return AFMT_MPEG; |
689 | case SNDRV_PCM_FORMAT_S32_LE: return AFMT_S32_LE; | ||
690 | case SNDRV_PCM_FORMAT_S32_BE: return AFMT_S32_BE; | ||
691 | case SNDRV_PCM_FORMAT_S24_LE: return AFMT_S24_LE; | ||
692 | case SNDRV_PCM_FORMAT_S24_BE: return AFMT_S24_BE; | ||
693 | case SNDRV_PCM_FORMAT_S24_3LE: return AFMT_S24_PACKED; | ||
694 | case SNDRV_PCM_FORMAT_FLOAT: return AFMT_FLOAT; | ||
695 | case SNDRV_PCM_FORMAT_IEC958_SUBFRAME: return AFMT_SPDIF_RAW; | ||
666 | default: return -EINVAL; | 696 | default: return -EINVAL; |
667 | } | 697 | } |
668 | } | 698 | } |
@@ -1725,7 +1755,10 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file) | |||
1725 | return AFMT_MU_LAW | AFMT_U8 | | 1755 | return AFMT_MU_LAW | AFMT_U8 | |
1726 | AFMT_S16_LE | AFMT_S16_BE | | 1756 | AFMT_S16_LE | AFMT_S16_BE | |
1727 | AFMT_S8 | AFMT_U16_LE | | 1757 | AFMT_S8 | AFMT_U16_LE | |
1728 | AFMT_U16_BE; | 1758 | AFMT_U16_BE | |
1759 | AFMT_S32_LE | AFMT_S32_BE | | ||
1760 | AFMT_S24_LE | AFMT_S24_LE | | ||
1761 | AFMT_S24_PACKED; | ||
1729 | params = kmalloc(sizeof(*params), GFP_KERNEL); | 1762 | params = kmalloc(sizeof(*params), GFP_KERNEL); |
1730 | if (!params) | 1763 | if (!params) |
1731 | return -ENOMEM; | 1764 | return -ENOMEM; |
diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c index 0e67dd280a5d..14095a927a1b 100644 --- a/sound/core/oss/pcm_plugin.c +++ b/sound/core/oss/pcm_plugin.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * PCM Plug-In shared (kernel/library) code | 2 | * PCM Plug-In shared (kernel/library) code |
3 | * Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz> |
4 | * Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org> | 4 | * Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org> |
5 | * | 5 | * |
6 | * | 6 | * |
@@ -25,9 +25,6 @@ | |||
25 | #endif | 25 | #endif |
26 | 26 | ||
27 | #include <sound/driver.h> | 27 | #include <sound/driver.h> |
28 | |||
29 | #ifdef CONFIG_SND_PCM_OSS_PLUGINS | ||
30 | |||
31 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
32 | #include <linux/time.h> | 29 | #include <linux/time.h> |
33 | #include <linux/vmalloc.h> | 30 | #include <linux/vmalloc.h> |
@@ -267,6 +264,8 @@ static int snd_pcm_plug_formats(struct snd_mask *mask, int format) | |||
267 | SNDRV_PCM_FMTBIT_U16_BE | SNDRV_PCM_FMTBIT_S16_BE | | 264 | SNDRV_PCM_FMTBIT_U16_BE | SNDRV_PCM_FMTBIT_S16_BE | |
268 | SNDRV_PCM_FMTBIT_U24_LE | SNDRV_PCM_FMTBIT_S24_LE | | 265 | SNDRV_PCM_FMTBIT_U24_LE | SNDRV_PCM_FMTBIT_S24_LE | |
269 | SNDRV_PCM_FMTBIT_U24_BE | SNDRV_PCM_FMTBIT_S24_BE | | 266 | SNDRV_PCM_FMTBIT_U24_BE | SNDRV_PCM_FMTBIT_S24_BE | |
267 | SNDRV_PCM_FMTBIT_U24_3LE | SNDRV_PCM_FMTBIT_S24_3LE | | ||
268 | SNDRV_PCM_FMTBIT_U24_3BE | SNDRV_PCM_FMTBIT_S24_3BE | | ||
270 | SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_S32_LE | | 269 | SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_S32_LE | |
271 | SNDRV_PCM_FMTBIT_U32_BE | SNDRV_PCM_FMTBIT_S32_BE); | 270 | SNDRV_PCM_FMTBIT_U32_BE | SNDRV_PCM_FMTBIT_S32_BE); |
272 | snd_mask_set(&formats, SNDRV_PCM_FORMAT_MU_LAW); | 271 | snd_mask_set(&formats, SNDRV_PCM_FORMAT_MU_LAW); |
@@ -283,6 +282,10 @@ static int preferred_formats[] = { | |||
283 | SNDRV_PCM_FORMAT_S16_BE, | 282 | SNDRV_PCM_FORMAT_S16_BE, |
284 | SNDRV_PCM_FORMAT_U16_LE, | 283 | SNDRV_PCM_FORMAT_U16_LE, |
285 | SNDRV_PCM_FORMAT_U16_BE, | 284 | SNDRV_PCM_FORMAT_U16_BE, |
285 | SNDRV_PCM_FORMAT_S24_3LE, | ||
286 | SNDRV_PCM_FORMAT_S24_3BE, | ||
287 | SNDRV_PCM_FORMAT_U24_3LE, | ||
288 | SNDRV_PCM_FORMAT_U24_3BE, | ||
286 | SNDRV_PCM_FORMAT_S24_LE, | 289 | SNDRV_PCM_FORMAT_S24_LE, |
287 | SNDRV_PCM_FORMAT_S24_BE, | 290 | SNDRV_PCM_FORMAT_S24_BE, |
288 | SNDRV_PCM_FORMAT_U24_LE, | 291 | SNDRV_PCM_FORMAT_U24_LE, |
@@ -297,41 +300,37 @@ static int preferred_formats[] = { | |||
297 | 300 | ||
298 | int snd_pcm_plug_slave_format(int format, struct snd_mask *format_mask) | 301 | int snd_pcm_plug_slave_format(int format, struct snd_mask *format_mask) |
299 | { | 302 | { |
303 | int i; | ||
304 | |||
300 | if (snd_mask_test(format_mask, format)) | 305 | if (snd_mask_test(format_mask, format)) |
301 | return format; | 306 | return format; |
302 | if (! snd_pcm_plug_formats(format_mask, format)) | 307 | if (! snd_pcm_plug_formats(format_mask, format)) |
303 | return -EINVAL; | 308 | return -EINVAL; |
304 | if (snd_pcm_format_linear(format)) { | 309 | if (snd_pcm_format_linear(format)) { |
305 | int width = snd_pcm_format_width(format); | 310 | unsigned int width = snd_pcm_format_width(format); |
306 | int unsignd = snd_pcm_format_unsigned(format); | 311 | int unsignd = snd_pcm_format_unsigned(format) > 0; |
307 | int big = snd_pcm_format_big_endian(format); | 312 | int big = snd_pcm_format_big_endian(format) > 0; |
308 | int format1; | 313 | unsigned int badness, best = -1; |
309 | int wid, width1=width; | 314 | int best_format = -1; |
310 | int dwidth1 = 8; | 315 | for (i = 0; i < ARRAY_SIZE(preferred_formats); i++) { |
311 | for (wid = 0; wid < 4; ++wid) { | 316 | int f = preferred_formats[i]; |
312 | int end, big1 = big; | 317 | unsigned int w; |
313 | for (end = 0; end < 2; ++end) { | 318 | if (!snd_mask_test(format_mask, f)) |
314 | int sgn, unsignd1 = unsignd; | 319 | continue; |
315 | for (sgn = 0; sgn < 2; ++sgn) { | 320 | w = snd_pcm_format_width(f); |
316 | format1 = snd_pcm_build_linear_format(width1, unsignd1, big1); | 321 | if (w >= width) |
317 | if (format1 >= 0 && | 322 | badness = w - width; |
318 | snd_mask_test(format_mask, format1)) | 323 | else |
319 | goto _found; | 324 | badness = width - w + 32; |
320 | unsignd1 = !unsignd1; | 325 | badness += snd_pcm_format_unsigned(f) != unsignd; |
321 | } | 326 | badness += snd_pcm_format_big_endian(f) != big; |
322 | big1 = !big1; | 327 | if (badness < best) { |
323 | } | 328 | best_format = f; |
324 | if (width1 == 32) { | 329 | best = badness; |
325 | dwidth1 = -dwidth1; | ||
326 | width1 = width; | ||
327 | } | 330 | } |
328 | width1 += dwidth1; | ||
329 | } | 331 | } |
330 | return -EINVAL; | 332 | return best_format >= 0 ? best_format : -EINVAL; |
331 | _found: | ||
332 | return format1; | ||
333 | } else { | 333 | } else { |
334 | unsigned int i; | ||
335 | switch (format) { | 334 | switch (format) { |
336 | case SNDRV_PCM_FORMAT_MU_LAW: | 335 | case SNDRV_PCM_FORMAT_MU_LAW: |
337 | for (i = 0; i < ARRAY_SIZE(preferred_formats); ++i) { | 336 | for (i = 0; i < ARRAY_SIZE(preferred_formats); ++i) { |
@@ -740,5 +739,3 @@ int snd_pcm_area_copy(const struct snd_pcm_channel_area *src_area, size_t src_of | |||
740 | } | 739 | } |
741 | return 0; | 740 | return 0; |
742 | } | 741 | } |
743 | |||
744 | #endif | ||
diff --git a/sound/core/oss/pcm_plugin.h b/sound/core/oss/pcm_plugin.h index 3be91b3d5377..ca2f4c39be46 100644 --- a/sound/core/oss/pcm_plugin.h +++ b/sound/core/oss/pcm_plugin.h | |||
@@ -3,7 +3,7 @@ | |||
3 | 3 | ||
4 | /* | 4 | /* |
5 | * Digital Audio (Plugin interface) abstract layer | 5 | * Digital Audio (Plugin interface) abstract layer |
6 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 6 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
7 | * | 7 | * |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
diff --git a/sound/core/oss/plugin_ops.h b/sound/core/oss/plugin_ops.h deleted file mode 100644 index 1f5bde4631f1..000000000000 --- a/sound/core/oss/plugin_ops.h +++ /dev/null | |||
@@ -1,370 +0,0 @@ | |||
1 | /* | ||
2 | * Plugin sample operators with fast switch | ||
3 | * Copyright (c) 2000 by Jaroslav Kysela <perex@suse.cz> | ||
4 | * | ||
5 | * | ||
6 | * This library is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU Library General Public License as | ||
8 | * published by the Free Software Foundation; either version 2 of | ||
9 | * the License, or (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU Library General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU Library General Public | ||
17 | * License along with this library; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | |||
23 | #define as_u8(ptr) (*(u_int8_t*)(ptr)) | ||
24 | #define as_u16(ptr) (*(u_int16_t*)(ptr)) | ||
25 | #define as_u32(ptr) (*(u_int32_t*)(ptr)) | ||
26 | #define as_u64(ptr) (*(u_int64_t*)(ptr)) | ||
27 | #define as_s8(ptr) (*(int8_t*)(ptr)) | ||
28 | #define as_s16(ptr) (*(int16_t*)(ptr)) | ||
29 | #define as_s32(ptr) (*(int32_t*)(ptr)) | ||
30 | #define as_s64(ptr) (*(int64_t*)(ptr)) | ||
31 | |||
32 | #ifdef COPY_LABELS | ||
33 | static void *copy_labels[4] = { | ||
34 | &©_8, | ||
35 | &©_16, | ||
36 | &©_32, | ||
37 | &©_64 | ||
38 | }; | ||
39 | #endif | ||
40 | |||
41 | #ifdef COPY_END | ||
42 | while(0) { | ||
43 | copy_8: as_s8(dst) = as_s8(src); goto COPY_END; | ||
44 | copy_16: as_s16(dst) = as_s16(src); goto COPY_END; | ||
45 | copy_32: as_s32(dst) = as_s32(src); goto COPY_END; | ||
46 | copy_64: as_s64(dst) = as_s64(src); goto COPY_END; | ||
47 | } | ||
48 | #endif | ||
49 | |||
50 | #ifdef CONV_LABELS | ||
51 | /* src_wid src_endswap sign_toggle dst_wid dst_endswap */ | ||
52 | static void *conv_labels[4 * 2 * 2 * 4 * 2] = { | ||
53 | &&conv_xxx1_xxx1, /* 8h -> 8h */ | ||
54 | &&conv_xxx1_xxx1, /* 8h -> 8s */ | ||
55 | &&conv_xxx1_xx10, /* 8h -> 16h */ | ||
56 | &&conv_xxx1_xx01, /* 8h -> 16s */ | ||
57 | &&conv_xxx1_x100, /* 8h -> 24h */ | ||
58 | &&conv_xxx1_001x, /* 8h -> 24s */ | ||
59 | &&conv_xxx1_1000, /* 8h -> 32h */ | ||
60 | &&conv_xxx1_0001, /* 8h -> 32s */ | ||
61 | &&conv_xxx1_xxx9, /* 8h ^> 8h */ | ||
62 | &&conv_xxx1_xxx9, /* 8h ^> 8s */ | ||
63 | &&conv_xxx1_xx90, /* 8h ^> 16h */ | ||
64 | &&conv_xxx1_xx09, /* 8h ^> 16s */ | ||
65 | &&conv_xxx1_x900, /* 8h ^> 24h */ | ||
66 | &&conv_xxx1_009x, /* 8h ^> 24s */ | ||
67 | &&conv_xxx1_9000, /* 8h ^> 32h */ | ||
68 | &&conv_xxx1_0009, /* 8h ^> 32s */ | ||
69 | &&conv_xxx1_xxx1, /* 8s -> 8h */ | ||
70 | &&conv_xxx1_xxx1, /* 8s -> 8s */ | ||
71 | &&conv_xxx1_xx10, /* 8s -> 16h */ | ||
72 | &&conv_xxx1_xx01, /* 8s -> 16s */ | ||
73 | &&conv_xxx1_x100, /* 8s -> 24h */ | ||
74 | &&conv_xxx1_001x, /* 8s -> 24s */ | ||
75 | &&conv_xxx1_1000, /* 8s -> 32h */ | ||
76 | &&conv_xxx1_0001, /* 8s -> 32s */ | ||
77 | &&conv_xxx1_xxx9, /* 8s ^> 8h */ | ||
78 | &&conv_xxx1_xxx9, /* 8s ^> 8s */ | ||
79 | &&conv_xxx1_xx90, /* 8s ^> 16h */ | ||
80 | &&conv_xxx1_xx09, /* 8s ^> 16s */ | ||
81 | &&conv_xxx1_x900, /* 8s ^> 24h */ | ||
82 | &&conv_xxx1_009x, /* 8s ^> 24s */ | ||
83 | &&conv_xxx1_9000, /* 8s ^> 32h */ | ||
84 | &&conv_xxx1_0009, /* 8s ^> 32s */ | ||
85 | &&conv_xx12_xxx1, /* 16h -> 8h */ | ||
86 | &&conv_xx12_xxx1, /* 16h -> 8s */ | ||
87 | &&conv_xx12_xx12, /* 16h -> 16h */ | ||
88 | &&conv_xx12_xx21, /* 16h -> 16s */ | ||
89 | &&conv_xx12_x120, /* 16h -> 24h */ | ||
90 | &&conv_xx12_021x, /* 16h -> 24s */ | ||
91 | &&conv_xx12_1200, /* 16h -> 32h */ | ||
92 | &&conv_xx12_0021, /* 16h -> 32s */ | ||
93 | &&conv_xx12_xxx9, /* 16h ^> 8h */ | ||
94 | &&conv_xx12_xxx9, /* 16h ^> 8s */ | ||
95 | &&conv_xx12_xx92, /* 16h ^> 16h */ | ||
96 | &&conv_xx12_xx29, /* 16h ^> 16s */ | ||
97 | &&conv_xx12_x920, /* 16h ^> 24h */ | ||
98 | &&conv_xx12_029x, /* 16h ^> 24s */ | ||
99 | &&conv_xx12_9200, /* 16h ^> 32h */ | ||
100 | &&conv_xx12_0029, /* 16h ^> 32s */ | ||
101 | &&conv_xx12_xxx2, /* 16s -> 8h */ | ||
102 | &&conv_xx12_xxx2, /* 16s -> 8s */ | ||
103 | &&conv_xx12_xx21, /* 16s -> 16h */ | ||
104 | &&conv_xx12_xx12, /* 16s -> 16s */ | ||
105 | &&conv_xx12_x210, /* 16s -> 24h */ | ||
106 | &&conv_xx12_012x, /* 16s -> 24s */ | ||
107 | &&conv_xx12_2100, /* 16s -> 32h */ | ||
108 | &&conv_xx12_0012, /* 16s -> 32s */ | ||
109 | &&conv_xx12_xxxA, /* 16s ^> 8h */ | ||
110 | &&conv_xx12_xxxA, /* 16s ^> 8s */ | ||
111 | &&conv_xx12_xxA1, /* 16s ^> 16h */ | ||
112 | &&conv_xx12_xx1A, /* 16s ^> 16s */ | ||
113 | &&conv_xx12_xA10, /* 16s ^> 24h */ | ||
114 | &&conv_xx12_01Ax, /* 16s ^> 24s */ | ||
115 | &&conv_xx12_A100, /* 16s ^> 32h */ | ||
116 | &&conv_xx12_001A, /* 16s ^> 32s */ | ||
117 | &&conv_x123_xxx1, /* 24h -> 8h */ | ||
118 | &&conv_x123_xxx1, /* 24h -> 8s */ | ||
119 | &&conv_x123_xx12, /* 24h -> 16h */ | ||
120 | &&conv_x123_xx21, /* 24h -> 16s */ | ||
121 | &&conv_x123_x123, /* 24h -> 24h */ | ||
122 | &&conv_x123_321x, /* 24h -> 24s */ | ||
123 | &&conv_x123_1230, /* 24h -> 32h */ | ||
124 | &&conv_x123_0321, /* 24h -> 32s */ | ||
125 | &&conv_x123_xxx9, /* 24h ^> 8h */ | ||
126 | &&conv_x123_xxx9, /* 24h ^> 8s */ | ||
127 | &&conv_x123_xx92, /* 24h ^> 16h */ | ||
128 | &&conv_x123_xx29, /* 24h ^> 16s */ | ||
129 | &&conv_x123_x923, /* 24h ^> 24h */ | ||
130 | &&conv_x123_329x, /* 24h ^> 24s */ | ||
131 | &&conv_x123_9230, /* 24h ^> 32h */ | ||
132 | &&conv_x123_0329, /* 24h ^> 32s */ | ||
133 | &&conv_123x_xxx3, /* 24s -> 8h */ | ||
134 | &&conv_123x_xxx3, /* 24s -> 8s */ | ||
135 | &&conv_123x_xx32, /* 24s -> 16h */ | ||
136 | &&conv_123x_xx23, /* 24s -> 16s */ | ||
137 | &&conv_123x_x321, /* 24s -> 24h */ | ||
138 | &&conv_123x_123x, /* 24s -> 24s */ | ||
139 | &&conv_123x_3210, /* 24s -> 32h */ | ||
140 | &&conv_123x_0123, /* 24s -> 32s */ | ||
141 | &&conv_123x_xxxB, /* 24s ^> 8h */ | ||
142 | &&conv_123x_xxxB, /* 24s ^> 8s */ | ||
143 | &&conv_123x_xxB2, /* 24s ^> 16h */ | ||
144 | &&conv_123x_xx2B, /* 24s ^> 16s */ | ||
145 | &&conv_123x_xB21, /* 24s ^> 24h */ | ||
146 | &&conv_123x_12Bx, /* 24s ^> 24s */ | ||
147 | &&conv_123x_B210, /* 24s ^> 32h */ | ||
148 | &&conv_123x_012B, /* 24s ^> 32s */ | ||
149 | &&conv_1234_xxx1, /* 32h -> 8h */ | ||
150 | &&conv_1234_xxx1, /* 32h -> 8s */ | ||
151 | &&conv_1234_xx12, /* 32h -> 16h */ | ||
152 | &&conv_1234_xx21, /* 32h -> 16s */ | ||
153 | &&conv_1234_x123, /* 32h -> 24h */ | ||
154 | &&conv_1234_321x, /* 32h -> 24s */ | ||
155 | &&conv_1234_1234, /* 32h -> 32h */ | ||
156 | &&conv_1234_4321, /* 32h -> 32s */ | ||
157 | &&conv_1234_xxx9, /* 32h ^> 8h */ | ||
158 | &&conv_1234_xxx9, /* 32h ^> 8s */ | ||
159 | &&conv_1234_xx92, /* 32h ^> 16h */ | ||
160 | &&conv_1234_xx29, /* 32h ^> 16s */ | ||
161 | &&conv_1234_x923, /* 32h ^> 24h */ | ||
162 | &&conv_1234_329x, /* 32h ^> 24s */ | ||
163 | &&conv_1234_9234, /* 32h ^> 32h */ | ||
164 | &&conv_1234_4329, /* 32h ^> 32s */ | ||
165 | &&conv_1234_xxx4, /* 32s -> 8h */ | ||
166 | &&conv_1234_xxx4, /* 32s -> 8s */ | ||
167 | &&conv_1234_xx43, /* 32s -> 16h */ | ||
168 | &&conv_1234_xx34, /* 32s -> 16s */ | ||
169 | &&conv_1234_x432, /* 32s -> 24h */ | ||
170 | &&conv_1234_234x, /* 32s -> 24s */ | ||
171 | &&conv_1234_4321, /* 32s -> 32h */ | ||
172 | &&conv_1234_1234, /* 32s -> 32s */ | ||
173 | &&conv_1234_xxxC, /* 32s ^> 8h */ | ||
174 | &&conv_1234_xxxC, /* 32s ^> 8s */ | ||
175 | &&conv_1234_xxC3, /* 32s ^> 16h */ | ||
176 | &&conv_1234_xx3C, /* 32s ^> 16s */ | ||
177 | &&conv_1234_xC32, /* 32s ^> 24h */ | ||
178 | &&conv_1234_23Cx, /* 32s ^> 24s */ | ||
179 | &&conv_1234_C321, /* 32s ^> 32h */ | ||
180 | &&conv_1234_123C, /* 32s ^> 32s */ | ||
181 | }; | ||
182 | #endif | ||
183 | |||
184 | #ifdef CONV_END | ||
185 | while(0) { | ||
186 | conv_xxx1_xxx1: as_u8(dst) = as_u8(src); goto CONV_END; | ||
187 | conv_xxx1_xx10: as_u16(dst) = (u_int16_t)as_u8(src) << 8; goto CONV_END; | ||
188 | conv_xxx1_xx01: as_u16(dst) = (u_int16_t)as_u8(src); goto CONV_END; | ||
189 | conv_xxx1_x100: as_u32(dst) = (u_int32_t)as_u8(src) << 16; goto CONV_END; | ||
190 | conv_xxx1_001x: as_u32(dst) = (u_int32_t)as_u8(src) << 8; goto CONV_END; | ||
191 | conv_xxx1_1000: as_u32(dst) = (u_int32_t)as_u8(src) << 24; goto CONV_END; | ||
192 | conv_xxx1_0001: as_u32(dst) = (u_int32_t)as_u8(src); goto CONV_END; | ||
193 | conv_xxx1_xxx9: as_u8(dst) = as_u8(src) ^ 0x80; goto CONV_END; | ||
194 | conv_xxx1_xx90: as_u16(dst) = (u_int16_t)(as_u8(src) ^ 0x80) << 8; goto CONV_END; | ||
195 | conv_xxx1_xx09: as_u16(dst) = (u_int16_t)(as_u8(src) ^ 0x80); goto CONV_END; | ||
196 | conv_xxx1_x900: as_u32(dst) = (u_int32_t)(as_u8(src) ^ 0x80) << 16; goto CONV_END; | ||
197 | conv_xxx1_009x: as_u32(dst) = (u_int32_t)(as_u8(src) ^ 0x80) << 8; goto CONV_END; | ||
198 | conv_xxx1_9000: as_u32(dst) = (u_int32_t)(as_u8(src) ^ 0x80) << 24; goto CONV_END; | ||
199 | conv_xxx1_0009: as_u32(dst) = (u_int32_t)(as_u8(src) ^ 0x80); goto CONV_END; | ||
200 | conv_xx12_xxx1: as_u8(dst) = as_u16(src) >> 8; goto CONV_END; | ||
201 | conv_xx12_xx12: as_u16(dst) = as_u16(src); goto CONV_END; | ||
202 | conv_xx12_xx21: as_u16(dst) = swab16(as_u16(src)); goto CONV_END; | ||
203 | conv_xx12_x120: as_u32(dst) = (u_int32_t)as_u16(src) << 8; goto CONV_END; | ||
204 | conv_xx12_021x: as_u32(dst) = (u_int32_t)swab16(as_u16(src)) << 8; goto CONV_END; | ||
205 | conv_xx12_1200: as_u32(dst) = (u_int32_t)as_u16(src) << 16; goto CONV_END; | ||
206 | conv_xx12_0021: as_u32(dst) = (u_int32_t)swab16(as_u16(src)); goto CONV_END; | ||
207 | conv_xx12_xxx9: as_u8(dst) = (as_u16(src) >> 8) ^ 0x80; goto CONV_END; | ||
208 | conv_xx12_xx92: as_u16(dst) = as_u16(src) ^ 0x8000; goto CONV_END; | ||
209 | conv_xx12_xx29: as_u16(dst) = swab16(as_u16(src)) ^ 0x80; goto CONV_END; | ||
210 | conv_xx12_x920: as_u32(dst) = (u_int32_t)(as_u16(src) ^ 0x8000) << 8; goto CONV_END; | ||
211 | conv_xx12_029x: as_u32(dst) = (u_int32_t)(swab16(as_u16(src)) ^ 0x80) << 8; goto CONV_END; | ||
212 | conv_xx12_9200: as_u32(dst) = (u_int32_t)(as_u16(src) ^ 0x8000) << 16; goto CONV_END; | ||
213 | conv_xx12_0029: as_u32(dst) = (u_int32_t)(swab16(as_u16(src)) ^ 0x80); goto CONV_END; | ||
214 | conv_xx12_xxx2: as_u8(dst) = as_u16(src) & 0xff; goto CONV_END; | ||
215 | conv_xx12_x210: as_u32(dst) = (u_int32_t)swab16(as_u16(src)) << 8; goto CONV_END; | ||
216 | conv_xx12_012x: as_u32(dst) = (u_int32_t)as_u16(src) << 8; goto CONV_END; | ||
217 | conv_xx12_2100: as_u32(dst) = (u_int32_t)swab16(as_u16(src)) << 16; goto CONV_END; | ||
218 | conv_xx12_0012: as_u32(dst) = (u_int32_t)as_u16(src); goto CONV_END; | ||
219 | conv_xx12_xxxA: as_u8(dst) = (as_u16(src) ^ 0x80) & 0xff; goto CONV_END; | ||
220 | conv_xx12_xxA1: as_u16(dst) = swab16(as_u16(src) ^ 0x80); goto CONV_END; | ||
221 | conv_xx12_xx1A: as_u16(dst) = as_u16(src) ^ 0x80; goto CONV_END; | ||
222 | conv_xx12_xA10: as_u32(dst) = (u_int32_t)swab16(as_u16(src) ^ 0x80) << 8; goto CONV_END; | ||
223 | conv_xx12_01Ax: as_u32(dst) = (u_int32_t)(as_u16(src) ^ 0x80) << 8; goto CONV_END; | ||
224 | conv_xx12_A100: as_u32(dst) = (u_int32_t)swab16(as_u16(src) ^ 0x80) << 16; goto CONV_END; | ||
225 | conv_xx12_001A: as_u32(dst) = (u_int32_t)(as_u16(src) ^ 0x80); goto CONV_END; | ||
226 | conv_x123_xxx1: as_u8(dst) = as_u32(src) >> 16; goto CONV_END; | ||
227 | conv_x123_xx12: as_u16(dst) = as_u32(src) >> 8; goto CONV_END; | ||
228 | conv_x123_xx21: as_u16(dst) = swab16(as_u32(src) >> 8); goto CONV_END; | ||
229 | conv_x123_x123: as_u32(dst) = as_u32(src); goto CONV_END; | ||
230 | conv_x123_321x: as_u32(dst) = swab32(as_u32(src)); goto CONV_END; | ||
231 | conv_x123_1230: as_u32(dst) = as_u32(src) << 8; goto CONV_END; | ||
232 | conv_x123_0321: as_u32(dst) = swab32(as_u32(src)) >> 8; goto CONV_END; | ||
233 | conv_x123_xxx9: as_u8(dst) = (as_u32(src) >> 16) ^ 0x80; goto CONV_END; | ||
234 | conv_x123_xx92: as_u16(dst) = (as_u32(src) >> 8) ^ 0x8000; goto CONV_END; | ||
235 | conv_x123_xx29: as_u16(dst) = swab16(as_u32(src) >> 8) ^ 0x80; goto CONV_END; | ||
236 | conv_x123_x923: as_u32(dst) = as_u32(src) ^ 0x800000; goto CONV_END; | ||
237 | conv_x123_329x: as_u32(dst) = swab32(as_u32(src)) ^ 0x8000; goto CONV_END; | ||
238 | conv_x123_9230: as_u32(dst) = (as_u32(src) ^ 0x800000) << 8; goto CONV_END; | ||
239 | conv_x123_0329: as_u32(dst) = (swab32(as_u32(src)) >> 8) ^ 0x80; goto CONV_END; | ||
240 | conv_123x_xxx3: as_u8(dst) = (as_u32(src) >> 8) & 0xff; goto CONV_END; | ||
241 | conv_123x_xx32: as_u16(dst) = swab16(as_u32(src) >> 8); goto CONV_END; | ||
242 | conv_123x_xx23: as_u16(dst) = (as_u32(src) >> 8) & 0xffff; goto CONV_END; | ||
243 | conv_123x_x321: as_u32(dst) = swab32(as_u32(src)); goto CONV_END; | ||
244 | conv_123x_123x: as_u32(dst) = as_u32(src); goto CONV_END; | ||
245 | conv_123x_3210: as_u32(dst) = swab32(as_u32(src)) << 8; goto CONV_END; | ||
246 | conv_123x_0123: as_u32(dst) = as_u32(src) >> 8; goto CONV_END; | ||
247 | conv_123x_xxxB: as_u8(dst) = ((as_u32(src) >> 8) & 0xff) ^ 0x80; goto CONV_END; | ||
248 | conv_123x_xxB2: as_u16(dst) = swab16((as_u32(src) >> 8) ^ 0x80); goto CONV_END; | ||
249 | conv_123x_xx2B: as_u16(dst) = ((as_u32(src) >> 8) & 0xffff) ^ 0x80; goto CONV_END; | ||
250 | conv_123x_xB21: as_u32(dst) = swab32(as_u32(src)) ^ 0x800000; goto CONV_END; | ||
251 | conv_123x_12Bx: as_u32(dst) = as_u32(src) ^ 0x8000; goto CONV_END; | ||
252 | conv_123x_B210: as_u32(dst) = swab32(as_u32(src) ^ 0x8000) << 8; goto CONV_END; | ||
253 | conv_123x_012B: as_u32(dst) = (as_u32(src) >> 8) ^ 0x80; goto CONV_END; | ||
254 | conv_1234_xxx1: as_u8(dst) = as_u32(src) >> 24; goto CONV_END; | ||
255 | conv_1234_xx12: as_u16(dst) = as_u32(src) >> 16; goto CONV_END; | ||
256 | conv_1234_xx21: as_u16(dst) = swab16(as_u32(src) >> 16); goto CONV_END; | ||
257 | conv_1234_x123: as_u32(dst) = as_u32(src) >> 8; goto CONV_END; | ||
258 | conv_1234_321x: as_u32(dst) = swab32(as_u32(src)) << 8; goto CONV_END; | ||
259 | conv_1234_1234: as_u32(dst) = as_u32(src); goto CONV_END; | ||
260 | conv_1234_4321: as_u32(dst) = swab32(as_u32(src)); goto CONV_END; | ||
261 | conv_1234_xxx9: as_u8(dst) = (as_u32(src) >> 24) ^ 0x80; goto CONV_END; | ||
262 | conv_1234_xx92: as_u16(dst) = (as_u32(src) >> 16) ^ 0x8000; goto CONV_END; | ||
263 | conv_1234_xx29: as_u16(dst) = swab16(as_u32(src) >> 16) ^ 0x80; goto CONV_END; | ||
264 | conv_1234_x923: as_u32(dst) = (as_u32(src) >> 8) ^ 0x800000; goto CONV_END; | ||
265 | conv_1234_329x: as_u32(dst) = (swab32(as_u32(src)) ^ 0x80) << 8; goto CONV_END; | ||
266 | conv_1234_9234: as_u32(dst) = as_u32(src) ^ 0x80000000; goto CONV_END; | ||
267 | conv_1234_4329: as_u32(dst) = swab32(as_u32(src)) ^ 0x80; goto CONV_END; | ||
268 | conv_1234_xxx4: as_u8(dst) = as_u32(src) & 0xff; goto CONV_END; | ||
269 | conv_1234_xx43: as_u16(dst) = swab16(as_u32(src)); goto CONV_END; | ||
270 | conv_1234_xx34: as_u16(dst) = as_u32(src) & 0xffff; goto CONV_END; | ||
271 | conv_1234_x432: as_u32(dst) = swab32(as_u32(src)) >> 8; goto CONV_END; | ||
272 | conv_1234_234x: as_u32(dst) = as_u32(src) << 8; goto CONV_END; | ||
273 | conv_1234_xxxC: as_u8(dst) = (as_u32(src) & 0xff) ^ 0x80; goto CONV_END; | ||
274 | conv_1234_xxC3: as_u16(dst) = swab16(as_u32(src) ^ 0x80); goto CONV_END; | ||
275 | conv_1234_xx3C: as_u16(dst) = (as_u32(src) & 0xffff) ^ 0x80; goto CONV_END; | ||
276 | conv_1234_xC32: as_u32(dst) = (swab32(as_u32(src)) >> 8) ^ 0x800000; goto CONV_END; | ||
277 | conv_1234_23Cx: as_u32(dst) = (as_u32(src) ^ 0x80) << 8; goto CONV_END; | ||
278 | conv_1234_C321: as_u32(dst) = swab32(as_u32(src) ^ 0x80); goto CONV_END; | ||
279 | conv_1234_123C: as_u32(dst) = as_u32(src) ^ 0x80; goto CONV_END; | ||
280 | } | ||
281 | #endif | ||
282 | |||
283 | #ifdef GET_S16_LABELS | ||
284 | /* src_wid src_endswap unsigned */ | ||
285 | static void *get_s16_labels[4 * 2 * 2] = { | ||
286 | &&get_s16_xxx1_xx10, /* 8h -> 16h */ | ||
287 | &&get_s16_xxx1_xx90, /* 8h ^> 16h */ | ||
288 | &&get_s16_xxx1_xx10, /* 8s -> 16h */ | ||
289 | &&get_s16_xxx1_xx90, /* 8s ^> 16h */ | ||
290 | &&get_s16_xx12_xx12, /* 16h -> 16h */ | ||
291 | &&get_s16_xx12_xx92, /* 16h ^> 16h */ | ||
292 | &&get_s16_xx12_xx21, /* 16s -> 16h */ | ||
293 | &&get_s16_xx12_xxA1, /* 16s ^> 16h */ | ||
294 | &&get_s16_x123_xx12, /* 24h -> 16h */ | ||
295 | &&get_s16_x123_xx92, /* 24h ^> 16h */ | ||
296 | &&get_s16_123x_xx32, /* 24s -> 16h */ | ||
297 | &&get_s16_123x_xxB2, /* 24s ^> 16h */ | ||
298 | &&get_s16_1234_xx12, /* 32h -> 16h */ | ||
299 | &&get_s16_1234_xx92, /* 32h ^> 16h */ | ||
300 | &&get_s16_1234_xx43, /* 32s -> 16h */ | ||
301 | &&get_s16_1234_xxC3, /* 32s ^> 16h */ | ||
302 | }; | ||
303 | #endif | ||
304 | |||
305 | #ifdef GET_S16_END | ||
306 | while(0) { | ||
307 | get_s16_xxx1_xx10: sample = (u_int16_t)as_u8(src) << 8; goto GET_S16_END; | ||
308 | get_s16_xxx1_xx90: sample = (u_int16_t)(as_u8(src) ^ 0x80) << 8; goto GET_S16_END; | ||
309 | get_s16_xx12_xx12: sample = as_u16(src); goto GET_S16_END; | ||
310 | get_s16_xx12_xx92: sample = as_u16(src) ^ 0x8000; goto GET_S16_END; | ||
311 | get_s16_xx12_xx21: sample = swab16(as_u16(src)); goto GET_S16_END; | ||
312 | get_s16_xx12_xxA1: sample = swab16(as_u16(src) ^ 0x80); goto GET_S16_END; | ||
313 | get_s16_x123_xx12: sample = as_u32(src) >> 8; goto GET_S16_END; | ||
314 | get_s16_x123_xx92: sample = (as_u32(src) >> 8) ^ 0x8000; goto GET_S16_END; | ||
315 | get_s16_123x_xx32: sample = swab16(as_u32(src) >> 8); goto GET_S16_END; | ||
316 | get_s16_123x_xxB2: sample = swab16((as_u32(src) >> 8) ^ 0x8000); goto GET_S16_END; | ||
317 | get_s16_1234_xx12: sample = as_u32(src) >> 16; goto GET_S16_END; | ||
318 | get_s16_1234_xx92: sample = (as_u32(src) >> 16) ^ 0x8000; goto GET_S16_END; | ||
319 | get_s16_1234_xx43: sample = swab16(as_u32(src)); goto GET_S16_END; | ||
320 | get_s16_1234_xxC3: sample = swab16(as_u32(src) ^ 0x80); goto GET_S16_END; | ||
321 | } | ||
322 | #endif | ||
323 | |||
324 | #ifdef PUT_S16_LABELS | ||
325 | /* dst_wid dst_endswap unsigned */ | ||
326 | static void *put_s16_labels[4 * 2 * 2] = { | ||
327 | &&put_s16_xx12_xxx1, /* 16h -> 8h */ | ||
328 | &&put_s16_xx12_xxx9, /* 16h ^> 8h */ | ||
329 | &&put_s16_xx12_xxx1, /* 16h -> 8s */ | ||
330 | &&put_s16_xx12_xxx9, /* 16h ^> 8s */ | ||
331 | &&put_s16_xx12_xx12, /* 16h -> 16h */ | ||
332 | &&put_s16_xx12_xx92, /* 16h ^> 16h */ | ||
333 | &&put_s16_xx12_xx21, /* 16h -> 16s */ | ||
334 | &&put_s16_xx12_xx29, /* 16h ^> 16s */ | ||
335 | &&put_s16_xx12_x120, /* 16h -> 24h */ | ||
336 | &&put_s16_xx12_x920, /* 16h ^> 24h */ | ||
337 | &&put_s16_xx12_021x, /* 16h -> 24s */ | ||
338 | &&put_s16_xx12_029x, /* 16h ^> 24s */ | ||
339 | &&put_s16_xx12_1200, /* 16h -> 32h */ | ||
340 | &&put_s16_xx12_9200, /* 16h ^> 32h */ | ||
341 | &&put_s16_xx12_0021, /* 16h -> 32s */ | ||
342 | &&put_s16_xx12_0029, /* 16h ^> 32s */ | ||
343 | }; | ||
344 | #endif | ||
345 | |||
346 | #ifdef PUT_S16_END | ||
347 | while (0) { | ||
348 | put_s16_xx12_xxx1: as_u8(dst) = sample >> 8; goto PUT_S16_END; | ||
349 | put_s16_xx12_xxx9: as_u8(dst) = (sample >> 8) ^ 0x80; goto PUT_S16_END; | ||
350 | put_s16_xx12_xx12: as_u16(dst) = sample; goto PUT_S16_END; | ||
351 | put_s16_xx12_xx92: as_u16(dst) = sample ^ 0x8000; goto PUT_S16_END; | ||
352 | put_s16_xx12_xx21: as_u16(dst) = swab16(sample); goto PUT_S16_END; | ||
353 | put_s16_xx12_xx29: as_u16(dst) = swab16(sample) ^ 0x80; goto PUT_S16_END; | ||
354 | put_s16_xx12_x120: as_u32(dst) = (u_int32_t)sample << 8; goto PUT_S16_END; | ||
355 | put_s16_xx12_x920: as_u32(dst) = (u_int32_t)(sample ^ 0x8000) << 8; goto PUT_S16_END; | ||
356 | put_s16_xx12_021x: as_u32(dst) = (u_int32_t)swab16(sample) << 8; goto PUT_S16_END; | ||
357 | put_s16_xx12_029x: as_u32(dst) = (u_int32_t)(swab16(sample) ^ 0x80) << 8; goto PUT_S16_END; | ||
358 | put_s16_xx12_1200: as_u32(dst) = (u_int32_t)sample << 16; goto PUT_S16_END; | ||
359 | put_s16_xx12_9200: as_u32(dst) = (u_int32_t)(sample ^ 0x8000) << 16; goto PUT_S16_END; | ||
360 | put_s16_xx12_0021: as_u32(dst) = (u_int32_t)swab16(sample); goto PUT_S16_END; | ||
361 | put_s16_xx12_0029: as_u32(dst) = (u_int32_t)swab16(sample) ^ 0x80; goto PUT_S16_END; | ||
362 | } | ||
363 | #endif | ||
364 | |||
365 | #undef as_u8 | ||
366 | #undef as_u16 | ||
367 | #undef as_u32 | ||
368 | #undef as_s8 | ||
369 | #undef as_s16 | ||
370 | #undef as_s32 | ||
diff --git a/sound/core/oss/rate.c b/sound/core/oss/rate.c index 18d8a0f4e816..9eb267913c38 100644 --- a/sound/core/oss/rate.c +++ b/sound/core/oss/rate.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Rate conversion Plug-In | 2 | * Rate conversion Plug-In |
3 | * Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This library is free software; you can redistribute it and/or modify | 6 | * This library is free software; you can redistribute it and/or modify |
@@ -20,9 +20,6 @@ | |||
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <sound/driver.h> | 22 | #include <sound/driver.h> |
23 | |||
24 | #ifdef CONFIG_SND_PCM_OSS_PLUGINS | ||
25 | |||
26 | #include <linux/time.h> | 23 | #include <linux/time.h> |
27 | #include <sound/core.h> | 24 | #include <sound/core.h> |
28 | #include <sound/pcm.h> | 25 | #include <sound/pcm.h> |
@@ -340,5 +337,3 @@ int snd_pcm_plugin_build_rate(struct snd_pcm_substream *plug, | |||
340 | *r_plugin = plugin; | 337 | *r_plugin = plugin; |
341 | return 0; | 338 | return 0; |
342 | } | 339 | } |
343 | |||
344 | #endif | ||
diff --git a/sound/core/oss/route.c b/sound/core/oss/route.c index 46917dc0196b..de3ffdeaf7e3 100644 --- a/sound/core/oss/route.c +++ b/sound/core/oss/route.c | |||
@@ -20,9 +20,6 @@ | |||
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <sound/driver.h> | 22 | #include <sound/driver.h> |
23 | |||
24 | #ifdef CONFIG_SND_PCM_OSS_PLUGINS | ||
25 | |||
26 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
27 | #include <linux/time.h> | 24 | #include <linux/time.h> |
28 | #include <sound/core.h> | 25 | #include <sound/core.h> |
@@ -108,5 +105,3 @@ int snd_pcm_plugin_build_route(struct snd_pcm_substream *plug, | |||
108 | *r_plugin = plugin; | 105 | *r_plugin = plugin; |
109 | return 0; | 106 | return 0; |
110 | } | 107 | } |
111 | |||
112 | #endif | ||
diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 2743414fc8fa..cf9b9493d41d 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Digital Audio (PCM) abstract layer | 2 | * Digital Audio (PCM) abstract layer |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -30,7 +30,7 @@ | |||
30 | #include <sound/control.h> | 30 | #include <sound/control.h> |
31 | #include <sound/info.h> | 31 | #include <sound/info.h> |
32 | 32 | ||
33 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Abramo Bagnara <abramo@alsa-project.org>"); | 33 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Abramo Bagnara <abramo@alsa-project.org>"); |
34 | MODULE_DESCRIPTION("Midlevel PCM code for ALSA."); | 34 | MODULE_DESCRIPTION("Midlevel PCM code for ALSA."); |
35 | MODULE_LICENSE("GPL"); | 35 | MODULE_LICENSE("GPL"); |
36 | 36 | ||
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 9fefcaa2c324..806f1fba5446 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Digital Audio (PCM) abstract layer | 2 | * Digital Audio (PCM) abstract layer |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * Abramo Bagnara <abramo@alsa-project.org> | 4 | * Abramo Bagnara <abramo@alsa-project.org> |
5 | * | 5 | * |
6 | * | 6 | * |
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c index 95b1b2f0b1e2..a13e38cfd2c6 100644 --- a/sound/core/pcm_memory.c +++ b/sound/core/pcm_memory.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Digital Audio (PCM) abstract layer | 2 | * Digital Audio (PCM) abstract layer |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c index 0019c59a779d..dd9aa51d8c82 100644 --- a/sound/core/pcm_misc.c +++ b/sound/core/pcm_misc.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * PCM Interface - misc routines | 2 | * PCM Interface - misc routines |
3 | * Copyright (c) 1998 by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) 1998 by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This library is free software; you can redistribute it and/or modify | 6 | * This library is free software; you can redistribute it and/or modify |
@@ -422,38 +422,6 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int | |||
422 | 422 | ||
423 | EXPORT_SYMBOL(snd_pcm_format_set_silence); | 423 | EXPORT_SYMBOL(snd_pcm_format_set_silence); |
424 | 424 | ||
425 | /* [width][unsigned][bigendian] */ | ||
426 | static int linear_formats[4][2][2] = { | ||
427 | {{ SNDRV_PCM_FORMAT_S8, SNDRV_PCM_FORMAT_S8}, | ||
428 | { SNDRV_PCM_FORMAT_U8, SNDRV_PCM_FORMAT_U8}}, | ||
429 | {{SNDRV_PCM_FORMAT_S16_LE, SNDRV_PCM_FORMAT_S16_BE}, | ||
430 | {SNDRV_PCM_FORMAT_U16_LE, SNDRV_PCM_FORMAT_U16_BE}}, | ||
431 | {{SNDRV_PCM_FORMAT_S24_LE, SNDRV_PCM_FORMAT_S24_BE}, | ||
432 | {SNDRV_PCM_FORMAT_U24_LE, SNDRV_PCM_FORMAT_U24_BE}}, | ||
433 | {{SNDRV_PCM_FORMAT_S32_LE, SNDRV_PCM_FORMAT_S32_BE}, | ||
434 | {SNDRV_PCM_FORMAT_U32_LE, SNDRV_PCM_FORMAT_U32_BE}} | ||
435 | }; | ||
436 | |||
437 | /** | ||
438 | * snd_pcm_build_linear_format - return the suitable linear format for the given condition | ||
439 | * @width: the bit-width | ||
440 | * @unsignd: 1 if unsigned, 0 if signed. | ||
441 | * @big_endian: 1 if big-endian, 0 if little-endian | ||
442 | * | ||
443 | * Returns the suitable linear format for the given condition. | ||
444 | */ | ||
445 | snd_pcm_format_t snd_pcm_build_linear_format(int width, int unsignd, int big_endian) | ||
446 | { | ||
447 | if (width & 7) | ||
448 | return SND_PCM_FORMAT_UNKNOWN; | ||
449 | width = (width / 8) - 1; | ||
450 | if (width < 0 || width >= 4) | ||
451 | return SND_PCM_FORMAT_UNKNOWN; | ||
452 | return linear_formats[width][!!unsignd][!!big_endian]; | ||
453 | } | ||
454 | |||
455 | EXPORT_SYMBOL(snd_pcm_build_linear_format); | ||
456 | |||
457 | /** | 425 | /** |
458 | * snd_pcm_limit_hw_rates - determine rate_min/rate_max fields | 426 | * snd_pcm_limit_hw_rates - determine rate_min/rate_max fields |
459 | * @runtime: the runtime instance | 427 | * @runtime: the runtime instance |
@@ -465,21 +433,16 @@ EXPORT_SYMBOL(snd_pcm_build_linear_format); | |||
465 | */ | 433 | */ |
466 | int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime) | 434 | int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime) |
467 | { | 435 | { |
468 | static unsigned rates[] = { | ||
469 | /* ATTENTION: these values depend on the definition in pcm.h! */ | ||
470 | 5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, | ||
471 | 64000, 88200, 96000, 176400, 192000 | ||
472 | }; | ||
473 | int i; | 436 | int i; |
474 | for (i = 0; i < (int)ARRAY_SIZE(rates); i++) { | 437 | for (i = 0; i < (int)snd_pcm_known_rates.count; i++) { |
475 | if (runtime->hw.rates & (1 << i)) { | 438 | if (runtime->hw.rates & (1 << i)) { |
476 | runtime->hw.rate_min = rates[i]; | 439 | runtime->hw.rate_min = snd_pcm_known_rates.list[i]; |
477 | break; | 440 | break; |
478 | } | 441 | } |
479 | } | 442 | } |
480 | for (i = (int)ARRAY_SIZE(rates) - 1; i >= 0; i--) { | 443 | for (i = (int)snd_pcm_known_rates.count - 1; i >= 0; i--) { |
481 | if (runtime->hw.rates & (1 << i)) { | 444 | if (runtime->hw.rates & (1 << i)) { |
482 | runtime->hw.rate_max = rates[i]; | 445 | runtime->hw.rate_max = snd_pcm_known_rates.list[i]; |
483 | break; | 446 | break; |
484 | } | 447 | } |
485 | } | 448 | } |
@@ -487,3 +450,21 @@ int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime) | |||
487 | } | 450 | } |
488 | 451 | ||
489 | EXPORT_SYMBOL(snd_pcm_limit_hw_rates); | 452 | EXPORT_SYMBOL(snd_pcm_limit_hw_rates); |
453 | |||
454 | /** | ||
455 | * snd_pcm_rate_to_rate_bit - converts sample rate to SNDRV_PCM_RATE_xxx bit | ||
456 | * @rate: the sample rate to convert | ||
457 | * | ||
458 | * Returns the SNDRV_PCM_RATE_xxx flag that corresponds to the given rate, or | ||
459 | * SNDRV_PCM_RATE_KNOT for an unknown rate. | ||
460 | */ | ||
461 | unsigned int snd_pcm_rate_to_rate_bit(unsigned int rate) | ||
462 | { | ||
463 | unsigned int i; | ||
464 | |||
465 | for (i = 0; i < snd_pcm_known_rates.count; i++) | ||
466 | if (snd_pcm_known_rates.list[i] == rate) | ||
467 | return 1u << i; | ||
468 | return SNDRV_PCM_RATE_KNOT; | ||
469 | } | ||
470 | EXPORT_SYMBOL(snd_pcm_rate_to_rate_bit); | ||
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 59b29cd482ae..fb3dde4db045 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Digital Audio (PCM) abstract layer | 2 | * Digital Audio (PCM) abstract layer |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -1787,12 +1787,18 @@ static int snd_pcm_hw_rule_sample_bits(struct snd_pcm_hw_params *params, | |||
1787 | static unsigned int rates[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100, | 1787 | static unsigned int rates[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100, |
1788 | 48000, 64000, 88200, 96000, 176400, 192000 }; | 1788 | 48000, 64000, 88200, 96000, 176400, 192000 }; |
1789 | 1789 | ||
1790 | const struct snd_pcm_hw_constraint_list snd_pcm_known_rates = { | ||
1791 | .count = ARRAY_SIZE(rates), | ||
1792 | .list = rates, | ||
1793 | }; | ||
1794 | |||
1790 | static int snd_pcm_hw_rule_rate(struct snd_pcm_hw_params *params, | 1795 | static int snd_pcm_hw_rule_rate(struct snd_pcm_hw_params *params, |
1791 | struct snd_pcm_hw_rule *rule) | 1796 | struct snd_pcm_hw_rule *rule) |
1792 | { | 1797 | { |
1793 | struct snd_pcm_hardware *hw = rule->private; | 1798 | struct snd_pcm_hardware *hw = rule->private; |
1794 | return snd_interval_list(hw_param_interval(params, rule->var), | 1799 | return snd_interval_list(hw_param_interval(params, rule->var), |
1795 | ARRAY_SIZE(rates), rates, hw->rates); | 1800 | snd_pcm_known_rates.count, |
1801 | snd_pcm_known_rates.list, hw->rates); | ||
1796 | } | 1802 | } |
1797 | 1803 | ||
1798 | static int snd_pcm_hw_rule_buffer_bytes_max(struct snd_pcm_hw_params *params, | 1804 | static int snd_pcm_hw_rule_buffer_bytes_max(struct snd_pcm_hw_params *params, |
diff --git a/sound/core/pcm_timer.c b/sound/core/pcm_timer.c index d94ed16d21ea..23aa9a27e215 100644 --- a/sound/core/pcm_timer.c +++ b/sound/core/pcm_timer.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Digital Audio (PCM) abstract layer | 2 | * Digital Audio (PCM) abstract layer |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index e470c3c7d611..b8e700b94e59 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Abstract layer for MIDI v1.0 stream | 2 | * Abstract layer for MIDI v1.0 stream |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -30,14 +30,13 @@ | |||
30 | #include <linux/mutex.h> | 30 | #include <linux/mutex.h> |
31 | #include <linux/moduleparam.h> | 31 | #include <linux/moduleparam.h> |
32 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
33 | #include <linux/wait.h> | ||
34 | #include <sound/rawmidi.h> | 33 | #include <sound/rawmidi.h> |
35 | #include <sound/info.h> | 34 | #include <sound/info.h> |
36 | #include <sound/control.h> | 35 | #include <sound/control.h> |
37 | #include <sound/minors.h> | 36 | #include <sound/minors.h> |
38 | #include <sound/initval.h> | 37 | #include <sound/initval.h> |
39 | 38 | ||
40 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 39 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
41 | MODULE_DESCRIPTION("Midlevel RawMidi code for ALSA."); | 40 | MODULE_DESCRIPTION("Midlevel RawMidi code for ALSA."); |
42 | MODULE_LICENSE("GPL"); | 41 | MODULE_LICENSE("GPL"); |
43 | 42 | ||
diff --git a/sound/core/seq/Makefile b/sound/core/seq/Makefile index 402e2b4a34c6..ceef14afee30 100644 --- a/sound/core/seq/Makefile +++ b/sound/core/seq/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | obj-$(CONFIG_SND) += instr/ | 6 | obj-$(CONFIG_SND) += instr/ |
diff --git a/sound/core/seq/instr/Makefile b/sound/core/seq/instr/Makefile index 69138f30a293..608960364813 100644 --- a/sound/core/seq/instr/Makefile +++ b/sound/core/seq/instr/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-ainstr-fm-objs := ainstr_fm.o | 6 | snd-ainstr-fm-objs := ainstr_fm.o |
diff --git a/sound/core/seq/instr/ainstr_gf1.c b/sound/core/seq/instr/ainstr_gf1.c index c640e1cf854d..49400262b1eb 100644 --- a/sound/core/seq/instr/ainstr_gf1.c +++ b/sound/core/seq/instr/ainstr_gf1.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * GF1 (GUS) Patch - Instrument routines | 2 | * GF1 (GUS) Patch - Instrument routines |
3 | * Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 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 | 6 | * it under the terms of the GNU General Public License as published by |
@@ -26,7 +26,7 @@ | |||
26 | #include <sound/initval.h> | 26 | #include <sound/initval.h> |
27 | #include <asm/uaccess.h> | 27 | #include <asm/uaccess.h> |
28 | 28 | ||
29 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 29 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
30 | MODULE_DESCRIPTION("Advanced Linux Sound Architecture GF1 (GUS) Patch support."); | 30 | MODULE_DESCRIPTION("Advanced Linux Sound Architecture GF1 (GUS) Patch support."); |
31 | MODULE_LICENSE("GPL"); | 31 | MODULE_LICENSE("GPL"); |
32 | 32 | ||
diff --git a/sound/core/seq/instr/ainstr_iw.c b/sound/core/seq/instr/ainstr_iw.c index 5367baee2d08..6c40eb73fa9f 100644 --- a/sound/core/seq/instr/ainstr_iw.c +++ b/sound/core/seq/instr/ainstr_iw.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * IWFFFF - AMD InterWave (tm) - Instrument routines | 2 | * IWFFFF - AMD InterWave (tm) - Instrument routines |
3 | * Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 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 | 6 | * it under the terms of the GNU General Public License as published by |
@@ -26,7 +26,7 @@ | |||
26 | #include <sound/initval.h> | 26 | #include <sound/initval.h> |
27 | #include <asm/uaccess.h> | 27 | #include <asm/uaccess.h> |
28 | 28 | ||
29 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 29 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
30 | MODULE_DESCRIPTION("Advanced Linux Sound Architecture IWFFFF support."); | 30 | MODULE_DESCRIPTION("Advanced Linux Sound Architecture IWFFFF support."); |
31 | MODULE_LICENSE("GPL"); | 31 | MODULE_LICENSE("GPL"); |
32 | 32 | ||
diff --git a/sound/core/seq/instr/ainstr_simple.c b/sound/core/seq/instr/ainstr_simple.c index ac717bef9d77..78f68bee24fe 100644 --- a/sound/core/seq/instr/ainstr_simple.c +++ b/sound/core/seq/instr/ainstr_simple.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Simple (MOD player) - Instrument routines | 2 | * Simple (MOD player) - Instrument routines |
3 | * Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 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 | 6 | * it under the terms of the GNU General Public License as published by |
@@ -26,7 +26,7 @@ | |||
26 | #include <sound/initval.h> | 26 | #include <sound/initval.h> |
27 | #include <asm/uaccess.h> | 27 | #include <asm/uaccess.h> |
28 | 28 | ||
29 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 29 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
30 | MODULE_DESCRIPTION("Advanced Linux Sound Architecture Simple Instrument support."); | 30 | MODULE_DESCRIPTION("Advanced Linux Sound Architecture Simple Instrument support."); |
31 | MODULE_LICENSE("GPL"); | 31 | MODULE_LICENSE("GPL"); |
32 | 32 | ||
diff --git a/sound/core/seq/oss/Makefile b/sound/core/seq/oss/Makefile index a37ddedf7107..b38406b8463c 100644 --- a/sound/core/seq/oss/Makefile +++ b/sound/core/seq/oss/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-seq-oss-objs := seq_oss.o seq_oss_init.o seq_oss_timer.o seq_oss_ioctl.o \ | 6 | snd-seq-oss-objs := seq_oss.o seq_oss_init.o seq_oss_timer.o seq_oss_ioctl.o \ |
diff --git a/sound/core/seq/oss/seq_oss_init.c b/sound/core/seq/oss/seq_oss_init.c index ca5a2ed4d7c3..d0d721c22eac 100644 --- a/sound/core/seq/oss/seq_oss_init.c +++ b/sound/core/seq/oss/seq_oss_init.c | |||
@@ -176,29 +176,29 @@ snd_seq_oss_open(struct file *file, int level) | |||
176 | int i, rc; | 176 | int i, rc; |
177 | struct seq_oss_devinfo *dp; | 177 | struct seq_oss_devinfo *dp; |
178 | 178 | ||
179 | if ((dp = kzalloc(sizeof(*dp), GFP_KERNEL)) == NULL) { | 179 | dp = kzalloc(sizeof(*dp), GFP_KERNEL); |
180 | if (!dp) { | ||
180 | snd_printk(KERN_ERR "can't malloc device info\n"); | 181 | snd_printk(KERN_ERR "can't malloc device info\n"); |
181 | return -ENOMEM; | 182 | return -ENOMEM; |
182 | } | 183 | } |
183 | debug_printk(("oss_open: dp = %p\n", dp)); | 184 | debug_printk(("oss_open: dp = %p\n", dp)); |
184 | 185 | ||
186 | dp->cseq = system_client; | ||
187 | dp->port = -1; | ||
188 | dp->queue = -1; | ||
189 | |||
185 | for (i = 0; i < SNDRV_SEQ_OSS_MAX_CLIENTS; i++) { | 190 | for (i = 0; i < SNDRV_SEQ_OSS_MAX_CLIENTS; i++) { |
186 | if (client_table[i] == NULL) | 191 | if (client_table[i] == NULL) |
187 | break; | 192 | break; |
188 | } | 193 | } |
194 | |||
195 | dp->index = i; | ||
189 | if (i >= SNDRV_SEQ_OSS_MAX_CLIENTS) { | 196 | if (i >= SNDRV_SEQ_OSS_MAX_CLIENTS) { |
190 | snd_printk(KERN_ERR "too many applications\n"); | 197 | snd_printk(KERN_ERR "too many applications\n"); |
191 | kfree(dp); | 198 | rc = -ENOMEM; |
192 | return -ENOMEM; | 199 | goto _error; |
193 | } | 200 | } |
194 | 201 | ||
195 | dp->index = i; | ||
196 | dp->cseq = system_client; | ||
197 | dp->port = -1; | ||
198 | dp->queue = -1; | ||
199 | dp->readq = NULL; | ||
200 | dp->writeq = NULL; | ||
201 | |||
202 | /* look up synth and midi devices */ | 202 | /* look up synth and midi devices */ |
203 | snd_seq_oss_synth_setup(dp); | 203 | snd_seq_oss_synth_setup(dp); |
204 | snd_seq_oss_midi_setup(dp); | 204 | snd_seq_oss_midi_setup(dp); |
@@ -211,14 +211,16 @@ snd_seq_oss_open(struct file *file, int level) | |||
211 | 211 | ||
212 | /* create port */ | 212 | /* create port */ |
213 | debug_printk(("create new port\n")); | 213 | debug_printk(("create new port\n")); |
214 | if ((rc = create_port(dp)) < 0) { | 214 | rc = create_port(dp); |
215 | if (rc < 0) { | ||
215 | snd_printk(KERN_ERR "can't create port\n"); | 216 | snd_printk(KERN_ERR "can't create port\n"); |
216 | goto _error; | 217 | goto _error; |
217 | } | 218 | } |
218 | 219 | ||
219 | /* allocate queue */ | 220 | /* allocate queue */ |
220 | debug_printk(("allocate queue\n")); | 221 | debug_printk(("allocate queue\n")); |
221 | if ((rc = alloc_seq_queue(dp)) < 0) | 222 | rc = alloc_seq_queue(dp); |
223 | if (rc < 0) | ||
222 | goto _error; | 224 | goto _error; |
223 | 225 | ||
224 | /* set address */ | 226 | /* set address */ |
@@ -235,7 +237,8 @@ snd_seq_oss_open(struct file *file, int level) | |||
235 | /* initialize read queue */ | 237 | /* initialize read queue */ |
236 | debug_printk(("initialize read queue\n")); | 238 | debug_printk(("initialize read queue\n")); |
237 | if (is_read_mode(dp->file_mode)) { | 239 | if (is_read_mode(dp->file_mode)) { |
238 | if ((dp->readq = snd_seq_oss_readq_new(dp, maxqlen)) == NULL) { | 240 | dp->readq = snd_seq_oss_readq_new(dp, maxqlen); |
241 | if (!dp->readq) { | ||
239 | rc = -ENOMEM; | 242 | rc = -ENOMEM; |
240 | goto _error; | 243 | goto _error; |
241 | } | 244 | } |
@@ -245,7 +248,7 @@ snd_seq_oss_open(struct file *file, int level) | |||
245 | debug_printk(("initialize write queue\n")); | 248 | debug_printk(("initialize write queue\n")); |
246 | if (is_write_mode(dp->file_mode)) { | 249 | if (is_write_mode(dp->file_mode)) { |
247 | dp->writeq = snd_seq_oss_writeq_new(dp, maxqlen); | 250 | dp->writeq = snd_seq_oss_writeq_new(dp, maxqlen); |
248 | if (dp->writeq == NULL) { | 251 | if (!dp->writeq) { |
249 | rc = -ENOMEM; | 252 | rc = -ENOMEM; |
250 | goto _error; | 253 | goto _error; |
251 | } | 254 | } |
@@ -253,7 +256,8 @@ snd_seq_oss_open(struct file *file, int level) | |||
253 | 256 | ||
254 | /* initialize timer */ | 257 | /* initialize timer */ |
255 | debug_printk(("initialize timer\n")); | 258 | debug_printk(("initialize timer\n")); |
256 | if ((dp->timer = snd_seq_oss_timer_new(dp)) == NULL) { | 259 | dp->timer = snd_seq_oss_timer_new(dp); |
260 | if (!dp->timer) { | ||
257 | snd_printk(KERN_ERR "can't alloc timer\n"); | 261 | snd_printk(KERN_ERR "can't alloc timer\n"); |
258 | rc = -ENOMEM; | 262 | rc = -ENOMEM; |
259 | goto _error; | 263 | goto _error; |
@@ -276,11 +280,13 @@ snd_seq_oss_open(struct file *file, int level) | |||
276 | return 0; | 280 | return 0; |
277 | 281 | ||
278 | _error: | 282 | _error: |
283 | snd_seq_oss_writeq_delete(dp->writeq); | ||
284 | snd_seq_oss_readq_delete(dp->readq); | ||
279 | snd_seq_oss_synth_cleanup(dp); | 285 | snd_seq_oss_synth_cleanup(dp); |
280 | snd_seq_oss_midi_cleanup(dp); | 286 | snd_seq_oss_midi_cleanup(dp); |
281 | i = dp->queue; | ||
282 | delete_port(dp); | 287 | delete_port(dp); |
283 | delete_seq_queue(i); | 288 | delete_seq_queue(dp->queue); |
289 | kfree(dp); | ||
284 | 290 | ||
285 | return rc; | 291 | return rc; |
286 | } | 292 | } |
diff --git a/sound/core/seq/oss/seq_oss_writeq.c b/sound/core/seq/oss/seq_oss_writeq.c index 5c8495601a38..217424858191 100644 --- a/sound/core/seq/oss/seq_oss_writeq.c +++ b/sound/core/seq/oss/seq_oss_writeq.c | |||
@@ -63,8 +63,10 @@ snd_seq_oss_writeq_new(struct seq_oss_devinfo *dp, int maxlen) | |||
63 | void | 63 | void |
64 | snd_seq_oss_writeq_delete(struct seq_oss_writeq *q) | 64 | snd_seq_oss_writeq_delete(struct seq_oss_writeq *q) |
65 | { | 65 | { |
66 | snd_seq_oss_writeq_clear(q); /* to be sure */ | 66 | if (q) { |
67 | kfree(q); | 67 | snd_seq_oss_writeq_clear(q); /* to be sure */ |
68 | kfree(q); | ||
69 | } | ||
68 | } | 70 | } |
69 | 71 | ||
70 | 72 | ||
diff --git a/sound/core/seq/seq.c b/sound/core/seq/seq.c index 2f0d8773ac6b..1878208a8026 100644 --- a/sound/core/seq/seq.c +++ b/sound/core/seq/seq.c | |||
@@ -53,7 +53,7 @@ int seq_default_timer_device = | |||
53 | int seq_default_timer_subdevice = 0; | 53 | int seq_default_timer_subdevice = 0; |
54 | int seq_default_timer_resolution = 0; /* Hz */ | 54 | int seq_default_timer_resolution = 0; /* Hz */ |
55 | 55 | ||
56 | MODULE_AUTHOR("Frank van de Pol <fvdpol@coil.demon.nl>, Jaroslav Kysela <perex@suse.cz>"); | 56 | MODULE_AUTHOR("Frank van de Pol <fvdpol@coil.demon.nl>, Jaroslav Kysela <perex@perex.cz>"); |
57 | MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer."); | 57 | MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer."); |
58 | MODULE_LICENSE("GPL"); | 58 | MODULE_LICENSE("GPL"); |
59 | 59 | ||
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index b31b5282a2c8..2e3fa25ab19f 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * ALSA sequencer Client Manager | 2 | * ALSA sequencer Client Manager |
3 | * Copyright (c) 1998-2001 by Frank van de Pol <fvdpol@coil.demon.nl> | 3 | * Copyright (c) 1998-2001 by Frank van de Pol <fvdpol@coil.demon.nl> |
4 | * Jaroslav Kysela <perex@suse.cz> | 4 | * Jaroslav Kysela <perex@perex.cz> |
5 | * Takashi Iwai <tiwai@suse.de> | 5 | * Takashi Iwai <tiwai@suse.de> |
6 | * | 6 | * |
7 | * | 7 | * |
diff --git a/sound/core/seq/seq_instr.c b/sound/core/seq/seq_instr.c index 5efe6523a589..9a6fd56c9109 100644 --- a/sound/core/seq/seq_instr.c +++ b/sound/core/seq/seq_instr.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Generic Instrument routines for ALSA sequencer | 2 | * Generic Instrument routines for ALSA sequencer |
3 | * Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 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 | 6 | * it under the terms of the GNU General Public License as published by |
@@ -26,7 +26,7 @@ | |||
26 | #include <sound/seq_instr.h> | 26 | #include <sound/seq_instr.h> |
27 | #include <sound/initval.h> | 27 | #include <sound/initval.h> |
28 | 28 | ||
29 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 29 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
30 | MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer instrument library."); | 30 | MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer instrument library."); |
31 | MODULE_LICENSE("GPL"); | 31 | MODULE_LICENSE("GPL"); |
32 | 32 | ||
@@ -109,7 +109,7 @@ void snd_seq_instr_list_free(struct snd_seq_kinstr_list **list_ptr) | |||
109 | spin_lock_irqsave(&list->lock, flags); | 109 | spin_lock_irqsave(&list->lock, flags); |
110 | while (instr->use) { | 110 | while (instr->use) { |
111 | spin_unlock_irqrestore(&list->lock, flags); | 111 | spin_unlock_irqrestore(&list->lock, flags); |
112 | schedule_timeout(1); | 112 | schedule_timeout_uninterruptible(1); |
113 | spin_lock_irqsave(&list->lock, flags); | 113 | spin_lock_irqsave(&list->lock, flags); |
114 | } | 114 | } |
115 | spin_unlock_irqrestore(&list->lock, flags); | 115 | spin_unlock_irqrestore(&list->lock, flags); |
@@ -198,8 +198,10 @@ int snd_seq_instr_list_free_cond(struct snd_seq_kinstr_list *list, | |||
198 | while (flist) { | 198 | while (flist) { |
199 | instr = flist; | 199 | instr = flist; |
200 | flist = instr->next; | 200 | flist = instr->next; |
201 | while (instr->use) | 201 | while (instr->use) { |
202 | schedule_timeout(1); | 202 | schedule_timeout_uninterruptible(1); |
203 | barrier(); | ||
204 | } | ||
203 | if (snd_seq_instr_free(instr, atomic)<0) | 205 | if (snd_seq_instr_free(instr, atomic)<0) |
204 | snd_printk(KERN_WARNING "instrument free problem\n"); | 206 | snd_printk(KERN_WARNING "instrument free problem\n"); |
205 | instr = next; | 207 | instr = next; |
@@ -555,7 +557,7 @@ static int instr_free(struct snd_seq_kinstr_ops *ops, | |||
555 | SNDRV_SEQ_INSTR_NOTIFY_REMOVE); | 557 | SNDRV_SEQ_INSTR_NOTIFY_REMOVE); |
556 | while (instr->use) { | 558 | while (instr->use) { |
557 | spin_unlock_irqrestore(&list->lock, flags); | 559 | spin_unlock_irqrestore(&list->lock, flags); |
558 | schedule_timeout(1); | 560 | schedule_timeout_uninterruptible(1); |
559 | spin_lock_irqsave(&list->lock, flags); | 561 | spin_lock_irqsave(&list->lock, flags); |
560 | } | 562 | } |
561 | spin_unlock_irqrestore(&list->lock, flags); | 563 | spin_unlock_irqrestore(&list->lock, flags); |
diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c index a3dc5e01e9f2..a72a1945bf8a 100644 --- a/sound/core/seq/seq_memory.c +++ b/sound/core/seq/seq_memory.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * ALSA sequencer Memory Manager | 2 | * ALSA sequencer Memory Manager |
3 | * Copyright (c) 1998 by Frank van de Pol <fvdpol@coil.demon.nl> | 3 | * Copyright (c) 1998 by Frank van de Pol <fvdpol@coil.demon.nl> |
4 | * Jaroslav Kysela <perex@suse.cz> | 4 | * Jaroslav Kysela <perex@perex.cz> |
5 | * 2000 by Takashi Iwai <tiwai@suse.de> | 5 | * 2000 by Takashi Iwai <tiwai@suse.de> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c index 1daa5b069c79..5929aaf1df9d 100644 --- a/sound/core/seq/seq_midi.c +++ b/sound/core/seq/seq_midi.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Generic MIDI synth driver for ALSA sequencer | 2 | * Generic MIDI synth driver for ALSA sequencer |
3 | * Copyright (c) 1998 by Frank van de Pol <fvdpol@coil.demon.nl> | 3 | * Copyright (c) 1998 by Frank van de Pol <fvdpol@coil.demon.nl> |
4 | * Jaroslav Kysela <perex@suse.cz> | 4 | * Jaroslav Kysela <perex@perex.cz> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
@@ -40,7 +40,7 @@ Possible options for midisynth module: | |||
40 | #include <sound/seq_midi_event.h> | 40 | #include <sound/seq_midi_event.h> |
41 | #include <sound/initval.h> | 41 | #include <sound/initval.h> |
42 | 42 | ||
43 | MODULE_AUTHOR("Frank van de Pol <fvdpol@coil.demon.nl>, Jaroslav Kysela <perex@suse.cz>"); | 43 | MODULE_AUTHOR("Frank van de Pol <fvdpol@coil.demon.nl>, Jaroslav Kysela <perex@perex.cz>"); |
44 | MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer MIDI synth."); | 44 | MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer MIDI synth."); |
45 | MODULE_LICENSE("GPL"); | 45 | MODULE_LICENSE("GPL"); |
46 | static int output_buffer_size = PAGE_SIZE; | 46 | static int output_buffer_size = PAGE_SIZE; |
diff --git a/sound/core/seq/seq_midi_event.c b/sound/core/seq/seq_midi_event.c index 5ff80b776906..b6820a5a73fc 100644 --- a/sound/core/seq/seq_midi_event.c +++ b/sound/core/seq/seq_midi_event.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * MIDI byte <-> sequencer event coder | 2 | * MIDI byte <-> sequencer event coder |
3 | * | 3 | * |
4 | * Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>, | 4 | * Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>, |
5 | * Jaroslav Kysela <perex@suse.cz> | 5 | * Jaroslav Kysela <perex@perex.cz> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by | 8 | * it under the terms of the GNU General Public License as published by |
@@ -28,14 +28,13 @@ | |||
28 | #include <sound/seq_midi_event.h> | 28 | #include <sound/seq_midi_event.h> |
29 | #include <sound/asoundef.h> | 29 | #include <sound/asoundef.h> |
30 | 30 | ||
31 | MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>, Jaroslav Kysela <perex@suse.cz>"); | 31 | MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>, Jaroslav Kysela <perex@perex.cz>"); |
32 | MODULE_DESCRIPTION("MIDI byte <-> sequencer event coder"); | 32 | MODULE_DESCRIPTION("MIDI byte <-> sequencer event coder"); |
33 | MODULE_LICENSE("GPL"); | 33 | MODULE_LICENSE("GPL"); |
34 | 34 | ||
35 | /* queue type */ | 35 | /* event type, index into status_event[] */ |
36 | /* from 0 to 7 are normal commands (note off, on, etc.) */ | 36 | /* from 0 to 6 are normal commands (note off, on, etc.) for 0x9?-0xe? */ |
37 | #define ST_NOTEOFF 0 | 37 | #define ST_INVALID 7 |
38 | #define ST_NOTEON 1 | ||
39 | #define ST_SPECIAL 8 | 38 | #define ST_SPECIAL 8 |
40 | #define ST_SYSEX ST_SPECIAL | 39 | #define ST_SYSEX ST_SPECIAL |
41 | /* from 8 to 15 are events for 0xf0-0xf7 */ | 40 | /* from 8 to 15 are events for 0xf0-0xf7 */ |
@@ -65,32 +64,33 @@ static struct status_event_list { | |||
65 | void (*encode)(struct snd_midi_event *dev, struct snd_seq_event *ev); | 64 | void (*encode)(struct snd_midi_event *dev, struct snd_seq_event *ev); |
66 | void (*decode)(struct snd_seq_event *ev, unsigned char *buf); | 65 | void (*decode)(struct snd_seq_event *ev, unsigned char *buf); |
67 | } status_event[] = { | 66 | } status_event[] = { |
68 | /* 0x80 - 0xf0 */ | 67 | /* 0x80 - 0xef */ |
69 | {SNDRV_SEQ_EVENT_NOTEOFF, 2, note_event, note_decode}, | 68 | {SNDRV_SEQ_EVENT_NOTEOFF, 2, note_event, note_decode}, |
70 | {SNDRV_SEQ_EVENT_NOTEON, 2, note_event, note_decode}, | 69 | {SNDRV_SEQ_EVENT_NOTEON, 2, note_event, note_decode}, |
71 | {SNDRV_SEQ_EVENT_KEYPRESS, 2, note_event, note_decode}, | 70 | {SNDRV_SEQ_EVENT_KEYPRESS, 2, note_event, note_decode}, |
72 | {SNDRV_SEQ_EVENT_CONTROLLER, 2, two_param_ctrl_event, two_param_decode}, | 71 | {SNDRV_SEQ_EVENT_CONTROLLER, 2, two_param_ctrl_event, two_param_decode}, |
73 | {SNDRV_SEQ_EVENT_PGMCHANGE, 1, one_param_ctrl_event, one_param_decode}, | 72 | {SNDRV_SEQ_EVENT_PGMCHANGE, 1, one_param_ctrl_event, one_param_decode}, |
74 | {SNDRV_SEQ_EVENT_CHANPRESS, 1, one_param_ctrl_event, one_param_decode}, | 73 | {SNDRV_SEQ_EVENT_CHANPRESS, 1, one_param_ctrl_event, one_param_decode}, |
75 | {SNDRV_SEQ_EVENT_PITCHBEND, 2, pitchbend_ctrl_event, pitchbend_decode}, | 74 | {SNDRV_SEQ_EVENT_PITCHBEND, 2, pitchbend_ctrl_event, pitchbend_decode}, |
76 | {SNDRV_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xf0 */ | 75 | /* invalid */ |
76 | {SNDRV_SEQ_EVENT_NONE, -1, NULL, NULL}, | ||
77 | /* 0xf0 - 0xff */ | 77 | /* 0xf0 - 0xff */ |
78 | {SNDRV_SEQ_EVENT_SYSEX, 1, NULL, NULL}, /* sysex: 0xf0 */ | 78 | {SNDRV_SEQ_EVENT_SYSEX, 1, NULL, NULL}, /* sysex: 0xf0 */ |
79 | {SNDRV_SEQ_EVENT_QFRAME, 1, one_param_event, one_param_decode}, /* 0xf1 */ | 79 | {SNDRV_SEQ_EVENT_QFRAME, 1, one_param_event, one_param_decode}, /* 0xf1 */ |
80 | {SNDRV_SEQ_EVENT_SONGPOS, 2, songpos_event, songpos_decode}, /* 0xf2 */ | 80 | {SNDRV_SEQ_EVENT_SONGPOS, 2, songpos_event, songpos_decode}, /* 0xf2 */ |
81 | {SNDRV_SEQ_EVENT_SONGSEL, 1, one_param_event, one_param_decode}, /* 0xf3 */ | 81 | {SNDRV_SEQ_EVENT_SONGSEL, 1, one_param_event, one_param_decode}, /* 0xf3 */ |
82 | {SNDRV_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xf4 */ | 82 | {SNDRV_SEQ_EVENT_NONE, -1, NULL, NULL}, /* 0xf4 */ |
83 | {SNDRV_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xf5 */ | 83 | {SNDRV_SEQ_EVENT_NONE, -1, NULL, NULL}, /* 0xf5 */ |
84 | {SNDRV_SEQ_EVENT_TUNE_REQUEST, 0, NULL, NULL}, /* 0xf6 */ | 84 | {SNDRV_SEQ_EVENT_TUNE_REQUEST, 0, NULL, NULL}, /* 0xf6 */ |
85 | {SNDRV_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xf7 */ | 85 | {SNDRV_SEQ_EVENT_NONE, -1, NULL, NULL}, /* 0xf7 */ |
86 | {SNDRV_SEQ_EVENT_CLOCK, 0, NULL, NULL}, /* 0xf8 */ | 86 | {SNDRV_SEQ_EVENT_CLOCK, 0, NULL, NULL}, /* 0xf8 */ |
87 | {SNDRV_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xf9 */ | 87 | {SNDRV_SEQ_EVENT_NONE, -1, NULL, NULL}, /* 0xf9 */ |
88 | {SNDRV_SEQ_EVENT_START, 0, NULL, NULL}, /* 0xfa */ | 88 | {SNDRV_SEQ_EVENT_START, 0, NULL, NULL}, /* 0xfa */ |
89 | {SNDRV_SEQ_EVENT_CONTINUE, 0, NULL, NULL}, /* 0xfb */ | 89 | {SNDRV_SEQ_EVENT_CONTINUE, 0, NULL, NULL}, /* 0xfb */ |
90 | {SNDRV_SEQ_EVENT_STOP, 0, NULL, NULL}, /* 0xfc */ | 90 | {SNDRV_SEQ_EVENT_STOP, 0, NULL, NULL}, /* 0xfc */ |
91 | {SNDRV_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xfd */ | 91 | {SNDRV_SEQ_EVENT_NONE, -1, NULL, NULL}, /* 0xfd */ |
92 | {SNDRV_SEQ_EVENT_SENSING, 0, NULL, NULL}, /* 0xfe */ | 92 | {SNDRV_SEQ_EVENT_SENSING, 0, NULL, NULL}, /* 0xfe */ |
93 | {SNDRV_SEQ_EVENT_RESET, 0, NULL, NULL}, /* 0xff */ | 93 | {SNDRV_SEQ_EVENT_RESET, 0, NULL, NULL}, /* 0xff */ |
94 | }; | 94 | }; |
95 | 95 | ||
96 | static int extra_decode_ctrl14(struct snd_midi_event *dev, unsigned char *buf, int len, | 96 | static int extra_decode_ctrl14(struct snd_midi_event *dev, unsigned char *buf, int len, |
@@ -129,6 +129,7 @@ int snd_midi_event_new(int bufsize, struct snd_midi_event **rdev) | |||
129 | } | 129 | } |
130 | dev->bufsize = bufsize; | 130 | dev->bufsize = bufsize; |
131 | dev->lastcmd = 0xff; | 131 | dev->lastcmd = 0xff; |
132 | dev->type = ST_INVALID; | ||
132 | spin_lock_init(&dev->lock); | 133 | spin_lock_init(&dev->lock); |
133 | *rdev = dev; | 134 | *rdev = dev; |
134 | return 0; | 135 | return 0; |
@@ -149,7 +150,7 @@ static inline void reset_encode(struct snd_midi_event *dev) | |||
149 | { | 150 | { |
150 | dev->read = 0; | 151 | dev->read = 0; |
151 | dev->qlen = 0; | 152 | dev->qlen = 0; |
152 | dev->type = 0; | 153 | dev->type = ST_INVALID; |
153 | } | 154 | } |
154 | 155 | ||
155 | void snd_midi_event_reset_encode(struct snd_midi_event *dev) | 156 | void snd_midi_event_reset_encode(struct snd_midi_event *dev) |
@@ -251,29 +252,31 @@ int snd_midi_event_encode_byte(struct snd_midi_event *dev, int c, | |||
251 | ev->type = status_event[ST_SPECIAL + c - 0xf0].event; | 252 | ev->type = status_event[ST_SPECIAL + c - 0xf0].event; |
252 | ev->flags &= ~SNDRV_SEQ_EVENT_LENGTH_MASK; | 253 | ev->flags &= ~SNDRV_SEQ_EVENT_LENGTH_MASK; |
253 | ev->flags |= SNDRV_SEQ_EVENT_LENGTH_FIXED; | 254 | ev->flags |= SNDRV_SEQ_EVENT_LENGTH_FIXED; |
254 | return 1; | 255 | return ev->type != SNDRV_SEQ_EVENT_NONE; |
255 | } | 256 | } |
256 | 257 | ||
257 | spin_lock_irqsave(&dev->lock, flags); | 258 | spin_lock_irqsave(&dev->lock, flags); |
258 | if (dev->qlen > 0) { | 259 | if ((c & 0x80) && |
259 | /* rest of command */ | 260 | (c != MIDI_CMD_COMMON_SYSEX_END || dev->type != ST_SYSEX)) { |
260 | dev->buf[dev->read++] = c; | ||
261 | if (dev->type != ST_SYSEX) | ||
262 | dev->qlen--; | ||
263 | } else { | ||
264 | /* new command */ | 261 | /* new command */ |
262 | dev->buf[0] = c; | ||
263 | if ((c & 0xf0) == 0xf0) /* system messages */ | ||
264 | dev->type = (c & 0x0f) + ST_SPECIAL; | ||
265 | else | ||
266 | dev->type = (c >> 4) & 0x07; | ||
265 | dev->read = 1; | 267 | dev->read = 1; |
266 | if (c & 0x80) { | 268 | dev->qlen = status_event[dev->type].qlen; |
267 | dev->buf[0] = c; | 269 | } else { |
268 | if ((c & 0xf0) == 0xf0) /* special events */ | 270 | if (dev->qlen > 0) { |
269 | dev->type = (c & 0x0f) + ST_SPECIAL; | 271 | /* rest of command */ |
270 | else | ||
271 | dev->type = (c >> 4) & 0x07; | ||
272 | dev->qlen = status_event[dev->type].qlen; | ||
273 | } else { | ||
274 | /* process this byte as argument */ | ||
275 | dev->buf[dev->read++] = c; | 272 | dev->buf[dev->read++] = c; |
273 | if (dev->type != ST_SYSEX) | ||
274 | dev->qlen--; | ||
275 | } else { | ||
276 | /* running status */ | ||
277 | dev->buf[1] = c; | ||
276 | dev->qlen = status_event[dev->type].qlen - 1; | 278 | dev->qlen = status_event[dev->type].qlen - 1; |
279 | dev->read = 2; | ||
277 | } | 280 | } |
278 | } | 281 | } |
279 | if (dev->qlen == 0) { | 282 | if (dev->qlen == 0) { |
@@ -282,6 +285,8 @@ int snd_midi_event_encode_byte(struct snd_midi_event *dev, int c, | |||
282 | ev->flags |= SNDRV_SEQ_EVENT_LENGTH_FIXED; | 285 | ev->flags |= SNDRV_SEQ_EVENT_LENGTH_FIXED; |
283 | if (status_event[dev->type].encode) /* set data values */ | 286 | if (status_event[dev->type].encode) /* set data values */ |
284 | status_event[dev->type].encode(dev, ev); | 287 | status_event[dev->type].encode(dev, ev); |
288 | if (dev->type >= ST_SPECIAL) | ||
289 | dev->type = ST_INVALID; | ||
285 | rc = 1; | 290 | rc = 1; |
286 | } else if (dev->type == ST_SYSEX) { | 291 | } else if (dev->type == ST_SYSEX) { |
287 | if (c == MIDI_CMD_COMMON_SYSEX_END || | 292 | if (c == MIDI_CMD_COMMON_SYSEX_END || |
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c index eefd1cf872b4..b6e23ad12ab9 100644 --- a/sound/core/seq/seq_ports.c +++ b/sound/core/seq/seq_ports.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * ALSA sequencer Ports | 2 | * ALSA sequencer Ports |
3 | * Copyright (c) 1998 by Frank van de Pol <fvdpol@coil.demon.nl> | 3 | * Copyright (c) 1998 by Frank van de Pol <fvdpol@coil.demon.nl> |
4 | * Jaroslav Kysela <perex@suse.cz> | 4 | * Jaroslav Kysela <perex@perex.cz> |
5 | * | 5 | * |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
diff --git a/sound/core/seq/seq_timer.c b/sound/core/seq/seq_timer.c index b4b9a132cb16..8716352afc81 100644 --- a/sound/core/seq/seq_timer.c +++ b/sound/core/seq/seq_timer.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * ALSA sequencer Timer | 2 | * ALSA sequencer Timer |
3 | * Copyright (c) 1998-1999 by Frank van de Pol <fvdpol@coil.demon.nl> | 3 | * Copyright (c) 1998-1999 by Frank van de Pol <fvdpol@coil.demon.nl> |
4 | * Jaroslav Kysela <perex@suse.cz> | 4 | * Jaroslav Kysela <perex@perex.cz> |
5 | * | 5 | * |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
diff --git a/sound/core/sound.c b/sound/core/sound.c index 8dc7a3b32b98..7b486c4d70db 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Advanced Linux Sound Architecture | 2 | * Advanced Linux Sound Architecture |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -42,7 +42,7 @@ EXPORT_SYMBOL(snd_major); | |||
42 | 42 | ||
43 | static int cards_limit = 1; | 43 | static int cards_limit = 1; |
44 | 44 | ||
45 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 45 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
46 | MODULE_DESCRIPTION("Advanced Linux Sound Architecture driver for soundcards."); | 46 | MODULE_DESCRIPTION("Advanced Linux Sound Architecture driver for soundcards."); |
47 | MODULE_LICENSE("GPL"); | 47 | MODULE_LICENSE("GPL"); |
48 | module_param(major, int, 0444); | 48 | module_param(major, int, 0444); |
@@ -266,6 +266,14 @@ int snd_register_device_for_dev(int type, struct snd_card *card, int dev, | |||
266 | snd_minors[minor] = preg; | 266 | snd_minors[minor] = preg; |
267 | preg->dev = device_create(sound_class, device, MKDEV(major, minor), | 267 | preg->dev = device_create(sound_class, device, MKDEV(major, minor), |
268 | "%s", name); | 268 | "%s", name); |
269 | if (IS_ERR(preg->dev)) { | ||
270 | snd_minors[minor] = NULL; | ||
271 | mutex_unlock(&sound_mutex); | ||
272 | minor = PTR_ERR(preg->dev); | ||
273 | kfree(preg); | ||
274 | return minor; | ||
275 | } | ||
276 | |||
269 | if (preg->dev) | 277 | if (preg->dev) |
270 | dev_set_drvdata(preg->dev, private_data); | 278 | dev_set_drvdata(preg->dev, private_data); |
271 | 279 | ||
diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c index 4566df41912a..dc73313b733a 100644 --- a/sound/core/sound_oss.c +++ b/sound/core/sound_oss.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Advanced Linux Sound Architecture | 2 | * Advanced Linux Sound Architecture |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
diff --git a/sound/core/timer.c b/sound/core/timer.c index f2bbacedd567..e7dc56ca4b97 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Timers abstract layer | 2 | * Timers abstract layer |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -44,7 +44,7 @@ | |||
44 | #endif | 44 | #endif |
45 | 45 | ||
46 | static int timer_limit = DEFAULT_TIMER_LIMIT; | 46 | static int timer_limit = DEFAULT_TIMER_LIMIT; |
47 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Takashi Iwai <tiwai@suse.de>"); | 47 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.de>"); |
48 | MODULE_DESCRIPTION("ALSA timer interface"); | 48 | MODULE_DESCRIPTION("ALSA timer interface"); |
49 | MODULE_LICENSE("GPL"); | 49 | MODULE_LICENSE("GPL"); |
50 | module_param(timer_limit, int, 0444); | 50 | module_param(timer_limit, int, 0444); |
diff --git a/sound/drivers/Makefile b/sound/drivers/Makefile index 04112642611a..80aeff5ccdea 100644 --- a/sound/drivers/Makefile +++ b/sound/drivers/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-dummy-objs := dummy.o | 6 | snd-dummy-objs := dummy.o |
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c index 4360ae9de19c..e008f3c58eac 100644 --- a/sound/drivers/dummy.c +++ b/sound/drivers/dummy.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Dummy soundcard | 2 | * Dummy soundcard |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 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 | 6 | * it under the terms of the GNU General Public License as published by |
@@ -34,7 +34,7 @@ | |||
34 | #include <sound/rawmidi.h> | 34 | #include <sound/rawmidi.h> |
35 | #include <sound/initval.h> | 35 | #include <sound/initval.h> |
36 | 36 | ||
37 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 37 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
38 | MODULE_DESCRIPTION("Dummy soundcard (/dev/null)"); | 38 | MODULE_DESCRIPTION("Dummy soundcard (/dev/null)"); |
39 | MODULE_LICENSE("GPL"); | 39 | MODULE_LICENSE("GPL"); |
40 | MODULE_SUPPORTED_DEVICE("{{ALSA,Dummy soundcard}}"); | 40 | MODULE_SUPPORTED_DEVICE("{{ALSA,Dummy soundcard}}"); |
@@ -510,15 +510,7 @@ static const DECLARE_TLV_DB_SCALE(db_scale_dummy, -4500, 30, 0); | |||
510 | .get = snd_dummy_capsrc_get, .put = snd_dummy_capsrc_put, \ | 510 | .get = snd_dummy_capsrc_get, .put = snd_dummy_capsrc_put, \ |
511 | .private_value = addr } | 511 | .private_value = addr } |
512 | 512 | ||
513 | static int snd_dummy_capsrc_info(struct snd_kcontrol *kcontrol, | 513 | #define snd_dummy_capsrc_info snd_ctl_boolean_stereo_info |
514 | struct snd_ctl_elem_info *uinfo) | ||
515 | { | ||
516 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
517 | uinfo->count = 2; | ||
518 | uinfo->value.integer.min = 0; | ||
519 | uinfo->value.integer.max = 1; | ||
520 | return 0; | ||
521 | } | ||
522 | 514 | ||
523 | static int snd_dummy_capsrc_get(struct snd_kcontrol *kcontrol, | 515 | static int snd_dummy_capsrc_get(struct snd_kcontrol *kcontrol, |
524 | struct snd_ctl_elem_value *ucontrol) | 516 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/drivers/mpu401/Makefile b/sound/drivers/mpu401/Makefile index 3fe185d19ae5..918f83f34c11 100644 --- a/sound/drivers/mpu401/Makefile +++ b/sound/drivers/mpu401/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-mpu401-objs := mpu401.o | 6 | snd-mpu401-objs := mpu401.o |
diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c index 67c6e9745418..1fc95dadde1d 100644 --- a/sound/drivers/mpu401/mpu401.c +++ b/sound/drivers/mpu401/mpu401.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for generic MPU-401 boards (UART mode only) | 2 | * Driver for generic MPU-401 boards (UART mode only) |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * Copyright (c) 2004 by Castet Matthieu <castet.matthieu@free.fr> | 4 | * Copyright (c) 2004 by Castet Matthieu <castet.matthieu@free.fr> |
5 | * | 5 | * |
6 | * | 6 | * |
@@ -30,7 +30,7 @@ | |||
30 | #include <sound/mpu401.h> | 30 | #include <sound/mpu401.h> |
31 | #include <sound/initval.h> | 31 | #include <sound/initval.h> |
32 | 32 | ||
33 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 33 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
34 | MODULE_DESCRIPTION("MPU-401 UART"); | 34 | MODULE_DESCRIPTION("MPU-401 UART"); |
35 | MODULE_LICENSE("GPL"); | 35 | MODULE_LICENSE("GPL"); |
36 | 36 | ||
@@ -70,6 +70,9 @@ static int snd_mpu401_create(int dev, struct snd_card **rcard) | |||
70 | struct snd_card *card; | 70 | struct snd_card *card; |
71 | int err; | 71 | int err; |
72 | 72 | ||
73 | if (!uart_enter[dev]) | ||
74 | snd_printk(KERN_ERR "the uart_enter option is obsolete; remove it\n"); | ||
75 | |||
73 | *rcard = NULL; | 76 | *rcard = NULL; |
74 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 77 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); |
75 | if (card == NULL) | 78 | if (card == NULL) |
@@ -83,8 +86,7 @@ static int snd_mpu401_create(int dev, struct snd_card **rcard) | |||
83 | strcat(card->longname, "polled"); | 86 | strcat(card->longname, "polled"); |
84 | } | 87 | } |
85 | 88 | ||
86 | err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port[dev], | 89 | err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port[dev], 0, |
87 | uart_enter[dev] ? 0 : MPU401_INFO_UART_ONLY, | ||
88 | irq[dev], irq[dev] >= 0 ? IRQF_DISABLED : 0, | 90 | irq[dev], irq[dev] >= 0 ? IRQF_DISABLED : 0, |
89 | NULL); | 91 | NULL); |
90 | if (err < 0) { | 92 | if (err < 0) { |
diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c index 85aedc348e2d..3306ecd49243 100644 --- a/sound/drivers/mpu401/mpu401_uart.c +++ b/sound/drivers/mpu401/mpu401_uart.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Routines for control of MPU-401 in UART mode | 3 | * Routines for control of MPU-401 in UART mode |
4 | * | 4 | * |
5 | * MPU-401 supports UART mode which is not capable generate transmit | 5 | * MPU-401 supports UART mode which is not capable generate transmit |
@@ -39,7 +39,7 @@ | |||
39 | #include <sound/core.h> | 39 | #include <sound/core.h> |
40 | #include <sound/mpu401.h> | 40 | #include <sound/mpu401.h> |
41 | 41 | ||
42 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 42 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
43 | MODULE_DESCRIPTION("Routines for control of MPU-401 in UART mode"); | 43 | MODULE_DESCRIPTION("Routines for control of MPU-401 in UART mode"); |
44 | MODULE_LICENSE("GPL"); | 44 | MODULE_LICENSE("GPL"); |
45 | 45 | ||
@@ -270,8 +270,7 @@ static int snd_mpu401_do_reset(struct snd_mpu401 *mpu) | |||
270 | { | 270 | { |
271 | if (snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1)) | 271 | if (snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1)) |
272 | return -EIO; | 272 | return -EIO; |
273 | if (!(mpu->info_flags & MPU401_INFO_UART_ONLY) && | 273 | if (snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 0)) |
274 | snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1)) | ||
275 | return -EIO; | 274 | return -EIO; |
276 | return 0; | 275 | return 0; |
277 | } | 276 | } |
diff --git a/sound/drivers/mts64.c b/sound/drivers/mts64.c index 2025db5947ae..911c159bb3d3 100644 --- a/sound/drivers/mts64.c +++ b/sound/drivers/mts64.c | |||
@@ -440,15 +440,7 @@ static void mts64_write_midi(struct mts64 *mts, u8 c, | |||
440 | *********************************************************************/ | 440 | *********************************************************************/ |
441 | 441 | ||
442 | /* SMPTE Switch */ | 442 | /* SMPTE Switch */ |
443 | static int snd_mts64_ctl_smpte_switch_info(struct snd_kcontrol *kctl, | 443 | #define snd_mts64_ctl_smpte_switch_info snd_ctl_boolean_mono_info |
444 | struct snd_ctl_elem_info *uinfo) | ||
445 | { | ||
446 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
447 | uinfo->count = 1; | ||
448 | uinfo->value.integer.min = 0; | ||
449 | uinfo->value.integer.max = 1; | ||
450 | return 0; | ||
451 | } | ||
452 | 444 | ||
453 | static int snd_mts64_ctl_smpte_switch_get(struct snd_kcontrol* kctl, | 445 | static int snd_mts64_ctl_smpte_switch_get(struct snd_kcontrol* kctl, |
454 | struct snd_ctl_elem_value *uctl) | 446 | struct snd_ctl_elem_value *uctl) |
diff --git a/sound/drivers/opl3/Makefile b/sound/drivers/opl3/Makefile index 12059785b5cb..19767a6a5c54 100644 --- a/sound/drivers/opl3/Makefile +++ b/sound/drivers/opl3/Makefile | |||
@@ -1,13 +1,11 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-opl3-lib-objs := opl3_lib.o opl3_synth.o | 6 | snd-opl3-lib-objs := opl3_lib.o opl3_synth.o |
7 | snd-opl3-synth-objs := opl3_seq.o opl3_midi.o opl3_drums.o | 7 | snd-opl3-synth-y := opl3_seq.o opl3_midi.o opl3_drums.o |
8 | ifeq ($(CONFIG_SND_SEQUENCER_OSS),y) | 8 | snd-opl3-synth-$(CONFIG_SND_SEQUENCER_OSS) += opl3_oss.o |
9 | snd-opl3-synth-objs += opl3_oss.o | ||
10 | endif | ||
11 | 9 | ||
12 | # | 10 | # |
13 | # this function returns: | 11 | # this function returns: |
diff --git a/sound/drivers/opl3/opl3_lib.c b/sound/drivers/opl3/opl3_lib.c index 87fe376f38f0..a2b9ce060295 100644 --- a/sound/drivers/opl3/opl3_lib.c +++ b/sound/drivers/opl3/opl3_lib.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz>, | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz>, |
3 | * Hannu Savolainen 1993-1996, | 3 | * Hannu Savolainen 1993-1996, |
4 | * Rob Hooft | 4 | * Rob Hooft |
5 | * | 5 | * |
@@ -31,7 +31,7 @@ | |||
31 | #include <linux/ioport.h> | 31 | #include <linux/ioport.h> |
32 | #include <sound/minors.h> | 32 | #include <sound/minors.h> |
33 | 33 | ||
34 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Hannu Savolainen 1993-1996, Rob Hooft"); | 34 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Hannu Savolainen 1993-1996, Rob Hooft"); |
35 | MODULE_DESCRIPTION("Routines for control of AdLib FM cards (OPL2/OPL3/OPL4 chips)"); | 35 | MODULE_DESCRIPTION("Routines for control of AdLib FM cards (OPL2/OPL3/OPL4 chips)"); |
36 | MODULE_LICENSE("GPL"); | 36 | MODULE_LICENSE("GPL"); |
37 | 37 | ||
diff --git a/sound/drivers/opl4/Makefile b/sound/drivers/opl4/Makefile index 141aacbaf315..d178b39ffa60 100644 --- a/sound/drivers/opl4/Makefile +++ b/sound/drivers/opl4/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-opl4-lib-objs := opl4_lib.o opl4_mixer.o opl4_proc.o | 6 | snd-opl4-lib-objs := opl4_lib.o opl4_mixer.o opl4_proc.o |
diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c index d3e6a20edd38..65de3a755ddb 100644 --- a/sound/drivers/serial-u16550.c +++ b/sound/drivers/serial-u16550.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * serial.c | 2 | * serial.c |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz>, | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz>, |
4 | * Isaku Yamahata <yamahata@private.email.ne.jp>, | 4 | * Isaku Yamahata <yamahata@private.email.ne.jp>, |
5 | * George Hansper <ghansper@apana.org.au>, | 5 | * George Hansper <ghansper@apana.org.au>, |
6 | * Hannu Savolainen | 6 | * Hannu Savolainen |
diff --git a/sound/drivers/vx/Makefile b/sound/drivers/vx/Makefile index 269bd8544a5d..9a168a3c1560 100644 --- a/sound/drivers/vx/Makefile +++ b/sound/drivers/vx/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-vx-lib-objs := vx_core.o vx_hwdep.o vx_pcm.o vx_mixer.o vx_cmd.o vx_uer.o | 6 | snd-vx-lib-objs := vx_core.o vx_hwdep.o vx_pcm.o vx_mixer.o vx_cmd.o vx_uer.o |
diff --git a/sound/drivers/vx/vx_mixer.c b/sound/drivers/vx/vx_mixer.c index f63152a6a223..b8fcd79a7e11 100644 --- a/sound/drivers/vx/vx_mixer.c +++ b/sound/drivers/vx/vx_mixer.c | |||
@@ -647,14 +647,7 @@ static int vx_audio_monitor_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el | |||
647 | return 0; | 647 | return 0; |
648 | } | 648 | } |
649 | 649 | ||
650 | static int vx_audio_sw_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 650 | #define vx_audio_sw_info snd_ctl_boolean_stereo_info |
651 | { | ||
652 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
653 | uinfo->count = 2; | ||
654 | uinfo->value.integer.min = 0; | ||
655 | uinfo->value.integer.max = 1; | ||
656 | return 0; | ||
657 | } | ||
658 | 651 | ||
659 | static int vx_audio_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 652 | static int vx_audio_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
660 | { | 653 | { |
@@ -865,14 +858,7 @@ static int vx_peak_meter_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ | |||
865 | return 0; | 858 | return 0; |
866 | } | 859 | } |
867 | 860 | ||
868 | static int vx_saturation_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 861 | #define vx_saturation_info snd_ctl_boolean_stereo_info |
869 | { | ||
870 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
871 | uinfo->count = 2; | ||
872 | uinfo->value.integer.min = 0; | ||
873 | uinfo->value.integer.max = 1; | ||
874 | return 0; | ||
875 | } | ||
876 | 862 | ||
877 | static int vx_saturation_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 863 | static int vx_saturation_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
878 | { | 864 | { |
diff --git a/sound/i2c/Makefile b/sound/i2c/Makefile index 45902d48c89c..37970666a453 100644 --- a/sound/i2c/Makefile +++ b/sound/i2c/Makefile | |||
@@ -1,15 +1,13 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-i2c-objs := i2c.o | 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 | ifeq ($(subst m,y,$(CONFIG_L3)),y) | 10 | obj-$(CONFIG_L3) += l3/ |
11 | obj-$(CONFIG_L3) += l3/ | ||
12 | endif | ||
13 | 11 | ||
14 | obj-$(CONFIG_SND) += other/ | 12 | obj-$(CONFIG_SND) += other/ |
15 | 13 | ||
diff --git a/sound/i2c/cs8427.c b/sound/i2c/cs8427.c index 64388cb8d6e5..744366b72345 100644 --- a/sound/i2c/cs8427.c +++ b/sound/i2c/cs8427.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Routines for control of the CS8427 via i2c bus | 2 | * Routines for control of the CS8427 via i2c bus |
3 | * IEC958 (S/PDIF) receiver & transmitter by Cirrus Logic | 3 | * IEC958 (S/PDIF) receiver & transmitter by Cirrus Logic |
4 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 4 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
5 | * | 5 | * |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
@@ -32,7 +32,7 @@ | |||
32 | 32 | ||
33 | static void snd_cs8427_reset(struct snd_i2c_device *cs8427); | 33 | static void snd_cs8427_reset(struct snd_i2c_device *cs8427); |
34 | 34 | ||
35 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 35 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
36 | MODULE_DESCRIPTION("IEC958 (S/PDIF) receiver & transmitter by Cirrus Logic"); | 36 | MODULE_DESCRIPTION("IEC958 (S/PDIF) receiver & transmitter by Cirrus Logic"); |
37 | MODULE_LICENSE("GPL"); | 37 | MODULE_LICENSE("GPL"); |
38 | 38 | ||
@@ -229,6 +229,12 @@ int snd_cs8427_create(struct snd_i2c_bus *bus, | |||
229 | snd_i2c_lock(bus); | 229 | snd_i2c_lock(bus); |
230 | err = snd_cs8427_reg_read(device, CS8427_REG_ID_AND_VER); | 230 | err = snd_cs8427_reg_read(device, CS8427_REG_ID_AND_VER); |
231 | if (err != CS8427_VER8427A) { | 231 | if (err != CS8427_VER8427A) { |
232 | /* give second chance */ | ||
233 | snd_printk(KERN_WARNING "invalid CS8427 signature 0x%x: " | ||
234 | "let me try again...\n", err); | ||
235 | err = snd_cs8427_reg_read(device, CS8427_REG_ID_AND_VER); | ||
236 | } | ||
237 | if (err != CS8427_VER8427A) { | ||
232 | snd_i2c_unlock(bus); | 238 | snd_i2c_unlock(bus); |
233 | snd_printk(KERN_ERR "unable to find CS8427 signature " | 239 | snd_printk(KERN_ERR "unable to find CS8427 signature " |
234 | "(expected 0x%x, read 0x%x),\n", | 240 | "(expected 0x%x, read 0x%x),\n", |
diff --git a/sound/i2c/i2c.c b/sound/i2c/i2c.c index b60fb1892828..1e58a963b2a7 100644 --- a/sound/i2c/i2c.c +++ b/sound/i2c/i2c.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * Generic i2c interface for ALSA | 2 | * Generic i2c interface for ALSA |
3 | * | 3 | * |
4 | * (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de> | 4 | * (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de> |
5 | * Modified for the ALSA driver by Jaroslav Kysela <perex@suse.cz> | 5 | * Modified for the ALSA driver by Jaroslav Kysela <perex@perex.cz> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by | 8 | * it under the terms of the GNU General Public License as published by |
@@ -28,7 +28,7 @@ | |||
28 | #include <sound/core.h> | 28 | #include <sound/core.h> |
29 | #include <sound/i2c.h> | 29 | #include <sound/i2c.h> |
30 | 30 | ||
31 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 31 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
32 | MODULE_DESCRIPTION("Generic i2c interface for ALSA"); | 32 | MODULE_DESCRIPTION("Generic i2c interface for ALSA"); |
33 | MODULE_LICENSE("GPL"); | 33 | MODULE_LICENSE("GPL"); |
34 | 34 | ||
diff --git a/sound/i2c/other/Makefile b/sound/i2c/other/Makefile index 77a8a7c75dd9..703d954238f4 100644 --- a/sound/i2c/other/Makefile +++ b/sound/i2c/other/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2003 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2003 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-ak4114-objs := ak4114.o | 6 | snd-ak4114-objs := ak4114.o |
diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c index 1efb973137a6..facde46f957a 100644 --- a/sound/i2c/other/ak4114.c +++ b/sound/i2c/other/ak4114.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Routines for control of the AK4114 via I2C and 4-wire serial interface | 2 | * Routines for control of the AK4114 via I2C and 4-wire serial interface |
3 | * IEC958 (S/PDIF) receiver by Asahi Kasei | 3 | * IEC958 (S/PDIF) receiver by Asahi Kasei |
4 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 4 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
5 | * | 5 | * |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
@@ -29,7 +29,7 @@ | |||
29 | #include <sound/ak4114.h> | 29 | #include <sound/ak4114.h> |
30 | #include <sound/asoundef.h> | 30 | #include <sound/asoundef.h> |
31 | 31 | ||
32 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 32 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
33 | MODULE_DESCRIPTION("AK4114 IEC958 (S/PDIF) receiver by Asahi Kasei"); | 33 | MODULE_DESCRIPTION("AK4114 IEC958 (S/PDIF) receiver by Asahi Kasei"); |
34 | MODULE_LICENSE("GPL"); | 34 | MODULE_LICENSE("GPL"); |
35 | 35 | ||
@@ -200,15 +200,7 @@ static int snd_ak4114_in_error_get(struct snd_kcontrol *kcontrol, | |||
200 | return 0; | 200 | return 0; |
201 | } | 201 | } |
202 | 202 | ||
203 | static int snd_ak4114_in_bit_info(struct snd_kcontrol *kcontrol, | 203 | #define snd_ak4114_in_bit_info snd_ctl_boolean_mono_info |
204 | struct snd_ctl_elem_info *uinfo) | ||
205 | { | ||
206 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
207 | uinfo->count = 1; | ||
208 | uinfo->value.integer.min = 0; | ||
209 | uinfo->value.integer.max = 1; | ||
210 | return 0; | ||
211 | } | ||
212 | 204 | ||
213 | static int snd_ak4114_in_bit_get(struct snd_kcontrol *kcontrol, | 205 | static int snd_ak4114_in_bit_get(struct snd_kcontrol *kcontrol, |
214 | struct snd_ctl_elem_value *ucontrol) | 206 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/i2c/other/ak4117.c b/sound/i2c/other/ak4117.c index c022f29da2f7..ee1585aec99b 100644 --- a/sound/i2c/other/ak4117.c +++ b/sound/i2c/other/ak4117.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Routines for control of the AK4117 via 4-wire serial interface | 2 | * Routines for control of the AK4117 via 4-wire serial interface |
3 | * IEC958 (S/PDIF) receiver by Asahi Kasei | 3 | * IEC958 (S/PDIF) receiver by Asahi Kasei |
4 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 4 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
5 | * | 5 | * |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
@@ -29,7 +29,7 @@ | |||
29 | #include <sound/ak4117.h> | 29 | #include <sound/ak4117.h> |
30 | #include <sound/asoundef.h> | 30 | #include <sound/asoundef.h> |
31 | 31 | ||
32 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 32 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
33 | MODULE_DESCRIPTION("AK4117 IEC958 (S/PDIF) receiver by Asahi Kasei"); | 33 | MODULE_DESCRIPTION("AK4117 IEC958 (S/PDIF) receiver by Asahi Kasei"); |
34 | MODULE_LICENSE("GPL"); | 34 | MODULE_LICENSE("GPL"); |
35 | 35 | ||
@@ -181,15 +181,7 @@ static int snd_ak4117_in_error_get(struct snd_kcontrol *kcontrol, | |||
181 | return 0; | 181 | return 0; |
182 | } | 182 | } |
183 | 183 | ||
184 | static int snd_ak4117_in_bit_info(struct snd_kcontrol *kcontrol, | 184 | #define snd_ak4117_in_bit_info snd_ctl_boolean_mono_info |
185 | struct snd_ctl_elem_info *uinfo) | ||
186 | { | ||
187 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
188 | uinfo->count = 1; | ||
189 | uinfo->value.integer.min = 0; | ||
190 | uinfo->value.integer.max = 1; | ||
191 | return 0; | ||
192 | } | ||
193 | 185 | ||
194 | static int snd_ak4117_in_bit_get(struct snd_kcontrol *kcontrol, | 186 | static int snd_ak4117_in_bit_get(struct snd_kcontrol *kcontrol, |
195 | struct snd_ctl_elem_value *ucontrol) | 187 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c index fd335159f849..de03f689fa2e 100644 --- a/sound/i2c/other/ak4xxx-adda.c +++ b/sound/i2c/other/ak4xxx-adda.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * ALSA driver for AK4524 / AK4528 / AK4529 / AK4355 / AK4358 / AK4381 | 2 | * ALSA driver for AK4524 / AK4528 / AK4529 / AK4355 / AK4358 / AK4381 |
3 | * AD and DA converters | 3 | * AD and DA converters |
4 | * | 4 | * |
5 | * Copyright (c) 2000-2004 Jaroslav Kysela <perex@suse.cz>, | 5 | * Copyright (c) 2000-2004 Jaroslav Kysela <perex@perex.cz>, |
6 | * Takashi Iwai <tiwai@suse.de> | 6 | * Takashi Iwai <tiwai@suse.de> |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
@@ -31,7 +31,7 @@ | |||
31 | #include <sound/tlv.h> | 31 | #include <sound/tlv.h> |
32 | #include <sound/ak4xxx-adda.h> | 32 | #include <sound/ak4xxx-adda.h> |
33 | 33 | ||
34 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Takashi Iwai <tiwai@suse.de>"); | 34 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.de>"); |
35 | MODULE_DESCRIPTION("Routines for control of AK452x / AK43xx AD/DA converters"); | 35 | MODULE_DESCRIPTION("Routines for control of AK452x / AK43xx AD/DA converters"); |
36 | MODULE_LICENSE("GPL"); | 36 | MODULE_LICENSE("GPL"); |
37 | 37 | ||
@@ -463,15 +463,7 @@ static int snd_akm4xxx_deemphasis_put(struct snd_kcontrol *kcontrol, | |||
463 | return change; | 463 | return change; |
464 | } | 464 | } |
465 | 465 | ||
466 | static int ak4xxx_switch_info(struct snd_kcontrol *kcontrol, | 466 | #define ak4xxx_switch_info snd_ctl_boolean_mono_info |
467 | struct snd_ctl_elem_info *uinfo) | ||
468 | { | ||
469 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
470 | uinfo->count = 1; | ||
471 | uinfo->value.integer.min = 0; | ||
472 | uinfo->value.integer.max = 1; | ||
473 | return 0; | ||
474 | } | ||
475 | 467 | ||
476 | static int ak4xxx_switch_get(struct snd_kcontrol *kcontrol, | 468 | static int ak4xxx_switch_get(struct snd_kcontrol *kcontrol, |
477 | struct snd_ctl_elem_value *ucontrol) | 469 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/i2c/other/pt2258.c b/sound/i2c/other/pt2258.c index e91cc3b44de5..00c83d8b32b1 100644 --- a/sound/i2c/other/pt2258.c +++ b/sound/i2c/other/pt2258.c | |||
@@ -140,15 +140,7 @@ static int pt2258_stereo_volume_put(struct snd_kcontrol *kcontrol, | |||
140 | return -EIO; | 140 | return -EIO; |
141 | } | 141 | } |
142 | 142 | ||
143 | static int pt2258_switch_info(struct snd_kcontrol *kcontrol, | 143 | #define pt2258_switch_info snd_ctl_boolean_mono_info |
144 | struct snd_ctl_elem_info *uinfo) | ||
145 | { | ||
146 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
147 | uinfo->count = 1; | ||
148 | uinfo->value.integer.min = 0; | ||
149 | uinfo->value.integer.max = 1; | ||
150 | return 0; | ||
151 | } | ||
152 | 144 | ||
153 | static int pt2258_switch_get(struct snd_kcontrol *kcontrol, | 145 | static int pt2258_switch_get(struct snd_kcontrol *kcontrol, |
154 | struct snd_ctl_elem_value *ucontrol) | 146 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c index 4c2fd14c1056..fe31bb5cffb8 100644 --- a/sound/i2c/other/tea575x-tuner.c +++ b/sound/i2c/other/tea575x-tuner.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * ALSA driver for TEA5757/5759 Philips AM/FM radio tuner chips | 2 | * ALSA driver for TEA5757/5759 Philips AM/FM radio tuner chips |
3 | * | 3 | * |
4 | * Copyright (c) 2004 Jaroslav Kysela <perex@suse.cz> | 4 | * Copyright (c) 2004 Jaroslav Kysela <perex@perex.cz> |
5 | * | 5 | * |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
@@ -28,7 +28,7 @@ | |||
28 | #include <sound/core.h> | 28 | #include <sound/core.h> |
29 | #include <sound/tea575x-tuner.h> | 29 | #include <sound/tea575x-tuner.h> |
30 | 30 | ||
31 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 31 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
32 | MODULE_DESCRIPTION("Routines for control of TEA5757/5759 Philips AM/FM radio tuner chips"); | 32 | MODULE_DESCRIPTION("Routines for control of TEA5757/5759 Philips AM/FM radio tuner chips"); |
33 | MODULE_LICENSE("GPL"); | 33 | MODULE_LICENSE("GPL"); |
34 | 34 | ||
diff --git a/sound/i2c/tea6330t.c b/sound/i2c/tea6330t.c index ae5b1e3a68ce..9bab744af0ef 100644 --- a/sound/i2c/tea6330t.c +++ b/sound/i2c/tea6330t.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Routines for control of the TEA6330T circuit via i2c bus | 2 | * Routines for control of the TEA6330T circuit via i2c bus |
3 | * Sound fader control circuit for car radios by Philips Semiconductors | 3 | * Sound fader control circuit for car radios by Philips Semiconductors |
4 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 4 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
5 | * | 5 | * |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
@@ -27,7 +27,7 @@ | |||
27 | #include <sound/control.h> | 27 | #include <sound/control.h> |
28 | #include <sound/tea6330t.h> | 28 | #include <sound/tea6330t.h> |
29 | 29 | ||
30 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 30 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
31 | MODULE_DESCRIPTION("Routines for control of the TEA6330T circuit via i2c bus"); | 31 | MODULE_DESCRIPTION("Routines for control of the TEA6330T circuit via i2c bus"); |
32 | MODULE_LICENSE("GPL"); | 32 | MODULE_LICENSE("GPL"); |
33 | 33 | ||
@@ -142,15 +142,7 @@ static int snd_tea6330t_put_master_volume(struct snd_kcontrol *kcontrol, | |||
142 | .info = snd_tea6330t_info_master_switch, \ | 142 | .info = snd_tea6330t_info_master_switch, \ |
143 | .get = snd_tea6330t_get_master_switch, .put = snd_tea6330t_put_master_switch } | 143 | .get = snd_tea6330t_get_master_switch, .put = snd_tea6330t_put_master_switch } |
144 | 144 | ||
145 | static int snd_tea6330t_info_master_switch(struct snd_kcontrol *kcontrol, | 145 | #define snd_tea6330t_info_master_switch snd_ctl_boolean_stereo_info |
146 | struct snd_ctl_elem_info *uinfo) | ||
147 | { | ||
148 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
149 | uinfo->count = 2; | ||
150 | uinfo->value.integer.min = 0; | ||
151 | uinfo->value.integer.max = 1; | ||
152 | return 0; | ||
153 | } | ||
154 | 146 | ||
155 | static int snd_tea6330t_get_master_switch(struct snd_kcontrol *kcontrol, | 147 | static int snd_tea6330t_get_master_switch(struct snd_kcontrol *kcontrol, |
156 | struct snd_ctl_elem_value *ucontrol) | 148 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig index ea5084abe60f..2639a6ab8f2e 100644 --- a/sound/isa/Kconfig +++ b/sound/isa/Kconfig | |||
@@ -191,6 +191,19 @@ config SND_ES18XX | |||
191 | To compile this driver as a module, choose M here: the module | 191 | To compile this driver as a module, choose M here: the module |
192 | will be called snd-es18xx. | 192 | will be called snd-es18xx. |
193 | 193 | ||
194 | config SND_SC6000 | ||
195 | tristate "Gallant SC-6000, Audio Excel DSP 16" | ||
196 | depends on SND && HAS_IOPORT | ||
197 | select SND_AD1848_LIB | ||
198 | select SND_OPL3_LIB | ||
199 | select SND_MPU401_UART | ||
200 | help | ||
201 | Say Y here to include support for Gallant SC-6000 card and clones: | ||
202 | Audio Excel DSP 16 and Zoltrix AV302. | ||
203 | |||
204 | To compile this driver as a module, choose M here: the module | ||
205 | will be called snd-sc6000. | ||
206 | |||
194 | config SND_GUS_SYNTH | 207 | config SND_GUS_SYNTH |
195 | tristate | 208 | tristate |
196 | 209 | ||
@@ -414,7 +427,7 @@ config SND_SSCAPE | |||
414 | config SND_WAVEFRONT | 427 | config SND_WAVEFRONT |
415 | tristate "Turtle Beach Maui,Tropez,Tropez+ (Wavefront)" | 428 | tristate "Turtle Beach Maui,Tropez,Tropez+ (Wavefront)" |
416 | depends on SND | 429 | depends on SND |
417 | select FW_LOADER if !SND_WAVEFRONT_FIRMWARE_IN_KERNEL | 430 | select FW_LOADER |
418 | select SND_OPL3_LIB | 431 | select SND_OPL3_LIB |
419 | select SND_MPU401_UART | 432 | select SND_MPU401_UART |
420 | select SND_CS4231_LIB | 433 | select SND_CS4231_LIB |
@@ -430,8 +443,9 @@ config SND_WAVEFRONT_FIRMWARE_IN_KERNEL | |||
430 | depends on SND_WAVEFRONT | 443 | depends on SND_WAVEFRONT |
431 | default y | 444 | default y |
432 | help | 445 | help |
433 | Say Y here to include the static firmware built in the kernel | 446 | Say Y here to include the static firmware for FX DSP built in |
434 | for the Wavefront driver. If you choose N here, you need to | 447 | the kernel for the Wavefront driver. If you choose N here, |
435 | install the firmware files from the alsa-firmware package. | 448 | you need to install the firmware files from the |
449 | alsa-firmware package. | ||
436 | 450 | ||
437 | endmenu | 451 | endmenu |
diff --git a/sound/isa/Makefile b/sound/isa/Makefile index bb317ccc170f..c0ce7db2a1b5 100644 --- a/sound/isa/Makefile +++ b/sound/isa/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-adlib-objs := adlib.o | 6 | snd-adlib-objs := adlib.o |
@@ -10,6 +10,7 @@ snd-cmi8330-objs := cmi8330.o | |||
10 | snd-dt019x-objs := dt019x.o | 10 | snd-dt019x-objs := dt019x.o |
11 | snd-es18xx-objs := es18xx.o | 11 | snd-es18xx-objs := es18xx.o |
12 | snd-opl3sa2-objs := opl3sa2.o | 12 | snd-opl3sa2-objs := opl3sa2.o |
13 | snd-sc6000-objs := sc6000.o | ||
13 | snd-sgalaxy-objs := sgalaxy.o | 14 | snd-sgalaxy-objs := sgalaxy.o |
14 | snd-sscape-objs := sscape.o | 15 | snd-sscape-objs := sscape.o |
15 | 16 | ||
@@ -21,6 +22,7 @@ obj-$(CONFIG_SND_CMI8330) += snd-cmi8330.o | |||
21 | obj-$(CONFIG_SND_DT019X) += snd-dt019x.o | 22 | obj-$(CONFIG_SND_DT019X) += snd-dt019x.o |
22 | obj-$(CONFIG_SND_ES18XX) += snd-es18xx.o | 23 | obj-$(CONFIG_SND_ES18XX) += snd-es18xx.o |
23 | obj-$(CONFIG_SND_OPL3SA2) += snd-opl3sa2.o | 24 | obj-$(CONFIG_SND_OPL3SA2) += snd-opl3sa2.o |
25 | obj-$(CONFIG_SND_SC6000) += snd-sc6000.o | ||
24 | obj-$(CONFIG_SND_SGALAXY) += snd-sgalaxy.o | 26 | obj-$(CONFIG_SND_SGALAXY) += snd-sgalaxy.o |
25 | obj-$(CONFIG_SND_SSCAPE) += snd-sscape.o | 27 | obj-$(CONFIG_SND_SSCAPE) += snd-sscape.o |
26 | 28 | ||
diff --git a/sound/isa/ad1816a/Makefile b/sound/isa/ad1816a/Makefile index 90e00e842e49..487ab23860e3 100644 --- a/sound/isa/ad1816a/Makefile +++ b/sound/isa/ad1816a/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-ad1816a-objs := ad1816a.o ad1816a_lib.o | 6 | snd-ad1816a-objs := ad1816a.o ad1816a_lib.o |
diff --git a/sound/isa/ad1816a/ad1816a_lib.c b/sound/isa/ad1816a/ad1816a_lib.c index ec9209cd5177..cf18fe4617a1 100644 --- a/sound/isa/ad1816a/ad1816a_lib.c +++ b/sound/isa/ad1816a/ad1816a_lib.c | |||
@@ -453,7 +453,6 @@ static int snd_ad1816a_playback_open(struct snd_pcm_substream *substream) | |||
453 | 453 | ||
454 | if ((error = snd_ad1816a_open(chip, AD1816A_MODE_PLAYBACK)) < 0) | 454 | if ((error = snd_ad1816a_open(chip, AD1816A_MODE_PLAYBACK)) < 0) |
455 | return error; | 455 | return error; |
456 | snd_pcm_set_sync(substream); | ||
457 | runtime->hw = snd_ad1816a_playback; | 456 | runtime->hw = snd_ad1816a_playback; |
458 | snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.buffer_bytes_max); | 457 | snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.buffer_bytes_max); |
459 | snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.period_bytes_max); | 458 | snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.period_bytes_max); |
@@ -469,7 +468,6 @@ static int snd_ad1816a_capture_open(struct snd_pcm_substream *substream) | |||
469 | 468 | ||
470 | if ((error = snd_ad1816a_open(chip, AD1816A_MODE_CAPTURE)) < 0) | 469 | if ((error = snd_ad1816a_open(chip, AD1816A_MODE_CAPTURE)) < 0) |
471 | return error; | 470 | return error; |
472 | snd_pcm_set_sync(substream); | ||
473 | runtime->hw = snd_ad1816a_capture; | 471 | runtime->hw = snd_ad1816a_capture; |
474 | snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.buffer_bytes_max); | 472 | snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.buffer_bytes_max); |
475 | snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.period_bytes_max); | 473 | snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.period_bytes_max); |
diff --git a/sound/isa/ad1848/Makefile b/sound/isa/ad1848/Makefile index 45d59998aa69..ae23331e9200 100644 --- a/sound/isa/ad1848/Makefile +++ b/sound/isa/ad1848/Makefile | |||
@@ -1,15 +1,12 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-ad1848-lib-objs := ad1848_lib.o | 6 | snd-ad1848-lib-objs := ad1848_lib.o |
7 | snd-ad1848-objs := ad1848.o | 7 | snd-ad1848-objs := ad1848.o |
8 | 8 | ||
9 | # Toplevel Module Dependency | 9 | # Toplevel Module Dependency |
10 | obj-$(CONFIG_SND_CMI8330) += snd-ad1848-lib.o | 10 | obj-$(CONFIG_SND_AD1848) += snd-ad1848.o |
11 | obj-$(CONFIG_SND_SGALAXY) += snd-ad1848-lib.o | 11 | obj-$(CONFIG_SND_AD1848_LIB) += snd-ad1848-lib.o |
12 | obj-$(CONFIG_SND_AD1848) += snd-ad1848.o snd-ad1848-lib.o | ||
13 | obj-$(CONFIG_SND_OPTI92X_AD1848) += snd-ad1848-lib.o | ||
14 | 12 | ||
15 | obj-m := $(sort $(obj-m)) | ||
diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c index d09a7fa86545..a4710b5e214c 100644 --- a/sound/isa/ad1848/ad1848.c +++ b/sound/isa/ad1848/ad1848.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * Generic driver for AD1848/AD1847/CS4248 chips (0.1 Alpha) | 2 | * Generic driver for AD1848/AD1847/CS4248 chips (0.1 Alpha) |
3 | * Copyright (c) by Tugrul Galatali <galatalt@stuy.edu>, | 3 | * Copyright (c) by Tugrul Galatali <galatalt@stuy.edu>, |
4 | * Jaroslav Kysela <perex@suse.cz> | 4 | * Jaroslav Kysela <perex@perex.cz> |
5 | * Based on card-4232.c by Jaroslav Kysela <perex@suse.cz> | 5 | * Based on card-4232.c by Jaroslav Kysela <perex@perex.cz> |
6 | * | 6 | * |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
@@ -36,7 +36,7 @@ | |||
36 | #define DEV_NAME "ad1848" | 36 | #define DEV_NAME "ad1848" |
37 | 37 | ||
38 | MODULE_DESCRIPTION(CRD_NAME); | 38 | MODULE_DESCRIPTION(CRD_NAME); |
39 | MODULE_AUTHOR("Tugrul Galatali <galatalt@stuy.edu>, Jaroslav Kysela <perex@suse.cz>"); | 39 | MODULE_AUTHOR("Tugrul Galatali <galatalt@stuy.edu>, Jaroslav Kysela <perex@perex.cz>"); |
40 | MODULE_LICENSE("GPL"); | 40 | MODULE_LICENSE("GPL"); |
41 | MODULE_SUPPORTED_DEVICE("{{Analog Devices,AD1848}," | 41 | MODULE_SUPPORTED_DEVICE("{{Analog Devices,AD1848}," |
42 | "{Analog Devices,AD1847}," | 42 | "{Analog Devices,AD1847}," |
diff --git a/sound/isa/ad1848/ad1848_lib.c b/sound/isa/ad1848/ad1848_lib.c index 1bc2e3fd5721..a901cd1ee692 100644 --- a/sound/isa/ad1848/ad1848_lib.c +++ b/sound/isa/ad1848/ad1848_lib.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Routines for control of AD1848/AD1847/CS4248 | 3 | * Routines for control of AD1848/AD1847/CS4248 |
4 | * | 4 | * |
5 | * | 5 | * |
@@ -35,7 +35,7 @@ | |||
35 | #include <asm/io.h> | 35 | #include <asm/io.h> |
36 | #include <asm/dma.h> | 36 | #include <asm/dma.h> |
37 | 37 | ||
38 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 38 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
39 | MODULE_DESCRIPTION("Routines for control of AD1848/AD1847/CS4248"); | 39 | MODULE_DESCRIPTION("Routines for control of AD1848/AD1847/CS4248"); |
40 | MODULE_LICENSE("GPL"); | 40 | MODULE_LICENSE("GPL"); |
41 | 41 | ||
@@ -70,7 +70,7 @@ static unsigned int rates[14] = { | |||
70 | }; | 70 | }; |
71 | 71 | ||
72 | static struct snd_pcm_hw_constraint_list hw_constraints_rates = { | 72 | static struct snd_pcm_hw_constraint_list hw_constraints_rates = { |
73 | .count = 14, | 73 | .count = ARRAY_SIZE(rates), |
74 | .list = rates, | 74 | .list = rates, |
75 | .mask = 0, | 75 | .mask = 0, |
76 | }; | 76 | }; |
@@ -99,24 +99,32 @@ static unsigned char snd_ad1848_original_image[16] = | |||
99 | * Basic I/O functions | 99 | * Basic I/O functions |
100 | */ | 100 | */ |
101 | 101 | ||
102 | void snd_ad1848_out(struct snd_ad1848 *chip, | 102 | static void snd_ad1848_wait(struct snd_ad1848 *chip) |
103 | unsigned char reg, | ||
104 | unsigned char value) | ||
105 | { | 103 | { |
106 | int timeout; | 104 | int timeout; |
107 | 105 | ||
108 | for (timeout = 250; timeout > 0 && (inb(AD1848P(chip, REGSEL)) & AD1848_INIT); timeout--) | 106 | for (timeout = 250; timeout > 0; timeout--) { |
107 | if ((inb(AD1848P(chip, REGSEL)) & AD1848_INIT) == 0) | ||
108 | break; | ||
109 | udelay(100); | 109 | udelay(100); |
110 | } | ||
111 | } | ||
112 | |||
113 | void snd_ad1848_out(struct snd_ad1848 *chip, | ||
114 | unsigned char reg, | ||
115 | unsigned char value) | ||
116 | { | ||
117 | snd_ad1848_wait(chip); | ||
110 | #ifdef CONFIG_SND_DEBUG | 118 | #ifdef CONFIG_SND_DEBUG |
111 | if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT) | 119 | if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT) |
112 | snd_printk(KERN_WARNING "auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); | 120 | snd_printk(KERN_WARNING "auto calibration time out - " |
121 | "reg = 0x%x, value = 0x%x\n", reg, value); | ||
113 | #endif | 122 | #endif |
114 | outb(chip->mce_bit | reg, AD1848P(chip, REGSEL)); | 123 | outb(chip->mce_bit | reg, AD1848P(chip, REGSEL)); |
115 | outb(chip->image[reg] = value, AD1848P(chip, REG)); | 124 | outb(chip->image[reg] = value, AD1848P(chip, REG)); |
116 | mb(); | 125 | mb(); |
117 | #if 0 | 126 | snd_printdd("codec out - reg 0x%x = 0x%x\n", |
118 | printk("codec out - reg 0x%x = 0x%x\n", chip->mce_bit | reg, value); | 127 | chip->mce_bit | reg, value); |
119 | #endif | ||
120 | } | 128 | } |
121 | 129 | ||
122 | EXPORT_SYMBOL(snd_ad1848_out); | 130 | EXPORT_SYMBOL(snd_ad1848_out); |
@@ -124,10 +132,7 @@ EXPORT_SYMBOL(snd_ad1848_out); | |||
124 | static void snd_ad1848_dout(struct snd_ad1848 *chip, | 132 | static void snd_ad1848_dout(struct snd_ad1848 *chip, |
125 | unsigned char reg, unsigned char value) | 133 | unsigned char reg, unsigned char value) |
126 | { | 134 | { |
127 | int timeout; | 135 | snd_ad1848_wait(chip); |
128 | |||
129 | for (timeout = 250; timeout > 0 && (inb(AD1848P(chip, REGSEL)) & AD1848_INIT); timeout--) | ||
130 | udelay(100); | ||
131 | outb(chip->mce_bit | reg, AD1848P(chip, REGSEL)); | 136 | outb(chip->mce_bit | reg, AD1848P(chip, REGSEL)); |
132 | outb(value, AD1848P(chip, REG)); | 137 | outb(value, AD1848P(chip, REG)); |
133 | mb(); | 138 | mb(); |
@@ -135,13 +140,11 @@ static void snd_ad1848_dout(struct snd_ad1848 *chip, | |||
135 | 140 | ||
136 | static unsigned char snd_ad1848_in(struct snd_ad1848 *chip, unsigned char reg) | 141 | static unsigned char snd_ad1848_in(struct snd_ad1848 *chip, unsigned char reg) |
137 | { | 142 | { |
138 | int timeout; | 143 | snd_ad1848_wait(chip); |
139 | |||
140 | for (timeout = 250; timeout > 0 && (inb(AD1848P(chip, REGSEL)) & AD1848_INIT); timeout--) | ||
141 | udelay(100); | ||
142 | #ifdef CONFIG_SND_DEBUG | 144 | #ifdef CONFIG_SND_DEBUG |
143 | if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT) | 145 | if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT) |
144 | snd_printk(KERN_WARNING "auto calibration time out - reg = 0x%x\n", reg); | 146 | snd_printk(KERN_WARNING "auto calibration time out - " |
147 | "reg = 0x%x\n", reg); | ||
145 | #endif | 148 | #endif |
146 | outb(chip->mce_bit | reg, AD1848P(chip, REGSEL)); | 149 | outb(chip->mce_bit | reg, AD1848P(chip, REGSEL)); |
147 | mb(); | 150 | mb(); |
@@ -183,8 +186,7 @@ static void snd_ad1848_mce_up(struct snd_ad1848 *chip) | |||
183 | unsigned long flags; | 186 | unsigned long flags; |
184 | int timeout; | 187 | int timeout; |
185 | 188 | ||
186 | for (timeout = 250; timeout > 0 && (inb(AD1848P(chip, REGSEL)) & AD1848_INIT); timeout--) | 189 | snd_ad1848_wait(chip); |
187 | udelay(100); | ||
188 | #ifdef CONFIG_SND_DEBUG | 190 | #ifdef CONFIG_SND_DEBUG |
189 | if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT) | 191 | if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT) |
190 | snd_printk(KERN_WARNING "mce_up - auto calibration time out (0)\n"); | 192 | snd_printk(KERN_WARNING "mce_up - auto calibration time out (0)\n"); |
@@ -201,9 +203,8 @@ static void snd_ad1848_mce_up(struct snd_ad1848 *chip) | |||
201 | 203 | ||
202 | static void snd_ad1848_mce_down(struct snd_ad1848 *chip) | 204 | static void snd_ad1848_mce_down(struct snd_ad1848 *chip) |
203 | { | 205 | { |
204 | unsigned long flags; | 206 | unsigned long flags, timeout; |
205 | int timeout; | 207 | int reg; |
206 | signed long time; | ||
207 | 208 | ||
208 | spin_lock_irqsave(&chip->reg_lock, flags); | 209 | spin_lock_irqsave(&chip->reg_lock, flags); |
209 | for (timeout = 5; timeout > 0; timeout--) | 210 | for (timeout = 5; timeout > 0; timeout--) |
@@ -211,61 +212,48 @@ static void snd_ad1848_mce_down(struct snd_ad1848 *chip) | |||
211 | /* end of cleanup sequence */ | 212 | /* end of cleanup sequence */ |
212 | for (timeout = 12000; timeout > 0 && (inb(AD1848P(chip, REGSEL)) & AD1848_INIT); timeout--) | 213 | for (timeout = 12000; timeout > 0 && (inb(AD1848P(chip, REGSEL)) & AD1848_INIT); timeout--) |
213 | udelay(100); | 214 | udelay(100); |
214 | #if 0 | 215 | |
215 | printk("(1) timeout = %i\n", timeout); | 216 | snd_printdd("(1) timeout = %d\n", timeout); |
216 | #endif | 217 | |
217 | #ifdef CONFIG_SND_DEBUG | 218 | #ifdef CONFIG_SND_DEBUG |
218 | if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT) | 219 | if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT) |
219 | snd_printk(KERN_WARNING "mce_down [0x%lx] - auto calibration time out (0)\n", AD1848P(chip, REGSEL)); | 220 | snd_printk(KERN_WARNING "mce_down [0x%lx] - auto calibration time out (0)\n", AD1848P(chip, REGSEL)); |
220 | #endif | 221 | #endif |
222 | |||
221 | chip->mce_bit &= ~AD1848_MCE; | 223 | chip->mce_bit &= ~AD1848_MCE; |
222 | timeout = inb(AD1848P(chip, REGSEL)); | 224 | reg = inb(AD1848P(chip, REGSEL)); |
223 | outb(chip->mce_bit | (timeout & 0x1f), AD1848P(chip, REGSEL)); | 225 | outb(chip->mce_bit | (reg & 0x1f), AD1848P(chip, REGSEL)); |
224 | if (timeout == 0x80) | 226 | if (reg == 0x80) |
225 | snd_printk(KERN_WARNING "mce_down [0x%lx]: serious init problem - codec still busy\n", chip->port); | 227 | snd_printk(KERN_WARNING "mce_down [0x%lx]: serious init problem - codec still busy\n", chip->port); |
226 | if ((timeout & AD1848_MCE) == 0) { | 228 | if ((reg & AD1848_MCE) == 0) { |
227 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 229 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
228 | return; | 230 | return; |
229 | } | 231 | } |
230 | /* calibration process */ | ||
231 | 232 | ||
232 | for (timeout = 500; timeout > 0 && (snd_ad1848_in(chip, AD1848_TEST_INIT) & AD1848_CALIB_IN_PROGRESS) == 0; timeout--); | 233 | /* |
233 | if ((snd_ad1848_in(chip, AD1848_TEST_INIT) & AD1848_CALIB_IN_PROGRESS) == 0) { | 234 | * Wait for auto-calibration (AC) process to finish, i.e. ACI to go low. |
234 | snd_printd("mce_down - auto calibration time out (1)\n"); | 235 | * It may take up to 5 sample periods (at most 907 us @ 5.5125 kHz) for |
235 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 236 | * the process to _start_, so it is important to wait at least that long |
236 | return; | 237 | * before checking. Otherwise we might think AC has finished when it |
237 | } | 238 | * has in fact not begun. It could take 128 (no AC) or 384 (AC) cycles |
238 | #if 0 | 239 | * for ACI to drop. This gives a wait of at most 70 ms with a more |
239 | printk("(2) timeout = %i, jiffies = %li\n", timeout, jiffies); | 240 | * typical value of 3-9 ms. |
240 | #endif | 241 | */ |
241 | time = HZ / 4; | 242 | timeout = jiffies + msecs_to_jiffies(250); |
242 | while (snd_ad1848_in(chip, AD1848_TEST_INIT) & AD1848_CALIB_IN_PROGRESS) { | 243 | do { |
243 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 244 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
244 | if (time <= 0) { | 245 | msleep(1); |
245 | snd_printk(KERN_ERR "mce_down - auto calibration time out (2)\n"); | ||
246 | return; | ||
247 | } | ||
248 | time = schedule_timeout(time); | ||
249 | spin_lock_irqsave(&chip->reg_lock, flags); | 246 | spin_lock_irqsave(&chip->reg_lock, flags); |
250 | } | 247 | reg = snd_ad1848_in(chip, AD1848_TEST_INIT) & |
251 | #if 0 | 248 | AD1848_CALIB_IN_PROGRESS; |
252 | printk("(3) jiffies = %li\n", jiffies); | 249 | } while (reg && time_before(jiffies, timeout)); |
253 | #endif | ||
254 | time = HZ / 10; | ||
255 | while (inb(AD1848P(chip, REGSEL)) & AD1848_INIT) { | ||
256 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
257 | if (time <= 0) { | ||
258 | snd_printk(KERN_ERR "mce_down - auto calibration time out (3)\n"); | ||
259 | return; | ||
260 | } | ||
261 | time = schedule_timeout(time); | ||
262 | spin_lock_irqsave(&chip->reg_lock, flags); | ||
263 | } | ||
264 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 250 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
265 | #if 0 | 251 | if (reg) |
266 | printk("(4) jiffies = %li\n", jiffies); | 252 | snd_printk(KERN_ERR |
267 | snd_printk("mce_down - exit = 0x%x\n", inb(AD1848P(chip, REGSEL))); | 253 | "mce_down - auto calibration time out (2)\n"); |
268 | #endif | 254 | |
255 | snd_printdd("(4) jiffies = %lu\n", jiffies); | ||
256 | snd_printd("mce_down - exit = 0x%x\n", inb(AD1848P(chip, REGSEL))); | ||
269 | } | 257 | } |
270 | 258 | ||
271 | static unsigned int snd_ad1848_get_count(unsigned char format, | 259 | static unsigned int snd_ad1848_get_count(unsigned char format, |
@@ -319,11 +307,11 @@ static unsigned char snd_ad1848_get_rate(unsigned int rate) | |||
319 | { | 307 | { |
320 | int i; | 308 | int i; |
321 | 309 | ||
322 | for (i = 0; i < 14; i++) | 310 | for (i = 0; i < ARRAY_SIZE(rates); i++) |
323 | if (rate == rates[i]) | 311 | if (rate == rates[i]) |
324 | return freq_bits[i]; | 312 | return freq_bits[i]; |
325 | snd_BUG(); | 313 | snd_BUG(); |
326 | return freq_bits[13]; | 314 | return freq_bits[ARRAY_SIZE(rates) - 1]; |
327 | } | 315 | } |
328 | 316 | ||
329 | static int snd_ad1848_ioctl(struct snd_pcm_substream *substream, | 317 | static int snd_ad1848_ioctl(struct snd_pcm_substream *substream, |
@@ -390,11 +378,9 @@ static int snd_ad1848_open(struct snd_ad1848 *chip, unsigned int mode) | |||
390 | { | 378 | { |
391 | unsigned long flags; | 379 | unsigned long flags; |
392 | 380 | ||
393 | mutex_lock(&chip->open_mutex); | 381 | if (chip->mode & AD1848_MODE_OPEN) |
394 | if (chip->mode & AD1848_MODE_OPEN) { | ||
395 | mutex_unlock(&chip->open_mutex); | ||
396 | return -EAGAIN; | 382 | return -EAGAIN; |
397 | } | 383 | |
398 | snd_ad1848_mce_down(chip); | 384 | snd_ad1848_mce_down(chip); |
399 | 385 | ||
400 | #ifdef SNDRV_DEBUG_MCE | 386 | #ifdef SNDRV_DEBUG_MCE |
@@ -435,7 +421,6 @@ static int snd_ad1848_open(struct snd_ad1848 *chip, unsigned int mode) | |||
435 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 421 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
436 | 422 | ||
437 | chip->mode = mode; | 423 | chip->mode = mode; |
438 | mutex_unlock(&chip->open_mutex); | ||
439 | 424 | ||
440 | return 0; | 425 | return 0; |
441 | } | 426 | } |
@@ -444,11 +429,8 @@ static void snd_ad1848_close(struct snd_ad1848 *chip) | |||
444 | { | 429 | { |
445 | unsigned long flags; | 430 | unsigned long flags; |
446 | 431 | ||
447 | mutex_lock(&chip->open_mutex); | 432 | if (!chip->mode) |
448 | if (!chip->mode) { | ||
449 | mutex_unlock(&chip->open_mutex); | ||
450 | return; | 433 | return; |
451 | } | ||
452 | /* disable IRQ */ | 434 | /* disable IRQ */ |
453 | spin_lock_irqsave(&chip->reg_lock, flags); | 435 | spin_lock_irqsave(&chip->reg_lock, flags); |
454 | outb(0, AD1848P(chip, STATUS)); /* clear IRQ */ | 436 | outb(0, AD1848P(chip, STATUS)); /* clear IRQ */ |
@@ -474,7 +456,6 @@ static void snd_ad1848_close(struct snd_ad1848 *chip) | |||
474 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 456 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
475 | 457 | ||
476 | chip->mode = 0; | 458 | chip->mode = 0; |
477 | mutex_unlock(&chip->open_mutex); | ||
478 | } | 459 | } |
479 | 460 | ||
480 | /* | 461 | /* |
@@ -892,7 +873,6 @@ int snd_ad1848_create(struct snd_card *card, | |||
892 | if (chip == NULL) | 873 | if (chip == NULL) |
893 | return -ENOMEM; | 874 | return -ENOMEM; |
894 | spin_lock_init(&chip->reg_lock); | 875 | spin_lock_init(&chip->reg_lock); |
895 | mutex_init(&chip->open_mutex); | ||
896 | chip->card = card; | 876 | chip->card = card; |
897 | chip->port = port; | 877 | chip->port = port; |
898 | chip->irq = -1; | 878 | chip->irq = -1; |
diff --git a/sound/isa/cs423x/Makefile b/sound/isa/cs423x/Makefile index 2fb4f7409d7c..5067ee001933 100644 --- a/sound/isa/cs423x/Makefile +++ b/sound/isa/cs423x/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-cs4231-lib-objs := cs4231_lib.o | 6 | snd-cs4231-lib-objs := cs4231_lib.o |
@@ -10,17 +10,8 @@ snd-cs4232-objs := cs4232.o | |||
10 | snd-cs4236-objs := cs4236.o | 10 | snd-cs4236-objs := cs4236.o |
11 | 11 | ||
12 | # Toplevel Module Dependency | 12 | # Toplevel Module Dependency |
13 | obj-$(CONFIG_SND_AZT2320) += snd-cs4231-lib.o | 13 | obj-$(CONFIG_SND_CS4231_LIB) += snd-cs4231-lib.o |
14 | obj-$(CONFIG_SND_MIRO) += snd-cs4231-lib.o | 14 | obj-$(CONFIG_SND_CS4231) += snd-cs4231.o |
15 | obj-$(CONFIG_SND_OPL3SA2) += snd-cs4231-lib.o | 15 | obj-$(CONFIG_SND_CS4232) += snd-cs4232.o |
16 | obj-$(CONFIG_SND_CS4231) += snd-cs4231.o snd-cs4231-lib.o | 16 | obj-$(CONFIG_SND_CS4236) += snd-cs4236.o snd-cs4236-lib.o |
17 | obj-$(CONFIG_SND_CS4232) += snd-cs4232.o snd-cs4231-lib.o | ||
18 | obj-$(CONFIG_SND_CS4236) += snd-cs4236.o snd-cs4236-lib.o snd-cs4231-lib.o | ||
19 | obj-$(CONFIG_SND_GUSMAX) += snd-cs4231-lib.o | ||
20 | obj-$(CONFIG_SND_INTERWAVE) += snd-cs4231-lib.o | ||
21 | obj-$(CONFIG_SND_INTERWAVE_STB) += snd-cs4231-lib.o | ||
22 | obj-$(CONFIG_SND_OPTI92X_CS4231) += snd-cs4231-lib.o | ||
23 | obj-$(CONFIG_SND_WAVEFRONT) += snd-cs4231-lib.o | ||
24 | obj-$(CONFIG_SND_SSCAPE) += snd-cs4231-lib.o | ||
25 | 17 | ||
26 | obj-m := $(sort $(obj-m)) | ||
diff --git a/sound/isa/cs423x/cs4231.c b/sound/isa/cs423x/cs4231.c index ac4041134150..13db6842eaaa 100644 --- a/sound/isa/cs423x/cs4231.c +++ b/sound/isa/cs423x/cs4231.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Generic driver for CS4231 chips | 2 | * Generic driver for CS4231 chips |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * Originally the CS4232/CS4232A driver, modified for use on CS4231 by | 4 | * Originally the CS4232/CS4232A driver, modified for use on CS4231 by |
5 | * Tugrul Galatali <galatalt@stuy.edu> | 5 | * Tugrul Galatali <galatalt@stuy.edu> |
6 | * | 6 | * |
@@ -36,7 +36,7 @@ | |||
36 | #define DEV_NAME "cs4231" | 36 | #define DEV_NAME "cs4231" |
37 | 37 | ||
38 | MODULE_DESCRIPTION(CRD_NAME); | 38 | MODULE_DESCRIPTION(CRD_NAME); |
39 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 39 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
40 | MODULE_LICENSE("GPL"); | 40 | MODULE_LICENSE("GPL"); |
41 | MODULE_SUPPORTED_DEVICE("{{Crystal Semiconductors,CS4231}}"); | 41 | MODULE_SUPPORTED_DEVICE("{{Crystal Semiconductors,CS4231}}"); |
42 | 42 | ||
diff --git a/sound/isa/cs423x/cs4231_lib.c b/sound/isa/cs423x/cs4231_lib.c index 914d77b61b0c..a5eb9659b519 100644 --- a/sound/isa/cs423x/cs4231_lib.c +++ b/sound/isa/cs423x/cs4231_lib.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Routines for control of CS4231(A)/CS4232/InterWave & compatible chips | 3 | * Routines for control of CS4231(A)/CS4232/InterWave & compatible chips |
4 | * | 4 | * |
5 | * Bugs: | 5 | * Bugs: |
@@ -39,7 +39,7 @@ | |||
39 | #include <asm/dma.h> | 39 | #include <asm/dma.h> |
40 | #include <asm/irq.h> | 40 | #include <asm/irq.h> |
41 | 41 | ||
42 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 42 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
43 | MODULE_DESCRIPTION("Routines for control of CS4231(A)/CS4232/InterWave & compatible chips"); | 43 | MODULE_DESCRIPTION("Routines for control of CS4231(A)/CS4232/InterWave & compatible chips"); |
44 | MODULE_LICENSE("GPL"); | 44 | MODULE_LICENSE("GPL"); |
45 | 45 | ||
@@ -74,7 +74,7 @@ static unsigned int rates[14] = { | |||
74 | }; | 74 | }; |
75 | 75 | ||
76 | static struct snd_pcm_hw_constraint_list hw_constraints_rates = { | 76 | static struct snd_pcm_hw_constraint_list hw_constraints_rates = { |
77 | .count = 14, | 77 | .count = ARRAY_SIZE(rates), |
78 | .list = rates, | 78 | .list = rates, |
79 | .mask = 0, | 79 | .mask = 0, |
80 | }; | 80 | }; |
@@ -134,29 +134,31 @@ static inline u8 cs4231_inb(struct snd_cs4231 *chip, u8 offset) | |||
134 | return inb(chip->port + offset); | 134 | return inb(chip->port + offset); |
135 | } | 135 | } |
136 | 136 | ||
137 | static void snd_cs4231_outm(struct snd_cs4231 *chip, unsigned char reg, | 137 | static void snd_cs4231_wait(struct snd_cs4231 *chip) |
138 | unsigned char mask, unsigned char value) | ||
139 | { | 138 | { |
140 | int timeout; | 139 | int timeout; |
141 | unsigned char tmp; | ||
142 | 140 | ||
143 | for (timeout = 250; | 141 | for (timeout = 250; |
144 | timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT); | 142 | timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT); |
145 | timeout--) | 143 | timeout--) |
146 | udelay(100); | 144 | udelay(100); |
145 | } | ||
146 | |||
147 | static void snd_cs4231_outm(struct snd_cs4231 *chip, unsigned char reg, | ||
148 | unsigned char mask, unsigned char value) | ||
149 | { | ||
150 | unsigned char tmp = (chip->image[reg] & mask) | value; | ||
151 | |||
152 | snd_cs4231_wait(chip); | ||
147 | #ifdef CONFIG_SND_DEBUG | 153 | #ifdef CONFIG_SND_DEBUG |
148 | if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) | 154 | if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) |
149 | snd_printk("outm: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); | 155 | snd_printk("outm: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); |
150 | #endif | 156 | #endif |
151 | if (chip->calibrate_mute) { | 157 | chip->image[reg] = tmp; |
152 | chip->image[reg] &= mask; | 158 | if (!chip->calibrate_mute) { |
153 | chip->image[reg] |= value; | ||
154 | } else { | ||
155 | cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg); | 159 | cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg); |
156 | mb(); | 160 | wmb(); |
157 | tmp = (chip->image[reg] & mask) | value; | ||
158 | cs4231_outb(chip, CS4231P(REG), tmp); | 161 | cs4231_outb(chip, CS4231P(REG), tmp); |
159 | chip->image[reg] = tmp; | ||
160 | mb(); | 162 | mb(); |
161 | } | 163 | } |
162 | } | 164 | } |
@@ -176,12 +178,7 @@ static void snd_cs4231_dout(struct snd_cs4231 *chip, unsigned char reg, unsigned | |||
176 | 178 | ||
177 | void snd_cs4231_out(struct snd_cs4231 *chip, unsigned char reg, unsigned char value) | 179 | void snd_cs4231_out(struct snd_cs4231 *chip, unsigned char reg, unsigned char value) |
178 | { | 180 | { |
179 | int timeout; | 181 | snd_cs4231_wait(chip); |
180 | |||
181 | for (timeout = 250; | ||
182 | timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT); | ||
183 | timeout--) | ||
184 | udelay(100); | ||
185 | #ifdef CONFIG_SND_DEBUG | 182 | #ifdef CONFIG_SND_DEBUG |
186 | if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) | 183 | if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) |
187 | snd_printk("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); | 184 | snd_printk("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); |
@@ -190,19 +187,13 @@ void snd_cs4231_out(struct snd_cs4231 *chip, unsigned char reg, unsigned char va | |||
190 | cs4231_outb(chip, CS4231P(REG), value); | 187 | cs4231_outb(chip, CS4231P(REG), value); |
191 | chip->image[reg] = value; | 188 | chip->image[reg] = value; |
192 | mb(); | 189 | mb(); |
193 | #if 0 | 190 | snd_printdd("codec out - reg 0x%x = 0x%x\n", |
194 | printk("codec out - reg 0x%x = 0x%x\n", chip->mce_bit | reg, value); | 191 | chip->mce_bit | reg, value); |
195 | #endif | ||
196 | } | 192 | } |
197 | 193 | ||
198 | unsigned char snd_cs4231_in(struct snd_cs4231 *chip, unsigned char reg) | 194 | unsigned char snd_cs4231_in(struct snd_cs4231 *chip, unsigned char reg) |
199 | { | 195 | { |
200 | int timeout; | 196 | snd_cs4231_wait(chip); |
201 | |||
202 | for (timeout = 250; | ||
203 | timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT); | ||
204 | timeout--) | ||
205 | udelay(100); | ||
206 | #ifdef CONFIG_SND_DEBUG | 197 | #ifdef CONFIG_SND_DEBUG |
207 | if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) | 198 | if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) |
208 | snd_printk("in: auto calibration time out - reg = 0x%x\n", reg); | 199 | snd_printk("in: auto calibration time out - reg = 0x%x\n", reg); |
@@ -304,8 +295,7 @@ void snd_cs4231_mce_up(struct snd_cs4231 *chip) | |||
304 | unsigned long flags; | 295 | unsigned long flags; |
305 | int timeout; | 296 | int timeout; |
306 | 297 | ||
307 | for (timeout = 250; timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT); timeout--) | 298 | snd_cs4231_wait(chip); |
308 | udelay(100); | ||
309 | #ifdef CONFIG_SND_DEBUG | 299 | #ifdef CONFIG_SND_DEBUG |
310 | if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) | 300 | if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) |
311 | snd_printk("mce_up - auto calibration time out (0)\n"); | 301 | snd_printk("mce_up - auto calibration time out (0)\n"); |
@@ -323,12 +313,11 @@ void snd_cs4231_mce_up(struct snd_cs4231 *chip) | |||
323 | void snd_cs4231_mce_down(struct snd_cs4231 *chip) | 313 | void snd_cs4231_mce_down(struct snd_cs4231 *chip) |
324 | { | 314 | { |
325 | unsigned long flags; | 315 | unsigned long flags; |
316 | unsigned long end_time; | ||
326 | int timeout; | 317 | int timeout; |
327 | 318 | ||
328 | snd_cs4231_busy_wait(chip); | 319 | snd_cs4231_busy_wait(chip); |
329 | #if 0 | 320 | |
330 | printk("(1) timeout = %i\n", timeout); | ||
331 | #endif | ||
332 | #ifdef CONFIG_SND_DEBUG | 321 | #ifdef CONFIG_SND_DEBUG |
333 | if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) | 322 | if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) |
334 | snd_printk("mce_down [0x%lx] - auto calibration time out (0)\n", (long)CS4231P(REGSEL)); | 323 | snd_printk("mce_down [0x%lx] - auto calibration time out (0)\n", (long)CS4231P(REGSEL)); |
@@ -346,42 +335,42 @@ void snd_cs4231_mce_down(struct snd_cs4231 *chip) | |||
346 | } | 335 | } |
347 | snd_cs4231_busy_wait(chip); | 336 | snd_cs4231_busy_wait(chip); |
348 | 337 | ||
349 | /* calibration process */ | 338 | /* |
339 | * Wait for (possible -- during init auto-calibration may not be set) | ||
340 | * calibration process to start. Needs upto 5 sample periods on AD1848 | ||
341 | * which at the slowest possible rate of 5.5125 kHz means 907 us. | ||
342 | */ | ||
343 | msleep(1); | ||
350 | 344 | ||
351 | for (timeout = 500; timeout > 0 && (snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) == 0; timeout--) | 345 | snd_printdd("(1) jiffies = %lu\n", jiffies); |
352 | udelay(10); | 346 | |
353 | if ((snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) == 0) { | 347 | /* check condition up to 250 ms */ |
354 | snd_printd("cs4231_mce_down - auto calibration time out (1)\n"); | 348 | end_time = jiffies + msecs_to_jiffies(250); |
355 | return; | 349 | while (snd_cs4231_in(chip, CS4231_TEST_INIT) & |
356 | } | 350 | CS4231_CALIB_IN_PROGRESS) { |
357 | #if 0 | 351 | |
358 | printk("(2) timeout = %i, jiffies = %li\n", timeout, jiffies); | 352 | if (time_after(jiffies, end_time)) { |
359 | #endif | 353 | snd_printk(KERN_ERR "mce_down - " |
360 | /* in 10 ms increments, check condition, up to 250 ms */ | 354 | "auto calibration time out (2)\n"); |
361 | timeout = 25; | ||
362 | while (snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) { | ||
363 | if (--timeout < 0) { | ||
364 | snd_printk("mce_down - auto calibration time out (2)\n"); | ||
365 | return; | 355 | return; |
366 | } | 356 | } |
367 | msleep(10); | 357 | msleep(1); |
368 | } | 358 | } |
369 | #if 0 | 359 | |
370 | printk("(3) jiffies = %li\n", jiffies); | 360 | snd_printdd("(2) jiffies = %lu\n", jiffies); |
371 | #endif | 361 | |
372 | /* in 10 ms increments, check condition, up to 100 ms */ | 362 | /* check condition up to 100 ms */ |
373 | timeout = 10; | 363 | end_time = jiffies + msecs_to_jiffies(100); |
374 | while (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) { | 364 | while (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) { |
375 | if (--timeout < 0) { | 365 | if (time_after(jiffies, end_time)) { |
376 | snd_printk(KERN_ERR "mce_down - auto calibration time out (3)\n"); | 366 | snd_printk(KERN_ERR "mce_down - auto calibration time out (3)\n"); |
377 | return; | 367 | return; |
378 | } | 368 | } |
379 | msleep(10); | 369 | msleep(1); |
380 | } | 370 | } |
381 | #if 0 | 371 | |
382 | printk("(4) jiffies = %li\n", jiffies); | 372 | snd_printdd("(3) jiffies = %lu\n", jiffies); |
383 | snd_printk("mce_down - exit = 0x%x\n", cs4231_inb(chip, CS4231P(REGSEL))); | 373 | snd_printd("mce_down - exit = 0x%x\n", cs4231_inb(chip, CS4231P(REGSEL))); |
384 | #endif | ||
385 | } | 374 | } |
386 | 375 | ||
387 | static unsigned int snd_cs4231_get_count(unsigned char format, unsigned int size) | 376 | static unsigned int snd_cs4231_get_count(unsigned char format, unsigned int size) |
@@ -459,11 +448,11 @@ static unsigned char snd_cs4231_get_rate(unsigned int rate) | |||
459 | { | 448 | { |
460 | int i; | 449 | int i; |
461 | 450 | ||
462 | for (i = 0; i < 14; i++) | 451 | for (i = 0; i < ARRAY_SIZE(rates); i++) |
463 | if (rate == rates[i]) | 452 | if (rate == rates[i]) |
464 | return freq_bits[i]; | 453 | return freq_bits[i]; |
465 | // snd_BUG(); | 454 | // snd_BUG(); |
466 | return freq_bits[13]; | 455 | return freq_bits[ARRAY_SIZE(rates) - 1]; |
467 | } | 456 | } |
468 | 457 | ||
469 | static unsigned char snd_cs4231_get_format(struct snd_cs4231 *chip, | 458 | static unsigned char snd_cs4231_get_format(struct snd_cs4231 *chip, |
@@ -555,6 +544,8 @@ static void snd_cs4231_playback_format(struct snd_cs4231 *chip, | |||
555 | snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, chip->image[CS4231_PLAYBK_FORMAT] = pdfr); | 544 | snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, chip->image[CS4231_PLAYBK_FORMAT] = pdfr); |
556 | } | 545 | } |
557 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 546 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
547 | if (chip->hardware == CS4231_HW_OPL3SA2) | ||
548 | udelay(100); /* this seems to help */ | ||
558 | snd_cs4231_mce_down(chip); | 549 | snd_cs4231_mce_down(chip); |
559 | } | 550 | } |
560 | snd_cs4231_calibrate_mute(chip, 0); | 551 | snd_cs4231_calibrate_mute(chip, 0); |
diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c index 1a14f33b6ab0..5784b43f4123 100644 --- a/sound/isa/cs423x/cs4236.c +++ b/sound/isa/cs423x/cs4236.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for generic CS4232/CS4235/CS4236/CS4236B/CS4237B/CS4238B/CS4239 chips | 2 | * Driver for generic CS4232/CS4235/CS4236/CS4236B/CS4237B/CS4238B/CS4239 chips |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -32,7 +32,7 @@ | |||
32 | #include <sound/opl3.h> | 32 | #include <sound/opl3.h> |
33 | #include <sound/initval.h> | 33 | #include <sound/initval.h> |
34 | 34 | ||
35 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 35 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
36 | MODULE_LICENSE("GPL"); | 36 | MODULE_LICENSE("GPL"); |
37 | #ifdef CS4232 | 37 | #ifdef CS4232 |
38 | MODULE_DESCRIPTION("Cirrus Logic CS4232"); | 38 | MODULE_DESCRIPTION("Cirrus Logic CS4232"); |
diff --git a/sound/isa/cs423x/cs4236_lib.c b/sound/isa/cs423x/cs4236_lib.c index 7a5a6c71f5e4..6bd064470d4c 100644 --- a/sound/isa/cs423x/cs4236_lib.c +++ b/sound/isa/cs423x/cs4236_lib.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Routines for control of CS4235/4236B/4237B/4238B/4239 chips | 3 | * Routines for control of CS4235/4236B/4237B/4238B/4239 chips |
4 | * | 4 | * |
5 | * Note: | 5 | * Note: |
@@ -89,7 +89,7 @@ | |||
89 | #include <sound/cs4231.h> | 89 | #include <sound/cs4231.h> |
90 | #include <sound/asoundef.h> | 90 | #include <sound/asoundef.h> |
91 | 91 | ||
92 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 92 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
93 | MODULE_DESCRIPTION("Routines for control of CS4235/4236B/4237B/4238B/4239 chips"); | 93 | MODULE_DESCRIPTION("Routines for control of CS4235/4236B/4237B/4238B/4239 chips"); |
94 | MODULE_LICENSE("GPL"); | 94 | MODULE_LICENSE("GPL"); |
95 | 95 | ||
diff --git a/sound/isa/es1688/Makefile b/sound/isa/es1688/Makefile index 501c8bf903af..aee1e4ddb22a 100644 --- a/sound/isa/es1688/Makefile +++ b/sound/isa/es1688/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-es1688-lib-objs := es1688_lib.o | 6 | snd-es1688-lib-objs := es1688_lib.o |
diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c index edc398712e8b..74bbc92f2e7c 100644 --- a/sound/isa/es1688/es1688.c +++ b/sound/isa/es1688/es1688.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for generic ESS AudioDrive ESx688 soundcards | 2 | * Driver for generic ESS AudioDrive ESx688 soundcards |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -39,7 +39,7 @@ | |||
39 | #define DEV_NAME "es1688" | 39 | #define DEV_NAME "es1688" |
40 | 40 | ||
41 | MODULE_DESCRIPTION(CRD_NAME); | 41 | MODULE_DESCRIPTION(CRD_NAME); |
42 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 42 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
43 | MODULE_LICENSE("GPL"); | 43 | MODULE_LICENSE("GPL"); |
44 | MODULE_SUPPORTED_DEVICE("{{ESS,ES688 PnP AudioDrive,pnp:ESS0100}," | 44 | MODULE_SUPPORTED_DEVICE("{{ESS,ES688 PnP AudioDrive,pnp:ESS0100}," |
45 | "{ESS,ES1688 PnP AudioDrive,pnp:ESS0102}," | 45 | "{ESS,ES1688 PnP AudioDrive,pnp:ESS0102}," |
diff --git a/sound/isa/es1688/es1688_lib.c b/sound/isa/es1688/es1688_lib.c index a2ab99f2ac35..5c26d495daa8 100644 --- a/sound/isa/es1688/es1688_lib.c +++ b/sound/isa/es1688/es1688_lib.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Routines for control of ESS ES1688/688/488 chip | 3 | * Routines for control of ESS ES1688/688/488 chip |
4 | * | 4 | * |
5 | * | 5 | * |
@@ -32,7 +32,7 @@ | |||
32 | #include <asm/io.h> | 32 | #include <asm/io.h> |
33 | #include <asm/dma.h> | 33 | #include <asm/dma.h> |
34 | 34 | ||
35 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 35 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
36 | MODULE_DESCRIPTION("ESS ESx688 lowlevel module"); | 36 | MODULE_DESCRIPTION("ESS ESx688 lowlevel module"); |
37 | MODULE_LICENSE("GPL"); | 37 | MODULE_LICENSE("GPL"); |
38 | 38 | ||
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c index f7732bf90be3..4a7367a8ff9d 100644 --- a/sound/isa/es18xx.c +++ b/sound/isa/es18xx.c | |||
@@ -1071,14 +1071,7 @@ static int snd_es18xx_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem | |||
1071 | return (snd_es18xx_mixer_bits(chip, 0x1c, 0x07, val) != val) || retVal; | 1071 | return (snd_es18xx_mixer_bits(chip, 0x1c, 0x07, val) != val) || retVal; |
1072 | } | 1072 | } |
1073 | 1073 | ||
1074 | static int snd_es18xx_info_spatializer_enable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1074 | #define snd_es18xx_info_spatializer_enable snd_ctl_boolean_mono_info |
1075 | { | ||
1076 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1077 | uinfo->count = 1; | ||
1078 | uinfo->value.integer.min = 0; | ||
1079 | uinfo->value.integer.max = 1; | ||
1080 | return 0; | ||
1081 | } | ||
1082 | 1075 | ||
1083 | static int snd_es18xx_get_spatializer_enable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1076 | static int snd_es18xx_get_spatializer_enable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1084 | { | 1077 | { |
@@ -1120,14 +1113,7 @@ static int snd_es18xx_get_hw_volume(struct snd_kcontrol *kcontrol, struct snd_ct | |||
1120 | return 0; | 1113 | return 0; |
1121 | } | 1114 | } |
1122 | 1115 | ||
1123 | static int snd_es18xx_info_hw_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1116 | #define snd_es18xx_info_hw_switch snd_ctl_boolean_stereo_info |
1124 | { | ||
1125 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1126 | uinfo->count = 2; | ||
1127 | uinfo->value.integer.min = 0; | ||
1128 | uinfo->value.integer.max = 1; | ||
1129 | return 0; | ||
1130 | } | ||
1131 | 1117 | ||
1132 | static int snd_es18xx_get_hw_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1118 | static int snd_es18xx_get_hw_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1133 | { | 1119 | { |
@@ -2042,6 +2028,7 @@ static int pnpc_registered; | |||
2042 | 2028 | ||
2043 | static struct pnp_device_id snd_audiodrive_pnpbiosids[] = { | 2029 | static struct pnp_device_id snd_audiodrive_pnpbiosids[] = { |
2044 | { .id = "ESS1869" }, | 2030 | { .id = "ESS1869" }, |
2031 | { .id = "ESS1879" }, | ||
2045 | { .id = "" } /* end */ | 2032 | { .id = "" } /* end */ |
2046 | }; | 2033 | }; |
2047 | 2034 | ||
diff --git a/sound/isa/gus/Makefile b/sound/isa/gus/Makefile index bae5dbd6c8e5..df3d59f25f5e 100644 --- a/sound/isa/gus/Makefile +++ b/sound/isa/gus/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-gus-lib-objs := gus_main.o \ | 6 | snd-gus-lib-objs := gus_main.o \ |
diff --git a/sound/isa/gus/gus_dma.c b/sound/isa/gus/gus_dma.c index 44ee5d3674a1..fc905141e8a5 100644 --- a/sound/isa/gus/gus_dma.c +++ b/sound/isa/gus/gus_dma.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Routines for GF1 DMA control | 2 | * Routines for GF1 DMA control |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
diff --git a/sound/isa/gus/gus_dram.c b/sound/isa/gus/gus_dram.c index f22fe7967fcc..9eaa932f6efe 100644 --- a/sound/isa/gus/gus_dram.c +++ b/sound/isa/gus/gus_dram.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * DRAM access routines | 3 | * DRAM access routines |
4 | * | 4 | * |
5 | * | 5 | * |
diff --git a/sound/isa/gus/gus_instr.c b/sound/isa/gus/gus_instr.c index d0c38e1856ef..bf137ea72329 100644 --- a/sound/isa/gus/gus_instr.c +++ b/sound/isa/gus/gus_instr.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Routines for Gravis UltraSound soundcards - Synthesizer | 2 | * Routines for Gravis UltraSound soundcards - Synthesizer |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
diff --git a/sound/isa/gus/gus_io.c b/sound/isa/gus/gus_io.c index 9b1fe292de4d..3d4f899285ef 100644 --- a/sound/isa/gus/gus_io.c +++ b/sound/isa/gus/gus_io.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * I/O routines for GF1/InterWave synthesizer chips | 3 | * I/O routines for GF1/InterWave synthesizer chips |
4 | * | 4 | * |
5 | * | 5 | * |
diff --git a/sound/isa/gus/gus_irq.c b/sound/isa/gus/gus_irq.c index 537d3cfe41f3..cd9a6f1c99e6 100644 --- a/sound/isa/gus/gus_irq.c +++ b/sound/isa/gus/gus_irq.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Routine for IRQ handling from GF1/InterWave chip | 2 | * Routine for IRQ handling from GF1/InterWave chip |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -45,11 +45,13 @@ __again: | |||
45 | // snd_printk("IRQ: status = 0x%x\n", status); | 45 | // snd_printk("IRQ: status = 0x%x\n", status); |
46 | if (status & 0x02) { | 46 | if (status & 0x02) { |
47 | STAT_ADD(gus->gf1.interrupt_stat_midi_in); | 47 | STAT_ADD(gus->gf1.interrupt_stat_midi_in); |
48 | gus->gf1.interrupt_handler_midi_in(gus); | 48 | if (gus->gf1.interrupt_handler_midi_in) |
49 | gus->gf1.interrupt_handler_midi_in(gus); | ||
49 | } | 50 | } |
50 | if (status & 0x01) { | 51 | if (status & 0x01) { |
51 | STAT_ADD(gus->gf1.interrupt_stat_midi_out); | 52 | STAT_ADD(gus->gf1.interrupt_stat_midi_out); |
52 | gus->gf1.interrupt_handler_midi_out(gus); | 53 | if (gus->gf1.interrupt_handler_midi_out) |
54 | gus->gf1.interrupt_handler_midi_out(gus); | ||
53 | } | 55 | } |
54 | if (status & (0x20 | 0x40)) { | 56 | if (status & (0x20 | 0x40)) { |
55 | unsigned int already, _current_; | 57 | unsigned int already, _current_; |
@@ -85,20 +87,24 @@ __again: | |||
85 | } | 87 | } |
86 | if (status & 0x04) { | 88 | if (status & 0x04) { |
87 | STAT_ADD(gus->gf1.interrupt_stat_timer1); | 89 | STAT_ADD(gus->gf1.interrupt_stat_timer1); |
88 | gus->gf1.interrupt_handler_timer1(gus); | 90 | if (gus->gf1.interrupt_handler_timer1) |
91 | gus->gf1.interrupt_handler_timer1(gus); | ||
89 | } | 92 | } |
90 | if (status & 0x08) { | 93 | if (status & 0x08) { |
91 | STAT_ADD(gus->gf1.interrupt_stat_timer2); | 94 | STAT_ADD(gus->gf1.interrupt_stat_timer2); |
92 | gus->gf1.interrupt_handler_timer2(gus); | 95 | if (gus->gf1.interrupt_handler_timer2) |
96 | gus->gf1.interrupt_handler_timer2(gus); | ||
93 | } | 97 | } |
94 | if (status & 0x80) { | 98 | if (status & 0x80) { |
95 | if (snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL) & 0x40) { | 99 | if (snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL) & 0x40) { |
96 | STAT_ADD(gus->gf1.interrupt_stat_dma_write); | 100 | STAT_ADD(gus->gf1.interrupt_stat_dma_write); |
97 | gus->gf1.interrupt_handler_dma_write(gus); | 101 | if (gus->gf1.interrupt_handler_dma_write) |
102 | gus->gf1.interrupt_handler_dma_write(gus); | ||
98 | } | 103 | } |
99 | if (snd_gf1_i_look8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL) & 0x40) { | 104 | if (snd_gf1_i_look8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL) & 0x40) { |
100 | STAT_ADD(gus->gf1.interrupt_stat_dma_read); | 105 | STAT_ADD(gus->gf1.interrupt_stat_dma_read); |
101 | gus->gf1.interrupt_handler_dma_read(gus); | 106 | if (gus->gf1.interrupt_handler_dma_read) |
107 | gus->gf1.interrupt_handler_dma_read(gus); | ||
102 | } | 108 | } |
103 | } | 109 | } |
104 | if (--loop > 0) | 110 | if (--loop > 0) |
diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c index 8ced5e81b9a7..b14d5d6d9a32 100644 --- a/sound/isa/gus/gus_main.c +++ b/sound/isa/gus/gus_main.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Routines for Gravis UltraSound soundcards | 2 | * Routines for Gravis UltraSound soundcards |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -31,7 +31,7 @@ | |||
31 | 31 | ||
32 | #include <asm/dma.h> | 32 | #include <asm/dma.h> |
33 | 33 | ||
34 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 34 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
35 | MODULE_DESCRIPTION("Routines for Gravis UltraSound soundcards"); | 35 | MODULE_DESCRIPTION("Routines for Gravis UltraSound soundcards"); |
36 | MODULE_LICENSE("GPL"); | 36 | MODULE_LICENSE("GPL"); |
37 | 37 | ||
@@ -154,6 +154,14 @@ int snd_gus_create(struct snd_card *card, | |||
154 | gus = kzalloc(sizeof(*gus), GFP_KERNEL); | 154 | gus = kzalloc(sizeof(*gus), GFP_KERNEL); |
155 | if (gus == NULL) | 155 | if (gus == NULL) |
156 | return -ENOMEM; | 156 | return -ENOMEM; |
157 | spin_lock_init(&gus->reg_lock); | ||
158 | spin_lock_init(&gus->voice_alloc); | ||
159 | spin_lock_init(&gus->active_voice_lock); | ||
160 | spin_lock_init(&gus->event_lock); | ||
161 | spin_lock_init(&gus->dma_lock); | ||
162 | spin_lock_init(&gus->pcm_volume_level_lock); | ||
163 | spin_lock_init(&gus->uart_cmd_lock); | ||
164 | mutex_init(&gus->dma_mutex); | ||
157 | gus->gf1.irq = -1; | 165 | gus->gf1.irq = -1; |
158 | gus->gf1.dma1 = -1; | 166 | gus->gf1.dma1 = -1; |
159 | gus->gf1.dma2 = -1; | 167 | gus->gf1.dma2 = -1; |
@@ -218,14 +226,6 @@ int snd_gus_create(struct snd_card *card, | |||
218 | gus->gf1.pcm_channels = pcm_channels; | 226 | gus->gf1.pcm_channels = pcm_channels; |
219 | gus->gf1.volume_ramp = 25; | 227 | gus->gf1.volume_ramp = 25; |
220 | gus->gf1.smooth_pan = 1; | 228 | gus->gf1.smooth_pan = 1; |
221 | spin_lock_init(&gus->reg_lock); | ||
222 | spin_lock_init(&gus->voice_alloc); | ||
223 | spin_lock_init(&gus->active_voice_lock); | ||
224 | spin_lock_init(&gus->event_lock); | ||
225 | spin_lock_init(&gus->dma_lock); | ||
226 | spin_lock_init(&gus->pcm_volume_level_lock); | ||
227 | spin_lock_init(&gus->uart_cmd_lock); | ||
228 | mutex_init(&gus->dma_mutex); | ||
229 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, gus, &ops)) < 0) { | 229 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, gus, &ops)) < 0) { |
230 | snd_gus_free(gus); | 230 | snd_gus_free(gus); |
231 | return err; | 231 | return err; |
@@ -398,7 +398,7 @@ static int snd_gus_check_version(struct snd_gus_card * gus) | |||
398 | gus->ess_flag = 1; | 398 | gus->ess_flag = 1; |
399 | } else { | 399 | } else { |
400 | snd_printk(KERN_ERR "unknown GF1 revision number at 0x%lx - 0x%x (0x%x)\n", gus->gf1.port, rev, val); | 400 | snd_printk(KERN_ERR "unknown GF1 revision number at 0x%lx - 0x%x (0x%x)\n", gus->gf1.port, rev, val); |
401 | snd_printk(KERN_ERR " please - report to <perex@suse.cz>\n"); | 401 | snd_printk(KERN_ERR " please - report to <perex@perex.cz>\n"); |
402 | } | 402 | } |
403 | } | 403 | } |
404 | } | 404 | } |
diff --git a/sound/isa/gus/gus_mem.c b/sound/isa/gus/gus_mem.c index 7107753b85b5..bcf4656853c4 100644 --- a/sound/isa/gus/gus_mem.c +++ b/sound/isa/gus/gus_mem.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * GUS's memory allocation routines / bottom layer | 3 | * GUS's memory allocation routines / bottom layer |
4 | * | 4 | * |
5 | * | 5 | * |
diff --git a/sound/isa/gus/gus_mem_proc.c b/sound/isa/gus/gus_mem_proc.c index 80f0a83818b2..f69a44728ebf 100644 --- a/sound/isa/gus/gus_mem_proc.c +++ b/sound/isa/gus/gus_mem_proc.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * GUS's memory access via proc filesystem | 3 | * GUS's memory access via proc filesystem |
4 | * | 4 | * |
5 | * | 5 | * |
diff --git a/sound/isa/gus/gus_mixer.c b/sound/isa/gus/gus_mixer.c index acc25a297200..a96253e16654 100644 --- a/sound/isa/gus/gus_mixer.c +++ b/sound/isa/gus/gus_mixer.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Routines for control of ICS 2101 chip and "mixer" in GF1 chip | 3 | * Routines for control of ICS 2101 chip and "mixer" in GF1 chip |
4 | * | 4 | * |
5 | * | 5 | * |
@@ -36,14 +36,7 @@ | |||
36 | .get = snd_gf1_get_single, .put = snd_gf1_put_single, \ | 36 | .get = snd_gf1_get_single, .put = snd_gf1_put_single, \ |
37 | .private_value = shift | (invert << 8) } | 37 | .private_value = shift | (invert << 8) } |
38 | 38 | ||
39 | static int snd_gf1_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 39 | #define snd_gf1_info_single snd_ctl_boolean_mono_info |
40 | { | ||
41 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
42 | uinfo->count = 1; | ||
43 | uinfo->value.integer.min = 0; | ||
44 | uinfo->value.integer.max = 1; | ||
45 | return 0; | ||
46 | } | ||
47 | 40 | ||
48 | static int snd_gf1_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 41 | static int snd_gf1_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
49 | { | 42 | { |
diff --git a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c index c7f95e7aa018..a7971f5ffe63 100644 --- a/sound/isa/gus/gus_pcm.c +++ b/sound/isa/gus/gus_pcm.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Routines for control of GF1 chip (PCM things) | 3 | * Routines for control of GF1 chip (PCM things) |
4 | * | 4 | * |
5 | * InterWave chips supports interleaved DMA, but this feature isn't used in | 5 | * InterWave chips supports interleaved DMA, but this feature isn't used in |
diff --git a/sound/isa/gus/gus_reset.c b/sound/isa/gus/gus_reset.c index b263655c4116..20cfdb87f84a 100644 --- a/sound/isa/gus/gus_reset.c +++ b/sound/isa/gus/gus_reset.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * | 3 | * |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
diff --git a/sound/isa/gus/gus_sample.c b/sound/isa/gus/gus_sample.c index 9e0c55ab25b2..cba0829a7106 100644 --- a/sound/isa/gus/gus_sample.c +++ b/sound/isa/gus/gus_sample.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Routines for Gravis UltraSound soundcards - Sample support | 2 | * Routines for Gravis UltraSound soundcards - Sample support |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
diff --git a/sound/isa/gus/gus_simple.c b/sound/isa/gus/gus_simple.c index dcad6ed0198c..39d121e2c8c4 100644 --- a/sound/isa/gus/gus_simple.c +++ b/sound/isa/gus/gus_simple.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Routines for Gravis UltraSound soundcards - Simple instrument handlers | 2 | * Routines for Gravis UltraSound soundcards - Simple instrument handlers |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
diff --git a/sound/isa/gus/gus_synth.c b/sound/isa/gus/gus_synth.c index 3e4d4d6edd8b..2c2051782aa2 100644 --- a/sound/isa/gus/gus_synth.c +++ b/sound/isa/gus/gus_synth.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Routines for Gravis UltraSound soundcards - Synthesizer | 2 | * Routines for Gravis UltraSound soundcards - Synthesizer |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -26,7 +26,7 @@ | |||
26 | #include <sound/gus.h> | 26 | #include <sound/gus.h> |
27 | #include <sound/seq_device.h> | 27 | #include <sound/seq_device.h> |
28 | 28 | ||
29 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 29 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
30 | MODULE_DESCRIPTION("Routines for Gravis UltraSound soundcards - Synthesizer"); | 30 | MODULE_DESCRIPTION("Routines for Gravis UltraSound soundcards - Synthesizer"); |
31 | MODULE_LICENSE("GPL"); | 31 | MODULE_LICENSE("GPL"); |
32 | 32 | ||
diff --git a/sound/isa/gus/gus_tables.h b/sound/isa/gus/gus_tables.h index 4adf098d3269..42a4ca0d622b 100644 --- a/sound/isa/gus/gus_tables.h +++ b/sound/isa/gus/gus_tables.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * | 3 | * |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
diff --git a/sound/isa/gus/gus_timer.c b/sound/isa/gus/gus_timer.c index a43b662f17c7..99eac573c414 100644 --- a/sound/isa/gus/gus_timer.c +++ b/sound/isa/gus/gus_timer.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Routines for Gravis UltraSound soundcards - Timers | 2 | * Routines for Gravis UltraSound soundcards - Timers |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * GUS have similar timers as AdLib (OPL2/OPL3 chips). | 5 | * GUS have similar timers as AdLib (OPL2/OPL3 chips). |
6 | * | 6 | * |
diff --git a/sound/isa/gus/gus_uart.c b/sound/isa/gus/gus_uart.c index 654290a8b21c..e6fd9b01c492 100644 --- a/sound/isa/gus/gus_uart.c +++ b/sound/isa/gus/gus_uart.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Routines for the GF1 MIDI interface - like UART 6850 | 3 | * Routines for the GF1 MIDI interface - like UART 6850 |
4 | * | 4 | * |
5 | * | 5 | * |
diff --git a/sound/isa/gus/gus_volume.c b/sound/isa/gus/gus_volume.c index dbbc0a6d7659..71a67744a14b 100644 --- a/sound/isa/gus/gus_volume.c +++ b/sound/isa/gus/gus_volume.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * | 3 | * |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
diff --git a/sound/isa/gus/gusclassic.c b/sound/isa/gus/gusclassic.c index 8f23f433d491..29e422b00b58 100644 --- a/sound/isa/gus/gusclassic.c +++ b/sound/isa/gus/gusclassic.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for Gravis UltraSound Classic soundcard | 2 | * Driver for Gravis UltraSound Classic soundcard |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -37,7 +37,7 @@ | |||
37 | #define DEV_NAME "gusclassic" | 37 | #define DEV_NAME "gusclassic" |
38 | 38 | ||
39 | MODULE_DESCRIPTION(CRD_NAME); | 39 | MODULE_DESCRIPTION(CRD_NAME); |
40 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 40 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
41 | MODULE_LICENSE("GPL"); | 41 | MODULE_LICENSE("GPL"); |
42 | MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound Classic}}"); | 42 | MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound Classic}}"); |
43 | 43 | ||
diff --git a/sound/isa/gus/gusextreme.c b/sound/isa/gus/gusextreme.c index 0aeaa6cf6cf0..fc59536c918e 100644 --- a/sound/isa/gus/gusextreme.c +++ b/sound/isa/gus/gusextreme.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for Gravis UltraSound Extreme soundcards | 2 | * Driver for Gravis UltraSound Extreme soundcards |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -41,7 +41,7 @@ | |||
41 | #define DEV_NAME "gusextreme" | 41 | #define DEV_NAME "gusextreme" |
42 | 42 | ||
43 | MODULE_DESCRIPTION(CRD_NAME); | 43 | MODULE_DESCRIPTION(CRD_NAME); |
44 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 44 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
45 | MODULE_LICENSE("GPL"); | 45 | MODULE_LICENSE("GPL"); |
46 | MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound Extreme}}"); | 46 | MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound Extreme}}"); |
47 | 47 | ||
diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c index 708783d4351f..4922f5da08f9 100644 --- a/sound/isa/gus/gusmax.c +++ b/sound/isa/gus/gusmax.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for Gravis UltraSound MAX soundcard | 2 | * Driver for Gravis UltraSound MAX soundcard |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -34,7 +34,7 @@ | |||
34 | #define SNDRV_LEGACY_FIND_FREE_DMA | 34 | #define SNDRV_LEGACY_FIND_FREE_DMA |
35 | #include <sound/initval.h> | 35 | #include <sound/initval.h> |
36 | 36 | ||
37 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 37 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
38 | MODULE_DESCRIPTION("Gravis UltraSound MAX"); | 38 | MODULE_DESCRIPTION("Gravis UltraSound MAX"); |
39 | MODULE_LICENSE("GPL"); | 39 | MODULE_LICENSE("GPL"); |
40 | MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound MAX}}"); | 40 | MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound MAX}}"); |
diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c index 0220cdbe1a2a..2091c50b2e3e 100644 --- a/sound/isa/gus/interwave.c +++ b/sound/isa/gus/interwave.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for AMD InterWave soundcard | 2 | * Driver for AMD InterWave soundcard |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -41,7 +41,7 @@ | |||
41 | #define SNDRV_LEGACY_FIND_FREE_DMA | 41 | #define SNDRV_LEGACY_FIND_FREE_DMA |
42 | #include <sound/initval.h> | 42 | #include <sound/initval.h> |
43 | 43 | ||
44 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 44 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
45 | MODULE_LICENSE("GPL"); | 45 | MODULE_LICENSE("GPL"); |
46 | #ifndef SNDRV_STB | 46 | #ifndef SNDRV_STB |
47 | MODULE_DESCRIPTION("AMD InterWave"); | 47 | MODULE_DESCRIPTION("AMD InterWave"); |
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c index e70db32991d9..59af9ab7191f 100644 --- a/sound/isa/opl3sa2.c +++ b/sound/isa/opl3sa2.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for Yamaha OPL3-SA[2,3] soundcards | 2 | * Driver for Yamaha OPL3-SA[2,3] soundcards |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -37,7 +37,7 @@ | |||
37 | 37 | ||
38 | #include <asm/io.h> | 38 | #include <asm/io.h> |
39 | 39 | ||
40 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 40 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
41 | MODULE_DESCRIPTION("Yamaha OPL3SA2+"); | 41 | MODULE_DESCRIPTION("Yamaha OPL3SA2+"); |
42 | MODULE_LICENSE("GPL"); | 42 | MODULE_LICENSE("GPL"); |
43 | MODULE_SUPPORTED_DEVICE("{{Yamaha,YMF719E-S}," | 43 | MODULE_SUPPORTED_DEVICE("{{Yamaha,YMF719E-S}," |
@@ -253,6 +253,7 @@ static int __devinit snd_opl3sa2_detect(struct snd_opl3sa2 *chip) | |||
253 | /* 0x03 - YM715B */ | 253 | /* 0x03 - YM715B */ |
254 | /* 0x04 - YM719 - OPL-SA4? */ | 254 | /* 0x04 - YM719 - OPL-SA4? */ |
255 | /* 0x05 - OPL3-SA3 - Libretto 100 */ | 255 | /* 0x05 - OPL3-SA3 - Libretto 100 */ |
256 | /* 0x07 - unknown - Neomagic MagicWave 3D */ | ||
256 | break; | 257 | break; |
257 | } | 258 | } |
258 | str[0] = chip->version + '0'; | 259 | str[0] = chip->version + '0'; |
diff --git a/sound/isa/opti9xx/Makefile b/sound/isa/opti9xx/Makefile index 0e41bfd5a403..b4d894db257a 100644 --- a/sound/isa/opti9xx/Makefile +++ b/sound/isa/opti9xx/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-opti92x-ad1848-objs := opti92x-ad1848.o | 6 | snd-opti92x-ad1848-objs := opti92x-ad1848.o |
diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c index cd29b30b362e..d295936611f8 100644 --- a/sound/isa/opti9xx/miro.c +++ b/sound/isa/opti9xx/miro.c | |||
@@ -242,14 +242,7 @@ static int aci_setvalue(struct snd_miro * miro, unsigned char index, int value) | |||
242 | * MIXER part | 242 | * MIXER part |
243 | */ | 243 | */ |
244 | 244 | ||
245 | static int snd_miro_info_capture(struct snd_kcontrol *kcontrol, | 245 | #define snd_miro_info_capture snd_ctl_boolean_mono_info |
246 | struct snd_ctl_elem_info *uinfo) | ||
247 | { | ||
248 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
249 | uinfo->count = 1; | ||
250 | |||
251 | return 0; | ||
252 | } | ||
253 | 246 | ||
254 | static int snd_miro_get_capture(struct snd_kcontrol *kcontrol, | 247 | static int snd_miro_get_capture(struct snd_kcontrol *kcontrol, |
255 | struct snd_ctl_elem_value *ucontrol) | 248 | struct snd_ctl_elem_value *ucontrol) |
@@ -344,14 +337,7 @@ static int snd_miro_put_preamp(struct snd_kcontrol *kcontrol, | |||
344 | return change; | 337 | return change; |
345 | } | 338 | } |
346 | 339 | ||
347 | static int snd_miro_info_amp(struct snd_kcontrol *kcontrol, | 340 | #define snd_miro_info_amp snd_ctl_boolean_mono_info |
348 | struct snd_ctl_elem_info *uinfo) | ||
349 | { | ||
350 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
351 | uinfo->count = 1; | ||
352 | |||
353 | return 0; | ||
354 | } | ||
355 | 341 | ||
356 | static int snd_miro_get_amp(struct snd_kcontrol *kcontrol, | 342 | static int snd_miro_get_amp(struct snd_kcontrol *kcontrol, |
357 | struct snd_ctl_elem_value *ucontrol) | 343 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index 049d479ce2b3..ee1a824d8fc0 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c | |||
@@ -501,6 +501,16 @@ static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip) | |||
501 | (chip->hardware == OPTi9XX_HW_82C930 ? 0x00 : 0x04), | 501 | (chip->hardware == OPTi9XX_HW_82C930 ? 0x00 : 0x04), |
502 | 0x34); | 502 | 0x34); |
503 | snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x20, 0xbf); | 503 | snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x20, 0xbf); |
504 | /* | ||
505 | * The BTC 1817DW has QS1000 wavetable which is connected | ||
506 | * to the serial digital input of the OPTI931. | ||
507 | */ | ||
508 | snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(21), 0x82, 0xff); | ||
509 | /* | ||
510 | * This bit sets OPTI931 to automaticaly select FM | ||
511 | * or digital input signal. | ||
512 | */ | ||
513 | snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(26), 0x01, 0x01); | ||
504 | break; | 514 | break; |
505 | #endif /* OPTi93X */ | 515 | #endif /* OPTi93X */ |
506 | 516 | ||
@@ -1732,11 +1742,11 @@ static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip, | |||
1732 | 1742 | ||
1733 | #ifdef OPTi93X | 1743 | #ifdef OPTi93X |
1734 | port = pnp_port_start(pdev, 0) - 4; | 1744 | port = pnp_port_start(pdev, 0) - 4; |
1735 | fm_port = pnp_port_start(pdev, 1); | 1745 | fm_port = pnp_port_start(pdev, 1) + 8; |
1736 | #else | 1746 | #else |
1737 | if (pid->driver_data != 0x0924) | 1747 | if (pid->driver_data != 0x0924) |
1738 | port = pnp_port_start(pdev, 1); | 1748 | port = pnp_port_start(pdev, 1); |
1739 | fm_port = pnp_port_start(pdev, 2); | 1749 | fm_port = pnp_port_start(pdev, 2) + 8; |
1740 | #endif /* OPTi93X */ | 1750 | #endif /* OPTi93X */ |
1741 | irq = pnp_irq(pdev, 0); | 1751 | irq = pnp_irq(pdev, 0); |
1742 | dma1 = pnp_dma(pdev, 0); | 1752 | dma1 = pnp_dma(pdev, 0); |
diff --git a/sound/isa/sb/Makefile b/sound/isa/sb/Makefile index 556e66928029..c9d1c986d70e 100644 --- a/sound/isa/sb/Makefile +++ b/sound/isa/sb/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-sb-common-objs := sb_common.o sb_mixer.o | 6 | snd-sb-common-objs := sb_common.o sb_mixer.o |
diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c index 658179e86142..4eea84cfd4f4 100644 --- a/sound/isa/sb/emu8000.c +++ b/sound/isa/sb/emu8000.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * and (c) 1999 Steve Ratcliffe <steve@parabola.demon.co.uk> | 3 | * and (c) 1999 Steve Ratcliffe <steve@parabola.demon.co.uk> |
4 | * Copyright (C) 1999-2000 Takashi Iwai <tiwai@suse.de> | 4 | * Copyright (C) 1999-2000 Takashi Iwai <tiwai@suse.de> |
5 | * | 5 | * |
diff --git a/sound/isa/sb/emu8000_synth.c b/sound/isa/sb/emu8000_synth.c index 3d72742b342f..0c7905c85b76 100644 --- a/sound/isa/sb/emu8000_synth.c +++ b/sound/isa/sb/emu8000_synth.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * and (c) 1999 Steve Ratcliffe <steve@parabola.demon.co.uk> | 3 | * and (c) 1999 Steve Ratcliffe <steve@parabola.demon.co.uk> |
4 | * Copyright (C) 1999-2000 Takashi Iwai <tiwai@suse.de> | 4 | * Copyright (C) 1999-2000 Takashi Iwai <tiwai@suse.de> |
5 | * | 5 | * |
diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c index c4ba24bfd27c..e7f9edd92626 100644 --- a/sound/isa/sb/sb16.c +++ b/sound/isa/sb/sb16.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for SoundBlaster 16/AWE32/AWE64 soundcards | 2 | * Driver for SoundBlaster 16/AWE32/AWE64 soundcards |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -44,7 +44,7 @@ | |||
44 | #define PFX "sb16: " | 44 | #define PFX "sb16: " |
45 | #endif | 45 | #endif |
46 | 46 | ||
47 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 47 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
48 | MODULE_LICENSE("GPL"); | 48 | MODULE_LICENSE("GPL"); |
49 | #ifndef SNDRV_SBAWE | 49 | #ifndef SNDRV_SBAWE |
50 | MODULE_DESCRIPTION("Sound Blaster 16"); | 50 | MODULE_DESCRIPTION("Sound Blaster 16"); |
diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c index b279f2308aef..3682059787ab 100644 --- a/sound/isa/sb/sb16_csp.c +++ b/sound/isa/sb/sb16_csp.c | |||
@@ -979,14 +979,7 @@ static int snd_sb_csp_restart(struct snd_sb_csp * p) | |||
979 | * QSound mixer control for PCM | 979 | * QSound mixer control for PCM |
980 | */ | 980 | */ |
981 | 981 | ||
982 | static int snd_sb_qsound_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 982 | #define snd_sb_qsound_switch_info snd_ctl_boolean_mono_info |
983 | { | ||
984 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
985 | uinfo->count = 1; | ||
986 | uinfo->value.integer.min = 0; | ||
987 | uinfo->value.integer.max = 1; | ||
988 | return 0; | ||
989 | } | ||
990 | 983 | ||
991 | static int snd_sb_qsound_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 984 | static int snd_sb_qsound_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
992 | { | 985 | { |
diff --git a/sound/isa/sb/sb16_main.c b/sound/isa/sb/sb16_main.c index 5d4d3aafe2d5..c06754f7ee5d 100644 --- a/sound/isa/sb/sb16_main.c +++ b/sound/isa/sb/sb16_main.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Routines for control of 16-bit SoundBlaster cards and clones | 3 | * Routines for control of 16-bit SoundBlaster cards and clones |
4 | * Note: This is very ugly hardware which uses one 8-bit DMA channel and | 4 | * Note: This is very ugly hardware which uses one 8-bit DMA channel and |
5 | * second 16-bit DMA channel. Unfortunately 8-bit DMA channel can't | 5 | * second 16-bit DMA channel. Unfortunately 8-bit DMA channel can't |
@@ -45,7 +45,7 @@ | |||
45 | #include <sound/control.h> | 45 | #include <sound/control.h> |
46 | #include <sound/info.h> | 46 | #include <sound/info.h> |
47 | 47 | ||
48 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 48 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
49 | MODULE_DESCRIPTION("Routines for control of 16-bit SoundBlaster cards and clones"); | 49 | MODULE_DESCRIPTION("Routines for control of 16-bit SoundBlaster cards and clones"); |
50 | MODULE_LICENSE("GPL"); | 50 | MODULE_LICENSE("GPL"); |
51 | 51 | ||
diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c index a1b3786b391e..f933aef7d8a9 100644 --- a/sound/isa/sb/sb8.c +++ b/sound/isa/sb/sb8.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for SoundBlaster 1.0/2.0/Pro soundcards and compatible | 2 | * Driver for SoundBlaster 1.0/2.0/Pro soundcards and compatible |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -31,7 +31,7 @@ | |||
31 | #include <sound/opl3.h> | 31 | #include <sound/opl3.h> |
32 | #include <sound/initval.h> | 32 | #include <sound/initval.h> |
33 | 33 | ||
34 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 34 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
35 | MODULE_DESCRIPTION("Sound Blaster 1.0/2.0/Pro"); | 35 | MODULE_DESCRIPTION("Sound Blaster 1.0/2.0/Pro"); |
36 | MODULE_LICENSE("GPL"); | 36 | MODULE_LICENSE("GPL"); |
37 | MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB 1.0/SB 2.0/SB Pro}}"); | 37 | MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB 1.0/SB 2.0/SB Pro}}"); |
diff --git a/sound/isa/sb/sb8_main.c b/sound/isa/sb/sb8_main.c index aea9e5ec7b36..bee894b3f5c7 100644 --- a/sound/isa/sb/sb8_main.c +++ b/sound/isa/sb/sb8_main.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Uros Bizjak <uros@kss-loka.si> | 3 | * Uros Bizjak <uros@kss-loka.si> |
4 | * | 4 | * |
5 | * Routines for control of 8-bit SoundBlaster cards and clones | 5 | * Routines for control of 8-bit SoundBlaster cards and clones |
@@ -38,7 +38,7 @@ | |||
38 | #include <sound/core.h> | 38 | #include <sound/core.h> |
39 | #include <sound/sb.h> | 39 | #include <sound/sb.h> |
40 | 40 | ||
41 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Uros Bizjak <uros@kss-loka.si>"); | 41 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Uros Bizjak <uros@kss-loka.si>"); |
42 | MODULE_DESCRIPTION("Routines for control of 8-bit SoundBlaster cards and clones"); | 42 | MODULE_DESCRIPTION("Routines for control of 8-bit SoundBlaster cards and clones"); |
43 | MODULE_LICENSE("GPL"); | 43 | MODULE_LICENSE("GPL"); |
44 | 44 | ||
diff --git a/sound/isa/sb/sb8_midi.c b/sound/isa/sb/sb8_midi.c index 0b67edd7ac6e..e56e5633411c 100644 --- a/sound/isa/sb/sb8_midi.c +++ b/sound/isa/sb/sb8_midi.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Routines for control of SoundBlaster cards - MIDI interface | 3 | * Routines for control of SoundBlaster cards - MIDI interface |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
diff --git a/sound/isa/sb/sb_common.c b/sound/isa/sb/sb_common.c index efa9d5c2558a..176193c05101 100644 --- a/sound/isa/sb/sb_common.c +++ b/sound/isa/sb/sb_common.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Uros Bizjak <uros@kss-loka.si> | 3 | * Uros Bizjak <uros@kss-loka.si> |
4 | * | 4 | * |
5 | * Lowlevel routines for control of Sound Blaster cards | 5 | * Lowlevel routines for control of Sound Blaster cards |
@@ -33,7 +33,7 @@ | |||
33 | #include <asm/io.h> | 33 | #include <asm/io.h> |
34 | #include <asm/dma.h> | 34 | #include <asm/dma.h> |
35 | 35 | ||
36 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 36 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
37 | MODULE_DESCRIPTION("ALSA lowlevel driver for Sound Blaster cards"); | 37 | MODULE_DESCRIPTION("ALSA lowlevel driver for Sound Blaster cards"); |
38 | MODULE_LICENSE("GPL"); | 38 | MODULE_LICENSE("GPL"); |
39 | 39 | ||
@@ -234,7 +234,9 @@ int snd_sbdsp_create(struct snd_card *card, | |||
234 | chip->dma16 = -1; | 234 | chip->dma16 = -1; |
235 | chip->port = port; | 235 | chip->port = port; |
236 | 236 | ||
237 | if (request_irq(irq, irq_handler, hardware == SB_HW_ALS4000 ? | 237 | if (request_irq(irq, irq_handler, |
238 | (hardware == SB_HW_ALS4000 || | ||
239 | hardware == SB_HW_CS5530) ? | ||
238 | IRQF_SHARED : IRQF_DISABLED, | 240 | IRQF_SHARED : IRQF_DISABLED, |
239 | "SoundBlaster", (void *) chip)) { | 241 | "SoundBlaster", (void *) chip)) { |
240 | snd_printk(KERN_ERR "sb: can't grab irq %d\n", irq); | 242 | snd_printk(KERN_ERR "sb: can't grab irq %d\n", irq); |
diff --git a/sound/isa/sb/sb_mixer.c b/sound/isa/sb/sb_mixer.c index 3d4befcff28e..03241cd5aaef 100644 --- a/sound/isa/sb/sb_mixer.c +++ b/sound/isa/sb/sb_mixer.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Routines for Sound Blaster mixer control | 3 | * Routines for Sound Blaster mixer control |
4 | * | 4 | * |
5 | * | 5 | * |
diff --git a/sound/isa/sc6000.c b/sound/isa/sc6000.c new file mode 100644 index 000000000000..94daf8399994 --- /dev/null +++ b/sound/isa/sc6000.c | |||
@@ -0,0 +1,656 @@ | |||
1 | /* | ||
2 | * Driver for Gallant SC-6000 soundcard. This card is also known as | ||
3 | * Audio Excel DSP 16 or Zoltrix AV302. | ||
4 | * These cards use CompuMedia ASC-9308 chip + AD1848 codec. | ||
5 | * | ||
6 | * Copyright (C) 2007 Krzysztof Helt <krzysztof.h1@wp.pl> | ||
7 | * | ||
8 | * I don't have documentation for this card. I used the driver | ||
9 | * for OSS/Free included in the kernel source as reference. | ||
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 | #include <sound/driver.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/delay.h> | ||
29 | #include <linux/isa.h> | ||
30 | #include <linux/io.h> | ||
31 | #include <asm/dma.h> | ||
32 | #include <sound/core.h> | ||
33 | #include <sound/ad1848.h> | ||
34 | #include <sound/opl3.h> | ||
35 | #include <sound/mpu401.h> | ||
36 | #include <sound/control.h> | ||
37 | #define SNDRV_LEGACY_FIND_FREE_IRQ | ||
38 | #define SNDRV_LEGACY_FIND_FREE_DMA | ||
39 | #include <sound/initval.h> | ||
40 | |||
41 | MODULE_AUTHOR("Krzysztof Helt"); | ||
42 | MODULE_DESCRIPTION("Gallant SC-6000"); | ||
43 | MODULE_LICENSE("GPL"); | ||
44 | MODULE_SUPPORTED_DEVICE("{{Gallant, SC-6000}," | ||
45 | "{AudioExcel, Audio Excel DSP 16}," | ||
46 | "{Zoltrix, AV302}}"); | ||
47 | |||
48 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ | ||
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 */ | ||
51 | static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220, 0x240 */ | ||
52 | static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5, 7, 9, 10, 11 */ | ||
53 | static long mss_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x530, 0xe80 */ | ||
54 | static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; | ||
55 | /* 0x300, 0x310, 0x320, 0x330 */ | ||
56 | static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5, 7, 9, 10, 0 */ | ||
57 | static int dma[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0, 1, 3 */ | ||
58 | |||
59 | module_param_array(index, int, NULL, 0444); | ||
60 | MODULE_PARM_DESC(index, "Index value for sc-6000 based soundcard."); | ||
61 | module_param_array(id, charp, NULL, 0444); | ||
62 | MODULE_PARM_DESC(id, "ID string for sc-6000 based soundcard."); | ||
63 | module_param_array(enable, bool, NULL, 0444); | ||
64 | MODULE_PARM_DESC(enable, "Enable sc-6000 based soundcard."); | ||
65 | module_param_array(port, long, NULL, 0444); | ||
66 | MODULE_PARM_DESC(port, "Port # for sc-6000 driver."); | ||
67 | module_param_array(mss_port, long, NULL, 0444); | ||
68 | MODULE_PARM_DESC(mss_port, "MSS Port # for sc-6000 driver."); | ||
69 | module_param_array(mpu_port, long, NULL, 0444); | ||
70 | MODULE_PARM_DESC(mpu_port, "MPU-401 port # for sc-6000 driver."); | ||
71 | module_param_array(irq, int, NULL, 0444); | ||
72 | MODULE_PARM_DESC(irq, "IRQ # for sc-6000 driver."); | ||
73 | module_param_array(mpu_irq, int, NULL, 0444); | ||
74 | MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for sc-6000 driver."); | ||
75 | module_param_array(dma, int, NULL, 0444); | ||
76 | MODULE_PARM_DESC(dma, "DMA # for sc-6000 driver."); | ||
77 | |||
78 | /* | ||
79 | * Commands of SC6000's DSP (SBPRO+special). | ||
80 | * Some of them are COMMAND_xx, in the future they may change. | ||
81 | */ | ||
82 | #define WRITE_MDIRQ_CFG 0x50 /* Set M&I&DRQ mask (the real config) */ | ||
83 | #define COMMAND_52 0x52 /* */ | ||
84 | #define READ_HARD_CFG 0x58 /* Read Hardware Config (I/O base etc) */ | ||
85 | #define COMMAND_5C 0x5c /* */ | ||
86 | #define COMMAND_60 0x60 /* */ | ||
87 | #define COMMAND_66 0x66 /* */ | ||
88 | #define COMMAND_6C 0x6c /* */ | ||
89 | #define COMMAND_6E 0x6e /* */ | ||
90 | #define COMMAND_88 0x88 /* Unknown command */ | ||
91 | #define DSP_INIT_MSS 0x8c /* Enable Microsoft Sound System mode */ | ||
92 | #define COMMAND_C5 0xc5 /* */ | ||
93 | #define GET_DSP_VERSION 0xe1 /* Get DSP Version */ | ||
94 | #define GET_DSP_COPYRIGHT 0xe3 /* Get DSP Copyright */ | ||
95 | |||
96 | /* | ||
97 | * Offsets of SC6000 DSP I/O ports. The offset is added to base I/O port | ||
98 | * to have the actual I/O port. | ||
99 | * Register permissions are: | ||
100 | * (wo) == Write Only | ||
101 | * (ro) == Read Only | ||
102 | * (w-) == Write | ||
103 | * (r-) == Read | ||
104 | */ | ||
105 | #define DSP_RESET 0x06 /* offset of DSP RESET (wo) */ | ||
106 | #define DSP_READ 0x0a /* offset of DSP READ (ro) */ | ||
107 | #define DSP_WRITE 0x0c /* offset of DSP WRITE (w-) */ | ||
108 | #define DSP_COMMAND 0x0c /* offset of DSP COMMAND (w-) */ | ||
109 | #define DSP_STATUS 0x0c /* offset of DSP STATUS (r-) */ | ||
110 | #define DSP_DATAVAIL 0x0e /* offset of DSP DATA AVAILABLE (ro) */ | ||
111 | |||
112 | #define PFX "sc6000: " | ||
113 | #define DRV_NAME "SC-6000" | ||
114 | |||
115 | /* hardware dependent functions */ | ||
116 | |||
117 | /* | ||
118 | * sc6000_irq_to_softcfg - Decode irq number into cfg code. | ||
119 | */ | ||
120 | static __devinit unsigned char sc6000_irq_to_softcfg(int irq) | ||
121 | { | ||
122 | unsigned char val = 0; | ||
123 | |||
124 | switch (irq) { | ||
125 | case 5: | ||
126 | val = 0x28; | ||
127 | break; | ||
128 | case 7: | ||
129 | val = 0x8; | ||
130 | break; | ||
131 | case 9: | ||
132 | val = 0x10; | ||
133 | break; | ||
134 | case 10: | ||
135 | val = 0x18; | ||
136 | break; | ||
137 | case 11: | ||
138 | val = 0x20; | ||
139 | break; | ||
140 | default: | ||
141 | break; | ||
142 | } | ||
143 | return val; | ||
144 | } | ||
145 | |||
146 | /* | ||
147 | * sc6000_dma_to_softcfg - Decode dma number into cfg code. | ||
148 | */ | ||
149 | static __devinit unsigned char sc6000_dma_to_softcfg(int dma) | ||
150 | { | ||
151 | unsigned char val = 0; | ||
152 | |||
153 | switch (dma) { | ||
154 | case 0: | ||
155 | val = 1; | ||
156 | break; | ||
157 | case 1: | ||
158 | val = 2; | ||
159 | break; | ||
160 | case 3: | ||
161 | val = 3; | ||
162 | break; | ||
163 | default: | ||
164 | break; | ||
165 | } | ||
166 | return val; | ||
167 | } | ||
168 | |||
169 | /* | ||
170 | * sc6000_mpu_irq_to_softcfg - Decode MPU-401 irq number into cfg code. | ||
171 | */ | ||
172 | static __devinit unsigned char sc6000_mpu_irq_to_softcfg(int mpu_irq) | ||
173 | { | ||
174 | unsigned char val = 0; | ||
175 | |||
176 | switch (mpu_irq) { | ||
177 | case 5: | ||
178 | val = 4; | ||
179 | break; | ||
180 | case 7: | ||
181 | val = 0x44; | ||
182 | break; | ||
183 | case 9: | ||
184 | val = 0x84; | ||
185 | break; | ||
186 | case 10: | ||
187 | val = 0xc4; | ||
188 | break; | ||
189 | default: | ||
190 | break; | ||
191 | } | ||
192 | return val; | ||
193 | } | ||
194 | |||
195 | static __devinit int sc6000_wait_data(char __iomem *vport) | ||
196 | { | ||
197 | int loop = 1000; | ||
198 | unsigned char val = 0; | ||
199 | |||
200 | do { | ||
201 | val = ioread8(vport + DSP_DATAVAIL); | ||
202 | if (val & 0x80) | ||
203 | return 0; | ||
204 | cpu_relax(); | ||
205 | } while (loop--); | ||
206 | |||
207 | return -EAGAIN; | ||
208 | } | ||
209 | |||
210 | static __devinit int sc6000_read(char __iomem *vport) | ||
211 | { | ||
212 | if (sc6000_wait_data(vport)) | ||
213 | return -EBUSY; | ||
214 | |||
215 | return ioread8(vport + DSP_READ); | ||
216 | |||
217 | } | ||
218 | |||
219 | static __devinit int sc6000_write(char __iomem *vport, int cmd) | ||
220 | { | ||
221 | unsigned char val; | ||
222 | int loop = 500000; | ||
223 | |||
224 | do { | ||
225 | val = ioread8(vport + DSP_STATUS); | ||
226 | /* | ||
227 | * DSP ready to receive data if bit 7 of val == 0 | ||
228 | */ | ||
229 | if (!(val & 0x80)) { | ||
230 | iowrite8(cmd, vport + DSP_COMMAND); | ||
231 | return 0; | ||
232 | } | ||
233 | cpu_relax(); | ||
234 | } while (loop--); | ||
235 | |||
236 | snd_printk(KERN_ERR "DSP Command (0x%x) timeout.\n", cmd); | ||
237 | |||
238 | return -EIO; | ||
239 | } | ||
240 | |||
241 | static int __devinit sc6000_dsp_get_answer(char __iomem *vport, int command, | ||
242 | char *data, int data_len) | ||
243 | { | ||
244 | int len = 0; | ||
245 | |||
246 | if (sc6000_write(vport, command)) { | ||
247 | snd_printk(KERN_ERR "CMD 0x%x: failed!\n", command); | ||
248 | return -EIO; | ||
249 | } | ||
250 | |||
251 | do { | ||
252 | int val = sc6000_read(vport); | ||
253 | |||
254 | if (val < 0) | ||
255 | break; | ||
256 | |||
257 | data[len++] = val; | ||
258 | |||
259 | } while (len < data_len); | ||
260 | |||
261 | /* | ||
262 | * If no more data available, return to the caller, no error if len>0. | ||
263 | * We have no other way to know when the string is finished. | ||
264 | */ | ||
265 | return len ? len : -EIO; | ||
266 | } | ||
267 | |||
268 | static int __devinit sc6000_dsp_reset(char __iomem *vport) | ||
269 | { | ||
270 | iowrite8(1, vport + DSP_RESET); | ||
271 | udelay(10); | ||
272 | iowrite8(0, vport + DSP_RESET); | ||
273 | udelay(20); | ||
274 | if (sc6000_read(vport) == 0xaa) | ||
275 | return 0; | ||
276 | return -ENODEV; | ||
277 | } | ||
278 | |||
279 | /* detection and initialization */ | ||
280 | static int __devinit sc6000_cfg_write(char __iomem *vport, | ||
281 | unsigned char softcfg) | ||
282 | { | ||
283 | |||
284 | if (sc6000_write(vport, WRITE_MDIRQ_CFG)) { | ||
285 | snd_printk(KERN_ERR "CMD 0x%x: failed!\n", WRITE_MDIRQ_CFG); | ||
286 | return -EIO; | ||
287 | } | ||
288 | if (sc6000_write(vport, softcfg)) { | ||
289 | snd_printk(KERN_ERR "sc6000_cfg_write: failed!\n"); | ||
290 | return -EIO; | ||
291 | } | ||
292 | return 0; | ||
293 | } | ||
294 | |||
295 | static int __devinit sc6000_setup_board(char __iomem *vport, int config) | ||
296 | { | ||
297 | int loop = 10; | ||
298 | |||
299 | do { | ||
300 | if (sc6000_write(vport, COMMAND_88)) { | ||
301 | snd_printk(KERN_ERR "CMD 0x%x: failed!\n", | ||
302 | COMMAND_88); | ||
303 | return -EIO; | ||
304 | } | ||
305 | } while ((sc6000_wait_data(vport) < 0) && loop--); | ||
306 | |||
307 | if (sc6000_read(vport) < 0) { | ||
308 | snd_printk(KERN_ERR "sc6000_read after CMD 0x%x: failed\n", | ||
309 | COMMAND_88); | ||
310 | return -EIO; | ||
311 | } | ||
312 | |||
313 | if (sc6000_cfg_write(vport, config)) | ||
314 | return -ENODEV; | ||
315 | |||
316 | return 0; | ||
317 | } | ||
318 | |||
319 | static int __devinit sc6000_init_mss(char __iomem *vport, int config, | ||
320 | char __iomem *vmss_port, int mss_config) | ||
321 | { | ||
322 | if (sc6000_write(vport, DSP_INIT_MSS)) { | ||
323 | snd_printk(KERN_ERR "sc6000_init_mss [0x%x]: failed!\n", | ||
324 | DSP_INIT_MSS); | ||
325 | return -EIO; | ||
326 | } | ||
327 | |||
328 | msleep(10); | ||
329 | |||
330 | if (sc6000_cfg_write(vport, config)) | ||
331 | return -EIO; | ||
332 | |||
333 | iowrite8(mss_config, vmss_port); | ||
334 | |||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | static int __devinit sc6000_init_board(char __iomem *vport, int irq, int dma, | ||
339 | char __iomem *vmss_port, int mpu_irq) | ||
340 | { | ||
341 | char answer[15]; | ||
342 | char version[2]; | ||
343 | int mss_config = sc6000_irq_to_softcfg(irq) | | ||
344 | sc6000_dma_to_softcfg(dma); | ||
345 | int config = mss_config | | ||
346 | sc6000_mpu_irq_to_softcfg(mpu_irq); | ||
347 | int err; | ||
348 | |||
349 | err = sc6000_dsp_reset(vport); | ||
350 | if (err < 0) { | ||
351 | snd_printk(KERN_ERR "sc6000_dsp_reset: failed!\n"); | ||
352 | return err; | ||
353 | } | ||
354 | |||
355 | memset(answer, 0, sizeof(answer)); | ||
356 | err = sc6000_dsp_get_answer(vport, GET_DSP_COPYRIGHT, answer, 15); | ||
357 | if (err <= 0) { | ||
358 | snd_printk(KERN_ERR "sc6000_dsp_copyright: failed!\n"); | ||
359 | return -ENODEV; | ||
360 | } | ||
361 | /* | ||
362 | * My SC-6000 card return "SC-6000" in DSPCopyright, so | ||
363 | * if we have something different, we have to be warned. | ||
364 | * Mine returns "SC-6000A " - KH | ||
365 | */ | ||
366 | if (strncmp("SC-6000", answer, 7)) | ||
367 | snd_printk(KERN_WARNING "Warning: non SC-6000 audio card!\n"); | ||
368 | |||
369 | if (sc6000_dsp_get_answer(vport, GET_DSP_VERSION, version, 2) < 2) { | ||
370 | snd_printk(KERN_ERR "sc6000_dsp_version: failed!\n"); | ||
371 | return -ENODEV; | ||
372 | } | ||
373 | printk(KERN_INFO PFX "Detected model: %s, DSP version %d.%d\n", | ||
374 | answer, version[0], version[1]); | ||
375 | |||
376 | /* | ||
377 | * 0x0A == (IRQ 7, DMA 1, MIRQ 0) | ||
378 | */ | ||
379 | err = sc6000_cfg_write(vport, 0x0a); | ||
380 | if (err < 0) { | ||
381 | snd_printk(KERN_ERR "sc6000_cfg_write: failed!\n"); | ||
382 | return -EFAULT; | ||
383 | } | ||
384 | |||
385 | err = sc6000_setup_board(vport, config); | ||
386 | if (err < 0) { | ||
387 | snd_printk(KERN_ERR "sc6000_setup_board: failed!\n"); | ||
388 | return -ENODEV; | ||
389 | } | ||
390 | |||
391 | err = sc6000_init_mss(vport, config, vmss_port, mss_config); | ||
392 | if (err < 0) { | ||
393 | snd_printk(KERN_ERR "Can not initialize" | ||
394 | "Microsoft Sound System mode.\n"); | ||
395 | return -ENODEV; | ||
396 | } | ||
397 | |||
398 | return 0; | ||
399 | } | ||
400 | |||
401 | static int __devinit snd_sc6000_mixer(struct snd_ad1848 *chip) | ||
402 | { | ||
403 | struct snd_card *card = chip->card; | ||
404 | struct snd_ctl_elem_id id1, id2; | ||
405 | int err; | ||
406 | |||
407 | memset(&id1, 0, sizeof(id1)); | ||
408 | memset(&id2, 0, sizeof(id2)); | ||
409 | id1.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | ||
410 | id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | ||
411 | /* reassign AUX0 to FM */ | ||
412 | strcpy(id1.name, "Aux Playback Switch"); | ||
413 | strcpy(id2.name, "FM Playback Switch"); | ||
414 | err = snd_ctl_rename_id(card, &id1, &id2); | ||
415 | if (err < 0) | ||
416 | return err; | ||
417 | strcpy(id1.name, "Aux Playback Volume"); | ||
418 | strcpy(id2.name, "FM Playback Volume"); | ||
419 | err = snd_ctl_rename_id(card, &id1, &id2); | ||
420 | if (err < 0) | ||
421 | return err; | ||
422 | /* reassign AUX1 to CD */ | ||
423 | strcpy(id1.name, "Aux Playback Switch"); id1.index = 1; | ||
424 | strcpy(id2.name, "CD Playback Switch"); | ||
425 | err = snd_ctl_rename_id(card, &id1, &id2); | ||
426 | if (err < 0) | ||
427 | return err; | ||
428 | strcpy(id1.name, "Aux Playback Volume"); | ||
429 | strcpy(id2.name, "CD Playback Volume"); | ||
430 | err = snd_ctl_rename_id(card, &id1, &id2); | ||
431 | if (err < 0) | ||
432 | return err; | ||
433 | return 0; | ||
434 | } | ||
435 | |||
436 | static int __devinit snd_sc6000_match(struct device *devptr, unsigned int dev) | ||
437 | { | ||
438 | if (!enable[dev]) | ||
439 | return 0; | ||
440 | if (port[dev] == SNDRV_AUTO_PORT) { | ||
441 | printk(KERN_ERR PFX "specify IO port\n"); | ||
442 | return 0; | ||
443 | } | ||
444 | if (mss_port[dev] == SNDRV_AUTO_PORT) { | ||
445 | printk(KERN_ERR PFX "specify MSS port\n"); | ||
446 | return 0; | ||
447 | } | ||
448 | if (port[dev] != 0x220 && port[dev] != 0x240) { | ||
449 | printk(KERN_ERR PFX "Port must be 0x220 or 0x240\n"); | ||
450 | return 0; | ||
451 | } | ||
452 | if (mss_port[dev] != 0x530 && mss_port[dev] != 0xe80) { | ||
453 | printk(KERN_ERR PFX "MSS port must be 0x530 or 0xe80\n"); | ||
454 | return 0; | ||
455 | } | ||
456 | if (irq[dev] != SNDRV_AUTO_IRQ && !sc6000_irq_to_softcfg(irq[dev])) { | ||
457 | printk(KERN_ERR PFX "invalid IRQ %d\n", irq[dev]); | ||
458 | return 0; | ||
459 | } | ||
460 | if (dma[dev] != SNDRV_AUTO_DMA && !sc6000_dma_to_softcfg(dma[dev])) { | ||
461 | printk(KERN_ERR PFX "invalid DMA %d\n", dma[dev]); | ||
462 | return 0; | ||
463 | } | ||
464 | if (mpu_port[dev] != SNDRV_AUTO_PORT && | ||
465 | (mpu_port[dev] & ~0x30L) != 0x300) { | ||
466 | printk(KERN_ERR PFX "invalid MPU-401 port %lx\n", | ||
467 | mpu_port[dev]); | ||
468 | return 0; | ||
469 | } | ||
470 | if (mpu_port[dev] != SNDRV_AUTO_PORT && | ||
471 | mpu_irq[dev] != SNDRV_AUTO_IRQ && mpu_irq[dev] != 0 && | ||
472 | !sc6000_mpu_irq_to_softcfg(mpu_irq[dev])) { | ||
473 | printk(KERN_ERR PFX "invalid MPU-401 IRQ %d\n", mpu_irq[dev]); | ||
474 | return 0; | ||
475 | } | ||
476 | return 1; | ||
477 | } | ||
478 | |||
479 | static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev) | ||
480 | { | ||
481 | static int possible_irqs[] = { 5, 7, 9, 10, 11, -1 }; | ||
482 | static int possible_dmas[] = { 1, 3, 0, -1 }; | ||
483 | int err; | ||
484 | int xirq = irq[dev]; | ||
485 | int xdma = dma[dev]; | ||
486 | struct snd_card *card; | ||
487 | struct snd_ad1848 *chip; | ||
488 | struct snd_opl3 *opl3; | ||
489 | char __iomem *vport; | ||
490 | char __iomem *vmss_port; | ||
491 | |||
492 | |||
493 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | ||
494 | if (!card) | ||
495 | return -ENOMEM; | ||
496 | |||
497 | if (xirq == SNDRV_AUTO_IRQ) { | ||
498 | xirq = snd_legacy_find_free_irq(possible_irqs); | ||
499 | if (xirq < 0) { | ||
500 | snd_printk(KERN_ERR PFX "unable to find a free IRQ\n"); | ||
501 | err = -EBUSY; | ||
502 | goto err_exit; | ||
503 | } | ||
504 | } | ||
505 | |||
506 | if (xdma == SNDRV_AUTO_DMA) { | ||
507 | xdma = snd_legacy_find_free_dma(possible_dmas); | ||
508 | if (xdma < 0) { | ||
509 | snd_printk(KERN_ERR PFX "unable to find a free DMA\n"); | ||
510 | err = -EBUSY; | ||
511 | goto err_exit; | ||
512 | } | ||
513 | } | ||
514 | |||
515 | if (!request_region(port[dev], 0x10, DRV_NAME)) { | ||
516 | snd_printk(KERN_ERR PFX | ||
517 | "I/O port region is already in use.\n"); | ||
518 | err = -EBUSY; | ||
519 | goto err_exit; | ||
520 | } | ||
521 | vport = devm_ioport_map(devptr, port[dev], 0x10); | ||
522 | if (!vport) { | ||
523 | snd_printk(KERN_ERR PFX | ||
524 | "I/O port cannot be iomaped.\n"); | ||
525 | err = -EBUSY; | ||
526 | goto err_unmap1; | ||
527 | } | ||
528 | |||
529 | /* to make it marked as used */ | ||
530 | if (!request_region(mss_port[dev], 4, DRV_NAME)) { | ||
531 | snd_printk(KERN_ERR PFX | ||
532 | "SC-6000 port I/O port region is already in use.\n"); | ||
533 | err = -EBUSY; | ||
534 | goto err_unmap1; | ||
535 | } | ||
536 | vmss_port = devm_ioport_map(devptr, mss_port[dev], 4); | ||
537 | if (!vport) { | ||
538 | snd_printk(KERN_ERR PFX | ||
539 | "MSS port I/O cannot be iomaped.\n"); | ||
540 | err = -EBUSY; | ||
541 | goto err_unmap2; | ||
542 | } | ||
543 | |||
544 | snd_printd("Initializing BASE[0x%lx] IRQ[%d] DMA[%d] MIRQ[%d]\n", | ||
545 | port[dev], xirq, xdma, | ||
546 | mpu_irq[dev] == SNDRV_AUTO_IRQ ? 0 : mpu_irq[dev]); | ||
547 | |||
548 | err = sc6000_init_board(vport, xirq, xdma, vmss_port, mpu_irq[dev]); | ||
549 | if (err < 0) | ||
550 | goto err_unmap2; | ||
551 | |||
552 | err = snd_ad1848_create(card, mss_port[dev] + 4, xirq, xdma, | ||
553 | AD1848_HW_DETECT, &chip); | ||
554 | if (err < 0) | ||
555 | goto err_unmap2; | ||
556 | card->private_data = chip; | ||
557 | |||
558 | err = snd_ad1848_pcm(chip, 0, NULL); | ||
559 | if (err < 0) { | ||
560 | snd_printk(KERN_ERR PFX | ||
561 | "error creating new ad1848 PCM device\n"); | ||
562 | goto err_unmap2; | ||
563 | } | ||
564 | err = snd_ad1848_mixer(chip); | ||
565 | if (err < 0) { | ||
566 | snd_printk(KERN_ERR PFX "error creating new ad1848 mixer\n"); | ||
567 | goto err_unmap2; | ||
568 | } | ||
569 | err = snd_sc6000_mixer(chip); | ||
570 | if (err < 0) { | ||
571 | snd_printk(KERN_ERR PFX "the mixer rewrite failed\n"); | ||
572 | goto err_unmap2; | ||
573 | } | ||
574 | if (snd_opl3_create(card, | ||
575 | 0x388, 0x388 + 2, | ||
576 | OPL3_HW_AUTO, 0, &opl3) < 0) { | ||
577 | snd_printk(KERN_ERR PFX "no OPL device at 0x%x-0x%x ?\n", | ||
578 | 0x388, 0x388 + 2); | ||
579 | } else { | ||
580 | err = snd_opl3_timer_new(opl3, 0, 1); | ||
581 | if (err < 0) | ||
582 | goto err_unmap2; | ||
583 | |||
584 | err = snd_opl3_hwdep_new(opl3, 0, 1, NULL); | ||
585 | if (err < 0) | ||
586 | goto err_unmap2; | ||
587 | } | ||
588 | |||
589 | if (mpu_port[dev] != SNDRV_AUTO_PORT) { | ||
590 | if (mpu_irq[dev] == SNDRV_AUTO_IRQ) | ||
591 | mpu_irq[dev] = -1; | ||
592 | if (snd_mpu401_uart_new(card, 0, | ||
593 | MPU401_HW_MPU401, | ||
594 | mpu_port[dev], 0, | ||
595 | mpu_irq[dev], IRQF_DISABLED, | ||
596 | NULL) < 0) | ||
597 | snd_printk(KERN_ERR "no MPU-401 device at 0x%lx ?\n", | ||
598 | mpu_port[dev]); | ||
599 | } | ||
600 | |||
601 | strcpy(card->driver, DRV_NAME); | ||
602 | strcpy(card->shortname, "SC-6000"); | ||
603 | sprintf(card->longname, "Gallant SC-6000 at 0x%lx, irq %d, dma %d", | ||
604 | mss_port[dev], xirq, xdma); | ||
605 | |||
606 | snd_card_set_dev(card, devptr); | ||
607 | |||
608 | err = snd_card_register(card); | ||
609 | if (err < 0) | ||
610 | goto err_unmap2; | ||
611 | |||
612 | dev_set_drvdata(devptr, card); | ||
613 | return 0; | ||
614 | |||
615 | err_unmap2: | ||
616 | release_region(mss_port[dev], 4); | ||
617 | err_unmap1: | ||
618 | release_region(port[dev], 0x10); | ||
619 | err_exit: | ||
620 | snd_card_free(card); | ||
621 | return err; | ||
622 | } | ||
623 | |||
624 | static int __devexit snd_sc6000_remove(struct device *devptr, unsigned int dev) | ||
625 | { | ||
626 | release_region(port[dev], 0x10); | ||
627 | release_region(mss_port[dev], 4); | ||
628 | |||
629 | snd_card_free(dev_get_drvdata(devptr)); | ||
630 | dev_set_drvdata(devptr, NULL); | ||
631 | return 0; | ||
632 | } | ||
633 | |||
634 | static struct isa_driver snd_sc6000_driver = { | ||
635 | .match = snd_sc6000_match, | ||
636 | .probe = snd_sc6000_probe, | ||
637 | .remove = __devexit_p(snd_sc6000_remove), | ||
638 | /* FIXME: suspend/resume */ | ||
639 | .driver = { | ||
640 | .name = DRV_NAME, | ||
641 | }, | ||
642 | }; | ||
643 | |||
644 | |||
645 | static int __init alsa_card_sc6000_init(void) | ||
646 | { | ||
647 | return isa_register_driver(&snd_sc6000_driver, SNDRV_CARDS); | ||
648 | } | ||
649 | |||
650 | static void __exit alsa_card_sc6000_exit(void) | ||
651 | { | ||
652 | isa_unregister_driver(&snd_sc6000_driver); | ||
653 | } | ||
654 | |||
655 | module_init(alsa_card_sc6000_init) | ||
656 | module_exit(alsa_card_sc6000_exit) | ||
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c index cbad2a51cbaa..1cb921d6137e 100644 --- a/sound/isa/sscape.c +++ b/sound/isa/sscape.c | |||
@@ -45,10 +45,12 @@ MODULE_LICENSE("GPL"); | |||
45 | 45 | ||
46 | static int index[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_IDX; | 46 | static int index[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_IDX; |
47 | static char* id[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_STR; | 47 | static char* id[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_STR; |
48 | static long port[SNDRV_CARDS] __devinitdata = { [0 ... (SNDRV_CARDS-1)] = SNDRV_AUTO_PORT }; | 48 | static long port[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_PORT; |
49 | static long wss_port[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_PORT; | ||
49 | static int irq[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_IRQ; | 50 | static int irq[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_IRQ; |
50 | static int mpu_irq[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_IRQ; | 51 | static int mpu_irq[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_IRQ; |
51 | static int dma[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_DMA; | 52 | static int dma[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_DMA; |
53 | static int dma2[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_DMA; | ||
52 | 54 | ||
53 | module_param_array(index, int, NULL, 0444); | 55 | module_param_array(index, int, NULL, 0444); |
54 | MODULE_PARM_DESC(index, "Index number for SoundScape soundcard"); | 56 | MODULE_PARM_DESC(index, "Index number for SoundScape soundcard"); |
@@ -59,6 +61,9 @@ MODULE_PARM_DESC(id, "Description for SoundScape card"); | |||
59 | module_param_array(port, long, NULL, 0444); | 61 | module_param_array(port, long, NULL, 0444); |
60 | MODULE_PARM_DESC(port, "Port # for SoundScape driver."); | 62 | MODULE_PARM_DESC(port, "Port # for SoundScape driver."); |
61 | 63 | ||
64 | module_param_array(wss_port, long, NULL, 0444); | ||
65 | MODULE_PARM_DESC(wss_port, "WSS Port # for SoundScape driver."); | ||
66 | |||
62 | module_param_array(irq, int, NULL, 0444); | 67 | module_param_array(irq, int, NULL, 0444); |
63 | MODULE_PARM_DESC(irq, "IRQ # for SoundScape driver."); | 68 | MODULE_PARM_DESC(irq, "IRQ # for SoundScape driver."); |
64 | 69 | ||
@@ -68,12 +73,16 @@ MODULE_PARM_DESC(mpu_irq, "MPU401 IRQ # for SoundScape driver."); | |||
68 | module_param_array(dma, int, NULL, 0444); | 73 | module_param_array(dma, int, NULL, 0444); |
69 | MODULE_PARM_DESC(dma, "DMA # for SoundScape driver."); | 74 | MODULE_PARM_DESC(dma, "DMA # for SoundScape driver."); |
70 | 75 | ||
76 | module_param_array(dma2, int, NULL, 0444); | ||
77 | MODULE_PARM_DESC(dma2, "DMA2 # for SoundScape driver."); | ||
78 | |||
71 | #ifdef CONFIG_PNP | 79 | #ifdef CONFIG_PNP |
72 | static int isa_registered; | 80 | static int isa_registered; |
73 | static int pnp_registered; | 81 | static int pnp_registered; |
74 | 82 | ||
75 | static struct pnp_card_device_id sscape_pnpids[] = { | 83 | static struct pnp_card_device_id sscape_pnpids[] = { |
76 | { .id = "ENS3081", .devs = { { "ENS0000" } } }, | 84 | { .id = "ENS3081", .devs = { { "ENS0000" } } }, /* Soundscape PnP */ |
85 | { .id = "ENS4081", .devs = { { "ENS1011" } } }, /* VIVO90 */ | ||
77 | { .id = "" } /* end */ | 86 | { .id = "" } /* end */ |
78 | }; | 87 | }; |
79 | 88 | ||
@@ -124,12 +133,21 @@ enum GA_REG { | |||
124 | #define AD1845_FREQ_SEL_MSB 0x16 | 133 | #define AD1845_FREQ_SEL_MSB 0x16 |
125 | #define AD1845_FREQ_SEL_LSB 0x17 | 134 | #define AD1845_FREQ_SEL_LSB 0x17 |
126 | 135 | ||
136 | enum card_type { | ||
137 | SSCAPE, | ||
138 | SSCAPE_PNP, | ||
139 | SSCAPE_VIVO, | ||
140 | }; | ||
141 | |||
127 | struct soundscape { | 142 | struct soundscape { |
128 | spinlock_t lock; | 143 | spinlock_t lock; |
129 | unsigned io_base; | 144 | unsigned io_base; |
145 | unsigned wss_base; | ||
130 | int codec_type; | 146 | int codec_type; |
131 | int ic_type; | 147 | int ic_type; |
148 | enum card_type type; | ||
132 | struct resource *io_res; | 149 | struct resource *io_res; |
150 | struct resource *wss_res; | ||
133 | struct snd_cs4231 *chip; | 151 | struct snd_cs4231 *chip; |
134 | struct snd_mpu401 *mpu; | 152 | struct snd_mpu401 *mpu; |
135 | struct snd_hwdep *hw; | 153 | struct snd_hwdep *hw; |
@@ -340,8 +358,9 @@ static inline void activate_ad1845_unsafe(unsigned io_base) | |||
340 | */ | 358 | */ |
341 | static void soundscape_free(struct snd_card *c) | 359 | static void soundscape_free(struct snd_card *c) |
342 | { | 360 | { |
343 | register struct soundscape *sscape = get_card_soundscape(c); | 361 | struct soundscape *sscape = get_card_soundscape(c); |
344 | release_and_free_resource(sscape->io_res); | 362 | release_and_free_resource(sscape->io_res); |
363 | release_and_free_resource(sscape->wss_res); | ||
345 | free_dma(sscape->chip->dma1); | 364 | free_dma(sscape->chip->dma1); |
346 | } | 365 | } |
347 | 366 | ||
@@ -382,7 +401,7 @@ static int obp_startup_ack(struct soundscape *s, unsigned timeout) | |||
382 | unsigned long flags; | 401 | unsigned long flags; |
383 | unsigned char x; | 402 | unsigned char x; |
384 | 403 | ||
385 | schedule_timeout(1); | 404 | schedule_timeout_uninterruptible(1); |
386 | 405 | ||
387 | spin_lock_irqsave(&s->lock, flags); | 406 | spin_lock_irqsave(&s->lock, flags); |
388 | x = inb(HOST_DATA_IO(s->io_base)); | 407 | x = inb(HOST_DATA_IO(s->io_base)); |
@@ -409,7 +428,7 @@ static int host_startup_ack(struct soundscape *s, unsigned timeout) | |||
409 | unsigned long flags; | 428 | unsigned long flags; |
410 | unsigned char x; | 429 | unsigned char x; |
411 | 430 | ||
412 | schedule_timeout(1); | 431 | schedule_timeout_uninterruptible(1); |
413 | 432 | ||
414 | spin_lock_irqsave(&s->lock, flags); | 433 | spin_lock_irqsave(&s->lock, flags); |
415 | x = inb(HOST_DATA_IO(s->io_base)); | 434 | x = inb(HOST_DATA_IO(s->io_base)); |
@@ -522,7 +541,7 @@ static int upload_dma_data(struct soundscape *s, | |||
522 | ret = -EAGAIN; | 541 | ret = -EAGAIN; |
523 | } | 542 | } |
524 | 543 | ||
525 | _release_dma: | 544 | _release_dma: |
526 | /* | 545 | /* |
527 | * NOTE!!! We are NOT holding any spinlocks at this point !!! | 546 | * NOTE!!! We are NOT holding any spinlocks at this point !!! |
528 | */ | 547 | */ |
@@ -802,6 +821,7 @@ static int __devinit detect_sscape(struct soundscape *s) | |||
802 | unsigned long flags; | 821 | unsigned long flags; |
803 | unsigned d; | 822 | unsigned d; |
804 | int retval = 0; | 823 | int retval = 0; |
824 | int codec = s->wss_base; | ||
805 | 825 | ||
806 | spin_lock_irqsave(&s->lock, flags); | 826 | spin_lock_irqsave(&s->lock, flags); |
807 | 827 | ||
@@ -833,9 +853,27 @@ static int __devinit detect_sscape(struct soundscape *s) | |||
833 | outb(0xfe, ODIE_ADDR_IO(s->io_base)); | 853 | outb(0xfe, ODIE_ADDR_IO(s->io_base)); |
834 | if ((inb(ODIE_ADDR_IO(s->io_base)) & 0x9f) != 0x0e) | 854 | if ((inb(ODIE_ADDR_IO(s->io_base)) & 0x9f) != 0x0e) |
835 | goto _done; | 855 | goto _done; |
836 | if ((inb(ODIE_DATA_IO(s->io_base)) & 0x9f) != 0x0e) | 856 | |
857 | outb(0xfe, ODIE_ADDR_IO(s->io_base)); | ||
858 | d = inb(ODIE_DATA_IO(s->io_base)); | ||
859 | if (s->type != SSCAPE_VIVO && (d & 0x9f) != 0x0e) | ||
837 | goto _done; | 860 | goto _done; |
838 | 861 | ||
862 | d = sscape_read_unsafe(s->io_base, GA_HMCTL_REG) & 0x3f; | ||
863 | sscape_write_unsafe(s->io_base, GA_HMCTL_REG, d | 0xc0); | ||
864 | |||
865 | if (s->type == SSCAPE_VIVO) | ||
866 | codec += 4; | ||
867 | /* wait for WSS codec */ | ||
868 | for (d = 0; d < 500; d++) { | ||
869 | if ((inb(codec) & 0x80) == 0) | ||
870 | break; | ||
871 | spin_unlock_irqrestore(&s->lock, flags); | ||
872 | msleep(1); | ||
873 | spin_lock_irqsave(&s->lock, flags); | ||
874 | } | ||
875 | snd_printd(KERN_INFO "init delay = %d ms\n", d); | ||
876 | |||
839 | /* | 877 | /* |
840 | * SoundScape successfully detected! | 878 | * SoundScape successfully detected! |
841 | */ | 879 | */ |
@@ -995,21 +1033,23 @@ static void ad1845_capture_format(struct snd_cs4231 * chip, struct snd_pcm_hw_pa | |||
995 | * try to support at least some of the extra bits by overriding | 1033 | * try to support at least some of the extra bits by overriding |
996 | * some of the CS4231 callback. | 1034 | * some of the CS4231 callback. |
997 | */ | 1035 | */ |
998 | static int __devinit create_ad1845(struct snd_card *card, unsigned port, int irq, int dma1) | 1036 | static int __devinit create_ad1845(struct snd_card *card, unsigned port, |
1037 | int irq, int dma1, int dma2) | ||
999 | { | 1038 | { |
1000 | register struct soundscape *sscape = get_card_soundscape(card); | 1039 | register struct soundscape *sscape = get_card_soundscape(card); |
1001 | struct snd_cs4231 *chip; | 1040 | struct snd_cs4231 *chip; |
1002 | int err; | 1041 | int err; |
1003 | 1042 | ||
1004 | #define CS4231_SHARE_HARDWARE (CS4231_HWSHARE_DMA1 | CS4231_HWSHARE_DMA2) | 1043 | if (sscape->type == SSCAPE_VIVO) |
1005 | /* | 1044 | port += 4; |
1006 | * The AD1845 PCM device is only half-duplex, and so | 1045 | |
1007 | * we only give it one DMA channel ... | 1046 | if (dma1 == dma2) |
1008 | */ | 1047 | dma2 = -1; |
1009 | if ((err = snd_cs4231_create(card, | 1048 | |
1010 | port, -1, irq, dma1, dma1, | 1049 | err = snd_cs4231_create(card, |
1011 | CS4231_HW_DETECT, | 1050 | port, -1, irq, dma1, dma2, |
1012 | CS4231_HWSHARE_DMA1, &chip)) == 0) { | 1051 | CS4231_HW_DETECT, CS4231_HWSHARE_DMA1, &chip); |
1052 | if (!err) { | ||
1013 | unsigned long flags; | 1053 | unsigned long flags; |
1014 | struct snd_pcm *pcm; | 1054 | struct snd_pcm *pcm; |
1015 | 1055 | ||
@@ -1031,49 +1071,72 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port, int irq | |||
1031 | snd_cs4231_mce_down(chip); | 1071 | snd_cs4231_mce_down(chip); |
1032 | */ | 1072 | */ |
1033 | 1073 | ||
1034 | /* | 1074 | if (sscape->type != SSCAPE_VIVO) { |
1035 | * The input clock frequency on the SoundScape must | 1075 | int val; |
1036 | * be 14.31818 MHz, because we must set this register | 1076 | /* |
1037 | * to get the playback to sound correct ... | 1077 | * The input clock frequency on the SoundScape must |
1038 | */ | 1078 | * be 14.31818 MHz, because we must set this register |
1039 | snd_cs4231_mce_up(chip); | 1079 | * to get the playback to sound correct ... |
1040 | spin_lock_irqsave(&chip->reg_lock, flags); | 1080 | */ |
1041 | snd_cs4231_out(chip, AD1845_CRYS_CLOCK_SEL, 0x20); | 1081 | snd_cs4231_mce_up(chip); |
1042 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 1082 | spin_lock_irqsave(&chip->reg_lock, flags); |
1043 | snd_cs4231_mce_down(chip); | 1083 | snd_cs4231_out(chip, AD1845_CRYS_CLOCK_SEL, 0x20); |
1084 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
1085 | snd_cs4231_mce_down(chip); | ||
1044 | 1086 | ||
1045 | /* | 1087 | /* |
1046 | * More custom configuration: | 1088 | * More custom configuration: |
1047 | * a) select "mode 2", and provide a current drive of 8 mA | 1089 | * a) select "mode 2" and provide a current drive of 8mA |
1048 | * b) enable frequency selection (for capture/playback) | 1090 | * b) enable frequency selection (for capture/playback) |
1049 | */ | 1091 | */ |
1050 | spin_lock_irqsave(&chip->reg_lock, flags); | 1092 | spin_lock_irqsave(&chip->reg_lock, flags); |
1051 | snd_cs4231_out(chip, CS4231_MISC_INFO, (CS4231_MODE2 | 0x10)); | 1093 | snd_cs4231_out(chip, CS4231_MISC_INFO, |
1052 | snd_cs4231_out(chip, AD1845_PWR_DOWN_CTRL, snd_cs4231_in(chip, AD1845_PWR_DOWN_CTRL) | AD1845_FREQ_SEL_ENABLE); | 1094 | CS4231_MODE2 | 0x10); |
1053 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 1095 | val = snd_cs4231_in(chip, AD1845_PWR_DOWN_CTRL); |
1096 | snd_cs4231_out(chip, AD1845_PWR_DOWN_CTRL, | ||
1097 | val | AD1845_FREQ_SEL_ENABLE); | ||
1098 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
1099 | } | ||
1054 | 1100 | ||
1055 | if ((err = snd_cs4231_pcm(chip, 0, &pcm)) < 0) { | 1101 | err = snd_cs4231_pcm(chip, 0, &pcm); |
1056 | snd_printk(KERN_ERR "sscape: No PCM device for AD1845 chip\n"); | 1102 | if (err < 0) { |
1103 | snd_printk(KERN_ERR "sscape: No PCM device " | ||
1104 | "for AD1845 chip\n"); | ||
1057 | goto _error; | 1105 | goto _error; |
1058 | } | 1106 | } |
1059 | 1107 | ||
1060 | if ((err = snd_cs4231_mixer(chip)) < 0) { | 1108 | err = snd_cs4231_mixer(chip); |
1061 | snd_printk(KERN_ERR "sscape: No mixer device for AD1845 chip\n"); | 1109 | if (err < 0) { |
1110 | snd_printk(KERN_ERR "sscape: No mixer device " | ||
1111 | "for AD1845 chip\n"); | ||
1062 | goto _error; | 1112 | goto _error; |
1063 | } | 1113 | } |
1064 | 1114 | err = snd_cs4231_timer(chip, 0, NULL); | |
1065 | if ((err = snd_ctl_add(card, snd_ctl_new1(&midi_mixer_ctl, chip))) < 0) { | 1115 | if (err < 0) { |
1066 | snd_printk(KERN_ERR "sscape: Could not create MIDI mixer control\n"); | 1116 | snd_printk(KERN_ERR "sscape: No timer device " |
1117 | "for AD1845 chip\n"); | ||
1067 | goto _error; | 1118 | goto _error; |
1068 | } | 1119 | } |
1069 | 1120 | ||
1121 | if (sscape->type != SSCAPE_VIVO) { | ||
1122 | err = snd_ctl_add(card, | ||
1123 | snd_ctl_new1(&midi_mixer_ctl, chip)); | ||
1124 | if (err < 0) { | ||
1125 | snd_printk(KERN_ERR "sscape: Could not create " | ||
1126 | "MIDI mixer control\n"); | ||
1127 | goto _error; | ||
1128 | } | ||
1129 | chip->set_playback_format = ad1845_playback_format; | ||
1130 | chip->set_capture_format = ad1845_capture_format; | ||
1131 | } | ||
1132 | |||
1070 | strcpy(card->driver, "SoundScape"); | 1133 | strcpy(card->driver, "SoundScape"); |
1071 | strcpy(card->shortname, pcm->name); | 1134 | strcpy(card->shortname, pcm->name); |
1072 | snprintf(card->longname, sizeof(card->longname), | 1135 | snprintf(card->longname, sizeof(card->longname), |
1073 | "%s at 0x%lx, IRQ %d, DMA %d\n", | 1136 | "%s at 0x%lx, IRQ %d, DMA1 %d, DMA2 %d\n", |
1074 | pcm->name, chip->port, chip->irq, chip->dma1); | 1137 | pcm->name, chip->port, chip->irq, |
1075 | chip->set_playback_format = ad1845_playback_format; | 1138 | chip->dma1, chip->dma2); |
1076 | chip->set_capture_format = ad1845_capture_format; | 1139 | |
1077 | sscape->chip = chip; | 1140 | sscape->chip = chip; |
1078 | } | 1141 | } |
1079 | 1142 | ||
@@ -1086,15 +1149,15 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port, int irq | |||
1086 | * Create an ALSA soundcard entry for the SoundScape, using | 1149 | * Create an ALSA soundcard entry for the SoundScape, using |
1087 | * the given list of port, IRQ and DMA resources. | 1150 | * the given list of port, IRQ and DMA resources. |
1088 | */ | 1151 | */ |
1089 | static int __devinit create_sscape(int dev, struct snd_card **rcardp) | 1152 | static int __devinit create_sscape(int dev, struct snd_card *card) |
1090 | { | 1153 | { |
1091 | struct snd_card *card; | 1154 | struct soundscape *sscape = get_card_soundscape(card); |
1092 | register struct soundscape *sscape; | 1155 | unsigned dma_cfg; |
1093 | register unsigned dma_cfg; | ||
1094 | unsigned irq_cfg; | 1156 | unsigned irq_cfg; |
1095 | unsigned mpu_irq_cfg; | 1157 | unsigned mpu_irq_cfg; |
1096 | unsigned xport; | 1158 | unsigned xport; |
1097 | struct resource *io_res; | 1159 | struct resource *io_res; |
1160 | struct resource *wss_res; | ||
1098 | unsigned long flags; | 1161 | unsigned long flags; |
1099 | int err; | 1162 | int err; |
1100 | 1163 | ||
@@ -1118,61 +1181,69 @@ static int __devinit create_sscape(int dev, struct snd_card **rcardp) | |||
1118 | * Grab IO ports that we will need to probe so that we | 1181 | * Grab IO ports that we will need to probe so that we |
1119 | * can detect and control this hardware ... | 1182 | * can detect and control this hardware ... |
1120 | */ | 1183 | */ |
1121 | if ((io_res = request_region(xport, 8, "SoundScape")) == NULL) { | 1184 | io_res = request_region(xport, 8, "SoundScape"); |
1185 | if (!io_res) { | ||
1122 | snd_printk(KERN_ERR "sscape: can't grab port 0x%x\n", xport); | 1186 | snd_printk(KERN_ERR "sscape: can't grab port 0x%x\n", xport); |
1123 | return -EBUSY; | 1187 | return -EBUSY; |
1124 | } | 1188 | } |
1189 | wss_res = NULL; | ||
1190 | if (sscape->type == SSCAPE_VIVO) { | ||
1191 | wss_res = request_region(wss_port[dev], 4, "SoundScape"); | ||
1192 | if (!wss_res) { | ||
1193 | snd_printk(KERN_ERR "sscape: can't grab port 0x%lx\n", | ||
1194 | wss_port[dev]); | ||
1195 | err = -EBUSY; | ||
1196 | goto _release_region; | ||
1197 | } | ||
1198 | } | ||
1125 | 1199 | ||
1126 | /* | 1200 | /* |
1127 | * Grab both DMA channels (OK, only one for now) ... | 1201 | * Grab one DMA channel ... |
1128 | */ | 1202 | */ |
1129 | if ((err = request_dma(dma[dev], "SoundScape")) < 0) { | 1203 | err = request_dma(dma[dev], "SoundScape"); |
1204 | if (err < 0) { | ||
1130 | snd_printk(KERN_ERR "sscape: can't grab DMA %d\n", dma[dev]); | 1205 | snd_printk(KERN_ERR "sscape: can't grab DMA %d\n", dma[dev]); |
1131 | goto _release_region; | 1206 | goto _release_region; |
1132 | } | 1207 | } |
1133 | 1208 | ||
1134 | /* | ||
1135 | * Create a new ALSA sound card entry, in anticipation | ||
1136 | * of detecting our hardware ... | ||
1137 | */ | ||
1138 | if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE, | ||
1139 | sizeof(struct soundscape))) == NULL) { | ||
1140 | err = -ENOMEM; | ||
1141 | goto _release_dma; | ||
1142 | } | ||
1143 | |||
1144 | sscape = get_card_soundscape(card); | ||
1145 | spin_lock_init(&sscape->lock); | 1209 | spin_lock_init(&sscape->lock); |
1146 | spin_lock_init(&sscape->fwlock); | 1210 | spin_lock_init(&sscape->fwlock); |
1147 | sscape->io_res = io_res; | 1211 | sscape->io_res = io_res; |
1212 | sscape->wss_res = wss_res; | ||
1148 | sscape->io_base = xport; | 1213 | sscape->io_base = xport; |
1214 | sscape->wss_base = wss_port[dev]; | ||
1149 | 1215 | ||
1150 | if (!detect_sscape(sscape)) { | 1216 | if (!detect_sscape(sscape)) { |
1151 | printk(KERN_ERR "sscape: hardware not detected at 0x%x\n", sscape->io_base); | 1217 | printk(KERN_ERR "sscape: hardware not detected at 0x%x\n", sscape->io_base); |
1152 | err = -ENODEV; | 1218 | err = -ENODEV; |
1153 | goto _release_card; | 1219 | goto _release_dma; |
1154 | } | 1220 | } |
1155 | 1221 | ||
1156 | printk(KERN_INFO "sscape: hardware detected at 0x%x, using IRQ %d, DMA %d\n", | 1222 | printk(KERN_INFO "sscape: hardware detected at 0x%x, using IRQ %d, DMA %d\n", |
1157 | sscape->io_base, irq[dev], dma[dev]); | 1223 | sscape->io_base, irq[dev], dma[dev]); |
1158 | 1224 | ||
1159 | /* | 1225 | if (sscape->type != SSCAPE_VIVO) { |
1160 | * Now create the hardware-specific device so that we can | 1226 | /* |
1161 | * load the microcode into the on-board processor. | 1227 | * Now create the hardware-specific device so that we can |
1162 | * We cannot use the MPU-401 MIDI system until this firmware | 1228 | * load the microcode into the on-board processor. |
1163 | * has been loaded into the card. | 1229 | * We cannot use the MPU-401 MIDI system until this firmware |
1164 | */ | 1230 | * has been loaded into the card. |
1165 | if ((err = snd_hwdep_new(card, "MC68EC000", 0, &(sscape->hw))) < 0) { | 1231 | */ |
1166 | printk(KERN_ERR "sscape: Failed to create firmware device\n"); | 1232 | err = snd_hwdep_new(card, "MC68EC000", 0, &(sscape->hw)); |
1167 | goto _release_card; | 1233 | if (err < 0) { |
1234 | printk(KERN_ERR "sscape: Failed to create " | ||
1235 | "firmware device\n"); | ||
1236 | goto _release_dma; | ||
1237 | } | ||
1238 | strlcpy(sscape->hw->name, "SoundScape M68K", | ||
1239 | sizeof(sscape->hw->name)); | ||
1240 | sscape->hw->name[sizeof(sscape->hw->name) - 1] = '\0'; | ||
1241 | sscape->hw->iface = SNDRV_HWDEP_IFACE_SSCAPE; | ||
1242 | sscape->hw->ops.open = sscape_hw_open; | ||
1243 | sscape->hw->ops.release = sscape_hw_release; | ||
1244 | sscape->hw->ops.ioctl = sscape_hw_ioctl; | ||
1245 | sscape->hw->private_data = sscape; | ||
1168 | } | 1246 | } |
1169 | strlcpy(sscape->hw->name, "SoundScape M68K", sizeof(sscape->hw->name)); | ||
1170 | sscape->hw->name[sizeof(sscape->hw->name) - 1] = '\0'; | ||
1171 | sscape->hw->iface = SNDRV_HWDEP_IFACE_SSCAPE; | ||
1172 | sscape->hw->ops.open = sscape_hw_open; | ||
1173 | sscape->hw->ops.release = sscape_hw_release; | ||
1174 | sscape->hw->ops.ioctl = sscape_hw_ioctl; | ||
1175 | sscape->hw->private_data = sscape; | ||
1176 | 1247 | ||
1177 | /* | 1248 | /* |
1178 | * Tell the on-board devices where their resources are (I think - | 1249 | * Tell the on-board devices where their resources are (I think - |
@@ -1197,7 +1268,8 @@ static int __devinit create_sscape(int dev, struct snd_card **rcardp) | |||
1197 | sscape_write_unsafe(sscape->io_base, | 1268 | sscape_write_unsafe(sscape->io_base, |
1198 | GA_INTCFG_REG, 0xf0 | (mpu_irq_cfg << 2) | mpu_irq_cfg); | 1269 | GA_INTCFG_REG, 0xf0 | (mpu_irq_cfg << 2) | mpu_irq_cfg); |
1199 | sscape_write_unsafe(sscape->io_base, | 1270 | sscape_write_unsafe(sscape->io_base, |
1200 | GA_CDCFG_REG, 0x09 | DMA_8BIT | (dma[dev] << 4) | (irq_cfg << 1)); | 1271 | GA_CDCFG_REG, 0x09 | DMA_8BIT |
1272 | | (dma[dev] << 4) | (irq_cfg << 1)); | ||
1201 | 1273 | ||
1202 | spin_unlock_irqrestore(&sscape->lock, flags); | 1274 | spin_unlock_irqrestore(&sscape->lock, flags); |
1203 | 1275 | ||
@@ -1205,30 +1277,37 @@ static int __devinit create_sscape(int dev, struct snd_card **rcardp) | |||
1205 | * We have now enabled the codec chip, and so we should | 1277 | * We have now enabled the codec chip, and so we should |
1206 | * detect the AD1845 device ... | 1278 | * detect the AD1845 device ... |
1207 | */ | 1279 | */ |
1208 | if ((err = create_ad1845(card, CODEC_IO(xport), irq[dev], dma[dev])) < 0) { | 1280 | err = create_ad1845(card, wss_port[dev], irq[dev], |
1209 | printk(KERN_ERR "sscape: No AD1845 device at 0x%x, IRQ %d\n", | 1281 | dma[dev], dma2[dev]); |
1210 | CODEC_IO(xport), irq[dev]); | 1282 | if (err < 0) { |
1211 | goto _release_card; | 1283 | printk(KERN_ERR "sscape: No AD1845 device at 0x%lx, IRQ %d\n", |
1284 | wss_port[dev], irq[dev]); | ||
1285 | goto _release_dma; | ||
1212 | } | 1286 | } |
1213 | #define MIDI_DEVNUM 0 | 1287 | #define MIDI_DEVNUM 0 |
1214 | if ((err = create_mpu401(card, MIDI_DEVNUM, MPU401_IO(xport), mpu_irq[dev])) < 0) { | 1288 | if (sscape->type != SSCAPE_VIVO) { |
1215 | printk(KERN_ERR "sscape: Failed to create MPU-401 device at 0x%x\n", | 1289 | err = create_mpu401(card, MIDI_DEVNUM, |
1216 | MPU401_IO(xport)); | 1290 | MPU401_IO(xport), mpu_irq[dev]); |
1217 | goto _release_card; | 1291 | if (err < 0) { |
1218 | } | 1292 | printk(KERN_ERR "sscape: Failed to create " |
1293 | "MPU-401 device at 0x%x\n", | ||
1294 | MPU401_IO(xport)); | ||
1295 | goto _release_dma; | ||
1296 | } | ||
1219 | 1297 | ||
1220 | /* | 1298 | /* |
1221 | * Enable the master IRQ ... | 1299 | * Enable the master IRQ ... |
1222 | */ | 1300 | */ |
1223 | sscape_write(sscape, GA_INTENA_REG, 0x80); | 1301 | sscape_write(sscape, GA_INTENA_REG, 0x80); |
1224 | 1302 | ||
1225 | /* | 1303 | /* |
1226 | * Initialize mixer | 1304 | * Initialize mixer |
1227 | */ | 1305 | */ |
1228 | sscape->midi_vol = 0; | 1306 | sscape->midi_vol = 0; |
1229 | host_write_ctrl_unsafe(sscape->io_base, CMD_SET_MIDI_VOL, 100); | 1307 | host_write_ctrl_unsafe(sscape->io_base, CMD_SET_MIDI_VOL, 100); |
1230 | host_write_ctrl_unsafe(sscape->io_base, 0, 100); | 1308 | host_write_ctrl_unsafe(sscape->io_base, 0, 100); |
1231 | host_write_ctrl_unsafe(sscape->io_base, CMD_XXX_MIDI_VOL, 100); | 1309 | host_write_ctrl_unsafe(sscape->io_base, CMD_XXX_MIDI_VOL, 100); |
1310 | } | ||
1232 | 1311 | ||
1233 | /* | 1312 | /* |
1234 | * Now that we have successfully created this sound card, | 1313 | * Now that we have successfully created this sound card, |
@@ -1237,17 +1316,14 @@ static int __devinit create_sscape(int dev, struct snd_card **rcardp) | |||
1237 | * function now that our "constructor" has completed. | 1316 | * function now that our "constructor" has completed. |
1238 | */ | 1317 | */ |
1239 | card->private_free = soundscape_free; | 1318 | card->private_free = soundscape_free; |
1240 | *rcardp = card; | ||
1241 | 1319 | ||
1242 | return 0; | 1320 | return 0; |
1243 | 1321 | ||
1244 | _release_card: | 1322 | _release_dma: |
1245 | snd_card_free(card); | ||
1246 | |||
1247 | _release_dma: | ||
1248 | free_dma(dma[dev]); | 1323 | free_dma(dma[dev]); |
1249 | 1324 | ||
1250 | _release_region: | 1325 | _release_region: |
1326 | release_and_free_resource(wss_res); | ||
1251 | release_and_free_resource(io_res); | 1327 | release_and_free_resource(io_res); |
1252 | 1328 | ||
1253 | return err; | 1329 | return err; |
@@ -1276,19 +1352,33 @@ static int __devinit snd_sscape_match(struct device *pdev, unsigned int i) | |||
1276 | static int __devinit snd_sscape_probe(struct device *pdev, unsigned int dev) | 1352 | static int __devinit snd_sscape_probe(struct device *pdev, unsigned int dev) |
1277 | { | 1353 | { |
1278 | struct snd_card *card; | 1354 | struct snd_card *card; |
1355 | struct soundscape *sscape; | ||
1279 | int ret; | 1356 | int ret; |
1280 | 1357 | ||
1358 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, | ||
1359 | sizeof(struct soundscape)); | ||
1360 | if (!card) | ||
1361 | return -ENOMEM; | ||
1362 | |||
1363 | sscape = get_card_soundscape(card); | ||
1364 | sscape->type = SSCAPE; | ||
1365 | |||
1281 | dma[dev] &= 0x03; | 1366 | dma[dev] &= 0x03; |
1282 | ret = create_sscape(dev, &card); | 1367 | ret = create_sscape(dev, card); |
1283 | if (ret < 0) | 1368 | if (ret < 0) |
1284 | return ret; | 1369 | goto _release_card; |
1370 | |||
1285 | snd_card_set_dev(card, pdev); | 1371 | snd_card_set_dev(card, pdev); |
1286 | if ((ret = snd_card_register(card)) < 0) { | 1372 | if ((ret = snd_card_register(card)) < 0) { |
1287 | printk(KERN_ERR "sscape: Failed to register sound card\n"); | 1373 | printk(KERN_ERR "sscape: Failed to register sound card\n"); |
1288 | return ret; | 1374 | goto _release_card; |
1289 | } | 1375 | } |
1290 | dev_set_drvdata(pdev, card); | 1376 | dev_set_drvdata(pdev, card); |
1291 | return 0; | 1377 | return 0; |
1378 | |||
1379 | _release_card: | ||
1380 | snd_card_free(card); | ||
1381 | return ret; | ||
1292 | } | 1382 | } |
1293 | 1383 | ||
1294 | static int __devexit snd_sscape_remove(struct device *devptr, unsigned int dev) | 1384 | static int __devexit snd_sscape_remove(struct device *devptr, unsigned int dev) |
@@ -1325,6 +1415,7 @@ static int __devinit sscape_pnp_detect(struct pnp_card_link *pcard, | |||
1325 | static int idx = 0; | 1415 | static int idx = 0; |
1326 | struct pnp_dev *dev; | 1416 | struct pnp_dev *dev; |
1327 | struct snd_card *card; | 1417 | struct snd_card *card; |
1418 | struct soundscape *sscape; | ||
1328 | int ret; | 1419 | int ret; |
1329 | 1420 | ||
1330 | /* | 1421 | /* |
@@ -1366,26 +1457,55 @@ static int __devinit sscape_pnp_detect(struct pnp_card_link *pcard, | |||
1366 | } | 1457 | } |
1367 | 1458 | ||
1368 | /* | 1459 | /* |
1460 | * Create a new ALSA sound card entry, in anticipation | ||
1461 | * of detecting our hardware ... | ||
1462 | */ | ||
1463 | card = snd_card_new(index[idx], id[idx], THIS_MODULE, | ||
1464 | sizeof(struct soundscape)); | ||
1465 | if (!card) | ||
1466 | return -ENOMEM; | ||
1467 | |||
1468 | sscape = get_card_soundscape(card); | ||
1469 | |||
1470 | /* | ||
1471 | * Identify card model ... | ||
1472 | */ | ||
1473 | if (!strncmp("ENS4081", pid->id, 7)) | ||
1474 | sscape->type = SSCAPE_VIVO; | ||
1475 | else | ||
1476 | sscape->type = SSCAPE_PNP; | ||
1477 | |||
1478 | /* | ||
1369 | * Read the correct parameters off the ISA PnP bus ... | 1479 | * Read the correct parameters off the ISA PnP bus ... |
1370 | */ | 1480 | */ |
1371 | port[idx] = pnp_port_start(dev, 0); | 1481 | port[idx] = pnp_port_start(dev, 0); |
1372 | irq[idx] = pnp_irq(dev, 0); | 1482 | irq[idx] = pnp_irq(dev, 0); |
1373 | mpu_irq[idx] = pnp_irq(dev, 1); | 1483 | mpu_irq[idx] = pnp_irq(dev, 1); |
1374 | dma[idx] = pnp_dma(dev, 0) & 0x03; | 1484 | dma[idx] = pnp_dma(dev, 0) & 0x03; |
1485 | if (sscape->type == SSCAPE_PNP) { | ||
1486 | dma2[idx] = dma[idx]; | ||
1487 | wss_port[idx] = CODEC_IO(port[idx]); | ||
1488 | } else { | ||
1489 | wss_port[idx] = pnp_port_start(dev, 1); | ||
1490 | dma2[idx] = pnp_dma(dev, 1); | ||
1491 | } | ||
1375 | 1492 | ||
1376 | ret = create_sscape(idx, &card); | 1493 | ret = create_sscape(idx, card); |
1377 | if (ret < 0) | 1494 | if (ret < 0) |
1378 | return ret; | 1495 | goto _release_card; |
1496 | |||
1379 | snd_card_set_dev(card, &pcard->card->dev); | 1497 | snd_card_set_dev(card, &pcard->card->dev); |
1380 | if ((ret = snd_card_register(card)) < 0) { | 1498 | if ((ret = snd_card_register(card)) < 0) { |
1381 | printk(KERN_ERR "sscape: Failed to register sound card\n"); | 1499 | printk(KERN_ERR "sscape: Failed to register sound card\n"); |
1382 | snd_card_free(card); | 1500 | goto _release_card; |
1383 | return ret; | ||
1384 | } | 1501 | } |
1385 | 1502 | ||
1386 | pnp_set_card_drvdata(pcard, card); | 1503 | pnp_set_card_drvdata(pcard, card); |
1387 | ++idx; | 1504 | ++idx; |
1505 | return 0; | ||
1388 | 1506 | ||
1507 | _release_card: | ||
1508 | snd_card_free(card); | ||
1389 | return ret; | 1509 | return ret; |
1390 | } | 1510 | } |
1391 | 1511 | ||
diff --git a/sound/isa/wavefront/Makefile b/sound/isa/wavefront/Makefile index b4cb28422db0..601bdddd44d0 100644 --- a/sound/isa/wavefront/Makefile +++ b/sound/isa/wavefront/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-wavefront-objs := wavefront.o wavefront_fx.o wavefront_synth.o wavefront_midi.o | 6 | snd-wavefront-objs := wavefront.o wavefront_fx.o wavefront_synth.o wavefront_midi.o |
diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c index bacc51c86587..a1ebb7c5c684 100644 --- a/sound/isa/wavefront/wavefront_synth.c +++ b/sound/isa/wavefront/wavefront_synth.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
28 | #include <linux/time.h> | 28 | #include <linux/time.h> |
29 | #include <linux/wait.h> | 29 | #include <linux/wait.h> |
30 | #include <linux/firmware.h> | ||
30 | #include <linux/moduleparam.h> | 31 | #include <linux/moduleparam.h> |
31 | #include <sound/core.h> | 32 | #include <sound/core.h> |
32 | #include <sound/snd_wavefront.h> | 33 | #include <sound/snd_wavefront.h> |
@@ -53,9 +54,8 @@ static int debug_default = 0; /* you can set this to control debugging | |||
53 | 54 | ||
54 | /* XXX this needs to be made firmware and hardware version dependent */ | 55 | /* XXX this needs to be made firmware and hardware version dependent */ |
55 | 56 | ||
56 | static char *ospath = "/etc/sound/wavefront.os"; /* where to find a processed | 57 | #define DEFAULT_OSPATH "wavefront.os" |
57 | version of the WaveFront OS | 58 | static char *ospath = DEFAULT_OSPATH; /* the firmware file name */ |
58 | */ | ||
59 | 59 | ||
60 | static int wait_usecs = 150; /* This magic number seems to give pretty optimal | 60 | static int wait_usecs = 150; /* This magic number seems to give pretty optimal |
61 | throughput based on my limited experimentation. | 61 | throughput based on my limited experimentation. |
@@ -97,7 +97,7 @@ MODULE_PARM_DESC(sleep_interval, "how long to sleep when waiting for reply"); | |||
97 | module_param(sleep_tries, int, 0444); | 97 | module_param(sleep_tries, int, 0444); |
98 | MODULE_PARM_DESC(sleep_tries, "how many times to try sleeping during a wait"); | 98 | MODULE_PARM_DESC(sleep_tries, "how many times to try sleeping during a wait"); |
99 | module_param(ospath, charp, 0444); | 99 | module_param(ospath, charp, 0444); |
100 | MODULE_PARM_DESC(ospath, "full pathname to processed ICS2115 OS firmware"); | 100 | MODULE_PARM_DESC(ospath, "pathname to processed ICS2115 OS firmware"); |
101 | module_param(reset_time, int, 0444); | 101 | module_param(reset_time, int, 0444); |
102 | MODULE_PARM_DESC(reset_time, "how long to wait for a reset to take effect"); | 102 | MODULE_PARM_DESC(reset_time, "how long to wait for a reset to take effect"); |
103 | module_param(ramcheck_time, int, 0444); | 103 | module_param(ramcheck_time, int, 0444); |
@@ -1768,7 +1768,7 @@ snd_wavefront_interrupt_bits (int irq) | |||
1768 | 1768 | ||
1769 | static void __devinit | 1769 | static void __devinit |
1770 | wavefront_should_cause_interrupt (snd_wavefront_t *dev, | 1770 | wavefront_should_cause_interrupt (snd_wavefront_t *dev, |
1771 | int val, int port, int timeout) | 1771 | int val, int port, unsigned long timeout) |
1772 | 1772 | ||
1773 | { | 1773 | { |
1774 | wait_queue_t wait; | 1774 | wait_queue_t wait; |
@@ -1779,11 +1779,9 @@ wavefront_should_cause_interrupt (snd_wavefront_t *dev, | |||
1779 | dev->irq_ok = 0; | 1779 | dev->irq_ok = 0; |
1780 | outb (val,port); | 1780 | outb (val,port); |
1781 | spin_unlock_irq(&dev->irq_lock); | 1781 | spin_unlock_irq(&dev->irq_lock); |
1782 | while (1) { | 1782 | while (!dev->irq_ok && time_before(jiffies, timeout)) { |
1783 | if ((timeout = schedule_timeout(timeout)) == 0) | 1783 | schedule_timeout_uninterruptible(1); |
1784 | return; | 1784 | barrier(); |
1785 | if (dev->irq_ok) | ||
1786 | return; | ||
1787 | } | 1785 | } |
1788 | } | 1786 | } |
1789 | 1787 | ||
@@ -1938,111 +1936,75 @@ wavefront_reset_to_cleanliness (snd_wavefront_t *dev) | |||
1938 | return (1); | 1936 | return (1); |
1939 | } | 1937 | } |
1940 | 1938 | ||
1941 | #include <linux/fs.h> | ||
1942 | #include <linux/mm.h> | ||
1943 | #include <linux/slab.h> | ||
1944 | #include <linux/unistd.h> | ||
1945 | #include <linux/syscalls.h> | ||
1946 | #include <asm/uaccess.h> | ||
1947 | |||
1948 | |||
1949 | static int __devinit | 1939 | static int __devinit |
1950 | wavefront_download_firmware (snd_wavefront_t *dev, char *path) | 1940 | wavefront_download_firmware (snd_wavefront_t *dev, char *path) |
1951 | 1941 | ||
1952 | { | 1942 | { |
1953 | unsigned char section[WF_SECTION_MAX]; | 1943 | unsigned char *buf; |
1954 | signed char section_length; /* yes, just a char; max value is WF_SECTION_MAX */ | 1944 | int len, err; |
1955 | int section_cnt_downloaded = 0; | 1945 | int section_cnt_downloaded = 0; |
1956 | int fd; | 1946 | const struct firmware *firmware; |
1957 | int c; | ||
1958 | int i; | ||
1959 | mm_segment_t fs; | ||
1960 | |||
1961 | /* This tries to be a bit cleverer than the stuff Alan Cox did for | ||
1962 | the generic sound firmware, in that it actually knows | ||
1963 | something about the structure of the Motorola firmware. In | ||
1964 | particular, it uses a version that has been stripped of the | ||
1965 | 20K of useless header information, and had section lengths | ||
1966 | added, making it possible to load the entire OS without any | ||
1967 | [kv]malloc() activity, since the longest entity we ever read is | ||
1968 | 42 bytes (well, WF_SECTION_MAX) long. | ||
1969 | */ | ||
1970 | |||
1971 | fs = get_fs(); | ||
1972 | set_fs (get_ds()); | ||
1973 | 1947 | ||
1974 | if ((fd = sys_open ((char __user *) path, 0, 0)) < 0) { | 1948 | err = request_firmware(&firmware, path, dev->card->dev); |
1975 | snd_printk ("Unable to load \"%s\".\n", | 1949 | if (err < 0) { |
1976 | path); | 1950 | snd_printk(KERN_ERR "firmware (%s) download failed!!!\n", path); |
1977 | return 1; | 1951 | return 1; |
1978 | } | 1952 | } |
1979 | 1953 | ||
1980 | while (1) { | 1954 | len = 0; |
1981 | int x; | 1955 | buf = firmware->data; |
1982 | 1956 | for (;;) { | |
1983 | if ((x = sys_read (fd, (char __user *) §ion_length, sizeof (section_length))) != | 1957 | int section_length = *(signed char *)buf; |
1984 | sizeof (section_length)) { | 1958 | if (section_length == 0) |
1985 | snd_printk ("firmware read error.\n"); | ||
1986 | goto failure; | ||
1987 | } | ||
1988 | |||
1989 | if (section_length == 0) { | ||
1990 | break; | 1959 | break; |
1991 | } | ||
1992 | |||
1993 | if (section_length < 0 || section_length > WF_SECTION_MAX) { | 1960 | if (section_length < 0 || section_length > WF_SECTION_MAX) { |
1994 | snd_printk ("invalid firmware section length %d\n", | 1961 | snd_printk(KERN_ERR |
1995 | section_length); | 1962 | "invalid firmware section length %d\n", |
1963 | section_length); | ||
1996 | goto failure; | 1964 | goto failure; |
1997 | } | 1965 | } |
1966 | buf++; | ||
1967 | len++; | ||
1998 | 1968 | ||
1999 | if (sys_read (fd, (char __user *) section, section_length) != section_length) { | 1969 | if (firmware->size < len + section_length) { |
2000 | snd_printk ("firmware section " | 1970 | snd_printk(KERN_ERR "firmware section read error.\n"); |
2001 | "read error.\n"); | ||
2002 | goto failure; | 1971 | goto failure; |
2003 | } | 1972 | } |
2004 | 1973 | ||
2005 | /* Send command */ | 1974 | /* Send command */ |
2006 | 1975 | if (wavefront_write(dev, WFC_DOWNLOAD_OS)) | |
2007 | if (wavefront_write (dev, WFC_DOWNLOAD_OS)) { | ||
2008 | goto failure; | 1976 | goto failure; |
2009 | } | ||
2010 | 1977 | ||
2011 | for (i = 0; i < section_length; i++) { | 1978 | for (; section_length; section_length--) { |
2012 | if (wavefront_write (dev, section[i])) { | 1979 | if (wavefront_write(dev, *buf)) |
2013 | goto failure; | 1980 | goto failure; |
2014 | } | 1981 | buf++; |
1982 | len++; | ||
2015 | } | 1983 | } |
2016 | 1984 | ||
2017 | /* get ACK */ | 1985 | /* get ACK */ |
2018 | 1986 | if (!wavefront_wait(dev, STAT_CAN_READ)) { | |
2019 | if (wavefront_wait (dev, STAT_CAN_READ)) { | 1987 | snd_printk(KERN_ERR "time out for firmware ACK.\n"); |
2020 | 1988 | goto failure; | |
2021 | if ((c = inb (dev->data_port)) != WF_ACK) { | 1989 | } |
2022 | 1990 | err = inb(dev->data_port); | |
2023 | snd_printk ("download " | 1991 | if (err != WF_ACK) { |
2024 | "of section #%d not " | 1992 | snd_printk(KERN_ERR |
2025 | "acknowledged, ack = 0x%x\n", | 1993 | "download of section #%d not " |
2026 | section_cnt_downloaded + 1, c); | 1994 | "acknowledged, ack = 0x%x\n", |
2027 | goto failure; | 1995 | section_cnt_downloaded + 1, err); |
2028 | |||
2029 | } | ||
2030 | |||
2031 | } else { | ||
2032 | snd_printk ("time out for firmware ACK.\n"); | ||
2033 | goto failure; | 1996 | goto failure; |
2034 | } | 1997 | } |
2035 | 1998 | ||
1999 | section_cnt_downloaded++; | ||
2036 | } | 2000 | } |
2037 | 2001 | ||
2038 | sys_close (fd); | 2002 | release_firmware(firmware); |
2039 | set_fs (fs); | ||
2040 | return 0; | 2003 | return 0; |
2041 | 2004 | ||
2042 | failure: | 2005 | failure: |
2043 | sys_close (fd); | 2006 | release_firmware(firmware); |
2044 | set_fs (fs); | 2007 | snd_printk(KERN_ERR "firmware download failed!!!\n"); |
2045 | snd_printk ("firmware download failed!!!\n"); | ||
2046 | return 1; | 2008 | return 1; |
2047 | } | 2009 | } |
2048 | 2010 | ||
@@ -2232,3 +2194,5 @@ snd_wavefront_detect (snd_wavefront_card_t *card) | |||
2232 | 2194 | ||
2233 | return 0; | 2195 | return 0; |
2234 | } | 2196 | } |
2197 | |||
2198 | MODULE_FIRMWARE(DEFAULT_OSPATH); | ||
diff --git a/sound/last.c b/sound/last.c index 964314efff5c..282b0cdb0589 100644 --- a/sound/last.c +++ b/sound/last.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Advanced Linux Sound Architecture | 2 | * Advanced Linux Sound Architecture |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index c6b44102aa5b..356bf21a1506 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig | |||
@@ -170,14 +170,14 @@ config SND_CA0106 | |||
170 | will be called snd-ca0106. | 170 | will be called snd-ca0106. |
171 | 171 | ||
172 | config SND_CMIPCI | 172 | config SND_CMIPCI |
173 | tristate "C-Media 8738, 8338" | 173 | tristate "C-Media 8338, 8738, 8768, 8770" |
174 | depends on SND | 174 | depends on SND |
175 | select SND_OPL3_LIB | 175 | select SND_OPL3_LIB |
176 | select SND_MPU401_UART | 176 | select SND_MPU401_UART |
177 | select SND_PCM | 177 | select SND_PCM |
178 | help | 178 | help |
179 | If you want to use soundcards based on C-Media CMI8338 or CMI8738 | 179 | If you want to use soundcards based on C-Media CMI8338, CMI8738, |
180 | chips, say Y here and read | 180 | CMI8768 or CMI8770 chips, say Y here and read |
181 | <file:Documentation/sound/alsa/CMIPCI.txt>. | 181 | <file:Documentation/sound/alsa/CMIPCI.txt>. |
182 | 182 | ||
183 | To compile this driver as a module, choose M here: the module | 183 | To compile this driver as a module, choose M here: the module |
@@ -500,6 +500,103 @@ config SND_HDA_INTEL | |||
500 | To compile this driver as a module, choose M here: the module | 500 | To compile this driver as a module, choose M here: the module |
501 | will be called snd-hda-intel. | 501 | will be called snd-hda-intel. |
502 | 502 | ||
503 | config SND_HDA_HWDEP | ||
504 | bool "Build hwdep interface for HD-audio driver" | ||
505 | depends on SND_HDA_INTEL | ||
506 | select SND_HWDEP | ||
507 | help | ||
508 | Say Y here to build a hwdep interface for HD-audio driver. | ||
509 | This interface can be used for out-of-band communication | ||
510 | with codecs for debugging purposes. | ||
511 | |||
512 | config SND_HDA_CODEC_REALTEK | ||
513 | bool "Build Realtek HD-audio codec support" | ||
514 | depends on SND_HDA_INTEL | ||
515 | default y | ||
516 | help | ||
517 | Say Y here to include Realtek HD-audio codec support in | ||
518 | snd-hda-intel driver, such as ALC880. | ||
519 | |||
520 | config SND_HDA_CODEC_ANALOG | ||
521 | bool "Build Analog Device HD-audio codec support" | ||
522 | depends on SND_HDA_INTEL | ||
523 | default y | ||
524 | help | ||
525 | Say Y here to include Analog Device HD-audio codec support in | ||
526 | snd-hda-intel driver, such as AD1986A. | ||
527 | |||
528 | config SND_HDA_CODEC_SIGMATEL | ||
529 | bool "Build IDT/Sigmatel HD-audio codec support" | ||
530 | depends on SND_HDA_INTEL | ||
531 | default y | ||
532 | help | ||
533 | Say Y here to include IDT (Sigmatel) HD-audio codec support in | ||
534 | snd-hda-intel driver, such as STAC9200. | ||
535 | |||
536 | config SND_HDA_CODEC_VIA | ||
537 | bool "Build VIA HD-audio codec support" | ||
538 | depends on SND_HDA_INTEL | ||
539 | default y | ||
540 | help | ||
541 | Say Y here to include VIA HD-audio codec support in | ||
542 | snd-hda-intel driver, such as VT1708. | ||
543 | |||
544 | config SND_HDA_CODEC_ATIHDMI | ||
545 | bool "Build ATI HDMI HD-audio codec support" | ||
546 | depends on SND_HDA_INTEL | ||
547 | default y | ||
548 | help | ||
549 | Say Y here to include ATI HDMI HD-audio codec support in | ||
550 | snd-hda-intel driver, such as ATI RS600 HDMI. | ||
551 | |||
552 | config SND_HDA_CODEC_CONEXANT | ||
553 | bool "Build Conexant HD-audio codec support" | ||
554 | depends on SND_HDA_INTEL | ||
555 | default y | ||
556 | help | ||
557 | Say Y here to include Conexant HD-audio codec support in | ||
558 | snd-hda-intel driver, such as CX20549. | ||
559 | |||
560 | config SND_HDA_CODEC_CMEDIA | ||
561 | bool "Build C-Media HD-audio codec support" | ||
562 | depends on SND_HDA_INTEL | ||
563 | default y | ||
564 | help | ||
565 | Say Y here to include C-Media HD-audio codec support in | ||
566 | snd-hda-intel driver, such as CMI9880. | ||
567 | |||
568 | config SND_HDA_CODEC_SI3054 | ||
569 | bool "Build Silicon Labs 3054 HD-modem codec support" | ||
570 | depends on SND_HDA_INTEL | ||
571 | default y | ||
572 | help | ||
573 | Say Y here to include Silicon Labs 3054 HD-modem codec | ||
574 | (and compatibles) support in snd-hda-intel driver. | ||
575 | |||
576 | config SND_HDA_GENERIC | ||
577 | bool "Enable generic HD-audio codec parser" | ||
578 | depends on SND_HDA_INTEL | ||
579 | default y | ||
580 | help | ||
581 | Say Y here to enable the generic HD-audio codec parser | ||
582 | in snd-hda-intel driver. | ||
583 | |||
584 | config SND_HDA_POWER_SAVE | ||
585 | bool "Aggressive power-saving on HD-audio" | ||
586 | depends on SND_HDA_INTEL && EXPERIMENTAL | ||
587 | help | ||
588 | Say Y here to enable more aggressive power-saving mode on | ||
589 | HD-audio driver. The power-saving timeout can be configured | ||
590 | via power_save option or over sysfs on-the-fly. | ||
591 | |||
592 | config SND_HDA_POWER_SAVE_DEFAULT | ||
593 | int "Default time-out for HD-audio power-save mode" | ||
594 | depends on SND_HDA_POWER_SAVE | ||
595 | default 0 | ||
596 | help | ||
597 | The default time-out value in seconds for HD-audio automatic | ||
598 | power-save mode. 0 means to disable the power-save mode. | ||
599 | |||
503 | config SND_HDSP | 600 | config SND_HDSP |
504 | tristate "RME Hammerfall DSP Audio" | 601 | tristate "RME Hammerfall DSP Audio" |
505 | depends on SND | 602 | depends on SND |
@@ -799,4 +896,12 @@ config SND_AC97_POWER_SAVE | |||
799 | snd-ac97-codec driver. You can toggle it dynamically over | 896 | snd-ac97-codec driver. You can toggle it dynamically over |
800 | sysfs, too. | 897 | sysfs, too. |
801 | 898 | ||
899 | config SND_AC97_POWER_SAVE_DEFAULT | ||
900 | int "Default time-out for AC97 power-save mode" | ||
901 | depends on SND_AC97_POWER_SAVE | ||
902 | default 0 | ||
903 | help | ||
904 | The default time-out value in seconds for AC97 automatic | ||
905 | power-save mode. 0 means to disable the power-save mode. | ||
906 | |||
802 | endmenu | 907 | endmenu |
diff --git a/sound/pci/Makefile b/sound/pci/Makefile index cd76e0293d06..09ddc82eeca2 100644 --- a/sound/pci/Makefile +++ b/sound/pci/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-ad1889-objs := ad1889.o | 6 | snd-ad1889-objs := ad1889.o |
diff --git a/sound/pci/ac97/Makefile b/sound/pci/ac97/Makefile index f5d471896b95..0be48b1a22d0 100644 --- a/sound/pci/ac97/Makefile +++ b/sound/pci/ac97/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-ac97-codec-objs := ac97_codec.o ac97_pcm.o | 6 | snd-ac97-codec-objs := ac97_codec.o ac97_pcm.o |
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index bbed644bf9c5..6a9966df0cc9 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Universal interface for Audio Codec '97 | 3 | * Universal interface for Audio Codec '97 |
4 | * | 4 | * |
5 | * For more details look to AC '97 component specification revision 2.2 | 5 | * For more details look to AC '97 component specification revision 2.2 |
@@ -39,7 +39,7 @@ | |||
39 | 39 | ||
40 | #include "ac97_patch.c" | 40 | #include "ac97_patch.c" |
41 | 41 | ||
42 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 42 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
43 | MODULE_DESCRIPTION("Universal interface for Audio Codec '97"); | 43 | MODULE_DESCRIPTION("Universal interface for Audio Codec '97"); |
44 | MODULE_LICENSE("GPL"); | 44 | MODULE_LICENSE("GPL"); |
45 | 45 | ||
@@ -49,7 +49,7 @@ module_param(enable_loopback, bool, 0444); | |||
49 | MODULE_PARM_DESC(enable_loopback, "Enable AC97 ADC/DAC Loopback Control"); | 49 | MODULE_PARM_DESC(enable_loopback, "Enable AC97 ADC/DAC Loopback Control"); |
50 | 50 | ||
51 | #ifdef CONFIG_SND_AC97_POWER_SAVE | 51 | #ifdef CONFIG_SND_AC97_POWER_SAVE |
52 | static int power_save; | 52 | static int power_save = CONFIG_SND_AC97_POWER_SAVE_DEFAULT; |
53 | module_param(power_save, bool, 0644); | 53 | module_param(power_save, bool, 0644); |
54 | MODULE_PARM_DESC(power_save, "Enable AC97 power-saving control"); | 54 | MODULE_PARM_DESC(power_save, "Enable AC97 power-saving control"); |
55 | #endif | 55 | #endif |
@@ -176,7 +176,7 @@ static const struct ac97_codec_id snd_ac97_codec_ids[] = { | |||
176 | { 0x574d4C09, 0xffffffff, "WM9709", NULL, NULL}, | 176 | { 0x574d4C09, 0xffffffff, "WM9709", NULL, NULL}, |
177 | { 0x574d4C12, 0xffffffff, "WM9711,WM9712", patch_wolfson11, NULL}, | 177 | { 0x574d4C12, 0xffffffff, "WM9711,WM9712", patch_wolfson11, NULL}, |
178 | { 0x574d4c13, 0xffffffff, "WM9713,WM9714", patch_wolfson13, NULL, AC97_DEFAULT_POWER_OFF}, | 178 | { 0x574d4c13, 0xffffffff, "WM9713,WM9714", patch_wolfson13, NULL, AC97_DEFAULT_POWER_OFF}, |
179 | { 0x594d4800, 0xffffffff, "YMF743", NULL, NULL }, | 179 | { 0x594d4800, 0xffffffff, "YMF743", patch_yamaha_ymf743, NULL }, |
180 | { 0x594d4802, 0xffffffff, "YMF752", NULL, NULL }, | 180 | { 0x594d4802, 0xffffffff, "YMF752", NULL, NULL }, |
181 | { 0x594d4803, 0xffffffff, "YMF753", patch_yamaha_ymf753, NULL }, | 181 | { 0x594d4803, 0xffffffff, "YMF753", patch_yamaha_ymf753, NULL }, |
182 | { 0x83847600, 0xffffffff, "STAC9700,83,84", patch_sigmatel_stac9700, NULL }, | 182 | { 0x83847600, 0xffffffff, "STAC9700,83,84", patch_sigmatel_stac9700, NULL }, |
@@ -779,6 +779,12 @@ static int snd_ac97_spdif_default_put(struct snd_kcontrol *kcontrol, struct snd_ | |||
779 | change |= snd_ac97_update_bits_nolock(ac97, AC97_CXR_AUDIO_MISC, | 779 | change |= snd_ac97_update_bits_nolock(ac97, AC97_CXR_AUDIO_MISC, |
780 | AC97_CXR_SPDIF_MASK | AC97_CXR_COPYRGT, | 780 | AC97_CXR_SPDIF_MASK | AC97_CXR_COPYRGT, |
781 | v); | 781 | v); |
782 | } else if (ac97->id == AC97_ID_YMF743) { | ||
783 | change |= snd_ac97_update_bits_nolock(ac97, | ||
784 | AC97_YMF7X3_DIT_CTRL, | ||
785 | 0xff38, | ||
786 | ((val << 4) & 0xff00) | | ||
787 | ((val << 2) & 0x0038)); | ||
782 | } else { | 788 | } else { |
783 | unsigned short extst = snd_ac97_read_cache(ac97, AC97_EXTENDED_STATUS); | 789 | unsigned short extst = snd_ac97_read_cache(ac97, AC97_EXTENDED_STATUS); |
784 | snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0); /* turn off */ | 790 | snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0); /* turn off */ |
@@ -1375,7 +1381,8 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) | |||
1375 | for (idx = 0; idx < 2; idx++) { | 1381 | for (idx = 0; idx < 2; idx++) { |
1376 | if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_tone[idx], ac97))) < 0) | 1382 | if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_tone[idx], ac97))) < 0) |
1377 | return err; | 1383 | return err; |
1378 | if (ac97->id == AC97_ID_YMF753) { | 1384 | if (ac97->id == AC97_ID_YMF743 || |
1385 | ac97->id == AC97_ID_YMF753) { | ||
1379 | kctl->private_value &= ~(0xff << 16); | 1386 | kctl->private_value &= ~(0xff << 16); |
1380 | kctl->private_value |= 7 << 16; | 1387 | kctl->private_value |= 7 << 16; |
1381 | } | 1388 | } |
@@ -2036,11 +2043,12 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, | |||
2036 | else { | 2043 | else { |
2037 | udelay(50); | 2044 | udelay(50); |
2038 | if (ac97->scaps & AC97_SCAP_SKIP_AUDIO) | 2045 | if (ac97->scaps & AC97_SCAP_SKIP_AUDIO) |
2039 | err = ac97_reset_wait(ac97, HZ/2, 1); | 2046 | err = ac97_reset_wait(ac97, msecs_to_jiffies(500), 1); |
2040 | else { | 2047 | else { |
2041 | err = ac97_reset_wait(ac97, HZ/2, 0); | 2048 | err = ac97_reset_wait(ac97, msecs_to_jiffies(500), 0); |
2042 | if (err < 0) | 2049 | if (err < 0) |
2043 | err = ac97_reset_wait(ac97, HZ/2, 1); | 2050 | err = ac97_reset_wait(ac97, |
2051 | msecs_to_jiffies(500), 1); | ||
2044 | } | 2052 | } |
2045 | if (err < 0) { | 2053 | if (err < 0) { |
2046 | snd_printk(KERN_WARNING "AC'97 %d does not respond - RESET\n", ac97->num); | 2054 | snd_printk(KERN_WARNING "AC'97 %d does not respond - RESET\n", ac97->num); |
@@ -2104,7 +2112,7 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, | |||
2104 | } | 2112 | } |
2105 | /* nothing should be in powerdown mode */ | 2113 | /* nothing should be in powerdown mode */ |
2106 | snd_ac97_write_cache(ac97, AC97_GENERAL_PURPOSE, 0); | 2114 | snd_ac97_write_cache(ac97, AC97_GENERAL_PURPOSE, 0); |
2107 | end_time = jiffies + (HZ / 10); | 2115 | end_time = jiffies + msecs_to_jiffies(100); |
2108 | do { | 2116 | do { |
2109 | if ((snd_ac97_read(ac97, AC97_POWERDOWN) & 0x0f) == 0x0f) | 2117 | if ((snd_ac97_read(ac97, AC97_POWERDOWN) & 0x0f) == 0x0f) |
2110 | goto __ready_ok; | 2118 | goto __ready_ok; |
@@ -2136,7 +2144,7 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, | |||
2136 | udelay(100); | 2144 | udelay(100); |
2137 | /* nothing should be in powerdown mode */ | 2145 | /* nothing should be in powerdown mode */ |
2138 | snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0); | 2146 | snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0); |
2139 | end_time = jiffies + (HZ / 10); | 2147 | end_time = jiffies + msecs_to_jiffies(100); |
2140 | do { | 2148 | do { |
2141 | if ((snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS) & tmp) == tmp) | 2149 | if ((snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS) & tmp) == tmp) |
2142 | goto __ready_ok; | 2150 | goto __ready_ok; |
@@ -2354,7 +2362,8 @@ int snd_ac97_update_power(struct snd_ac97 *ac97, int reg, int powerup) | |||
2354 | * (for avoiding loud click noises for many (OSS) apps | 2362 | * (for avoiding loud click noises for many (OSS) apps |
2355 | * that open/close frequently) | 2363 | * that open/close frequently) |
2356 | */ | 2364 | */ |
2357 | schedule_delayed_work(&ac97->power_work, HZ*2); | 2365 | schedule_delayed_work(&ac97->power_work, |
2366 | msecs_to_jiffies(2000)); | ||
2358 | else { | 2367 | else { |
2359 | cancel_delayed_work(&ac97->power_work); | 2368 | cancel_delayed_work(&ac97->power_work); |
2360 | update_power_regs(ac97); | 2369 | update_power_regs(ac97); |
@@ -2436,7 +2445,7 @@ EXPORT_SYMBOL(snd_ac97_suspend); | |||
2436 | /* | 2445 | /* |
2437 | * restore ac97 status | 2446 | * restore ac97 status |
2438 | */ | 2447 | */ |
2439 | void snd_ac97_restore_status(struct snd_ac97 *ac97) | 2448 | static void snd_ac97_restore_status(struct snd_ac97 *ac97) |
2440 | { | 2449 | { |
2441 | int i; | 2450 | int i; |
2442 | 2451 | ||
@@ -2457,7 +2466,7 @@ void snd_ac97_restore_status(struct snd_ac97 *ac97) | |||
2457 | /* | 2466 | /* |
2458 | * restore IEC958 status | 2467 | * restore IEC958 status |
2459 | */ | 2468 | */ |
2460 | void snd_ac97_restore_iec958(struct snd_ac97 *ac97) | 2469 | static void snd_ac97_restore_iec958(struct snd_ac97 *ac97) |
2461 | { | 2470 | { |
2462 | if (ac97->ext_id & AC97_EI_SPDIF) { | 2471 | if (ac97->ext_id & AC97_EI_SPDIF) { |
2463 | if (ac97->regs[AC97_EXTENDED_STATUS] & AC97_EA_SPDIF) { | 2472 | if (ac97->regs[AC97_EXTENDED_STATUS] & AC97_EA_SPDIF) { |
@@ -2494,7 +2503,10 @@ void snd_ac97_resume(struct snd_ac97 *ac97) | |||
2494 | 2503 | ||
2495 | snd_ac97_write(ac97, AC97_POWERDOWN, 0); | 2504 | snd_ac97_write(ac97, AC97_POWERDOWN, 0); |
2496 | if (! (ac97->flags & AC97_DEFAULT_POWER_OFF)) { | 2505 | if (! (ac97->flags & AC97_DEFAULT_POWER_OFF)) { |
2497 | snd_ac97_write(ac97, AC97_RESET, 0); | 2506 | if (!(ac97->scaps & AC97_SCAP_SKIP_AUDIO)) |
2507 | snd_ac97_write(ac97, AC97_RESET, 0); | ||
2508 | else if (!(ac97->scaps & AC97_SCAP_SKIP_MODEM)) | ||
2509 | snd_ac97_write(ac97, AC97_EXTENDED_MID, 0); | ||
2498 | udelay(100); | 2510 | udelay(100); |
2499 | snd_ac97_write(ac97, AC97_POWERDOWN, 0); | 2511 | snd_ac97_write(ac97, AC97_POWERDOWN, 0); |
2500 | } | 2512 | } |
diff --git a/sound/pci/ac97/ac97_id.h b/sound/pci/ac97/ac97_id.h index 6d73514dc49e..c129492c82b3 100644 --- a/sound/pci/ac97/ac97_id.h +++ b/sound/pci/ac97/ac97_id.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Universal interface for Audio Codec '97 | 3 | * Universal interface for Audio Codec '97 |
4 | * | 4 | * |
5 | * For more details look to AC '97 component specification revision 2.2 | 5 | * For more details look to AC '97 component specification revision 2.2 |
@@ -54,6 +54,7 @@ | |||
54 | #define AC97_ID_ALC658 0x414c4780 | 54 | #define AC97_ID_ALC658 0x414c4780 |
55 | #define AC97_ID_ALC658D 0x414c4781 | 55 | #define AC97_ID_ALC658D 0x414c4781 |
56 | #define AC97_ID_ALC850 0x414c4790 | 56 | #define AC97_ID_ALC850 0x414c4790 |
57 | #define AC97_ID_YMF743 0x594d4800 | ||
57 | #define AC97_ID_YMF753 0x594d4803 | 58 | #define AC97_ID_YMF753 0x594d4803 |
58 | #define AC97_ID_VT1616 0x49434551 | 59 | #define AC97_ID_VT1616 0x49434551 |
59 | #define AC97_ID_CM9738 0x434d4941 | 60 | #define AC97_ID_CM9738 0x434d4941 |
diff --git a/sound/pci/ac97/ac97_local.h b/sound/pci/ac97/ac97_local.h index 78745c5c6df8..c276a5e3f7ac 100644 --- a/sound/pci/ac97/ac97_local.h +++ b/sound/pci/ac97/ac97_local.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Universal interface for Audio Codec '97 | 3 | * Universal interface for Audio Codec '97 |
4 | * | 4 | * |
5 | * For more details look to AC '97 component specification revision 2.2 | 5 | * For more details look to AC '97 component specification revision 2.2 |
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index 581ebba4d1a7..98c8b727b62b 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Universal interface for Audio Codec '97 | 3 | * Universal interface for Audio Codec '97 |
4 | * | 4 | * |
5 | * For more details look to AC '97 component specification revision 2.2 | 5 | * For more details look to AC '97 component specification revision 2.2 |
@@ -204,9 +204,13 @@ static inline int is_shared_micin(struct snd_ac97 *ac97) | |||
204 | 204 | ||
205 | 205 | ||
206 | /* The following snd_ac97_ymf753_... items added by David Shust (dshust@shustring.com) */ | 206 | /* The following snd_ac97_ymf753_... items added by David Shust (dshust@shustring.com) */ |
207 | /* Modified for YMF743 by Keita Maehara <maehara@debian.org> */ | ||
207 | 208 | ||
208 | /* It is possible to indicate to the Yamaha YMF753 the type of speakers being used. */ | 209 | /* It is possible to indicate to the Yamaha YMF7x3 the type of |
209 | static int snd_ac97_ymf753_info_speaker(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 210 | speakers being used. */ |
211 | |||
212 | static int snd_ac97_ymf7x3_info_speaker(struct snd_kcontrol *kcontrol, | ||
213 | struct snd_ctl_elem_info *uinfo) | ||
210 | { | 214 | { |
211 | static char *texts[3] = { | 215 | static char *texts[3] = { |
212 | "Standard", "Small", "Smaller" | 216 | "Standard", "Small", "Smaller" |
@@ -221,12 +225,13 @@ static int snd_ac97_ymf753_info_speaker(struct snd_kcontrol *kcontrol, struct sn | |||
221 | return 0; | 225 | return 0; |
222 | } | 226 | } |
223 | 227 | ||
224 | static int snd_ac97_ymf753_get_speaker(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 228 | static int snd_ac97_ymf7x3_get_speaker(struct snd_kcontrol *kcontrol, |
229 | struct snd_ctl_elem_value *ucontrol) | ||
225 | { | 230 | { |
226 | struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); | 231 | struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); |
227 | unsigned short val; | 232 | unsigned short val; |
228 | 233 | ||
229 | val = ac97->regs[AC97_YMF753_3D_MODE_SEL]; | 234 | val = ac97->regs[AC97_YMF7X3_3D_MODE_SEL]; |
230 | val = (val >> 10) & 3; | 235 | val = (val >> 10) & 3; |
231 | if (val > 0) /* 0 = invalid */ | 236 | if (val > 0) /* 0 = invalid */ |
232 | val--; | 237 | val--; |
@@ -234,7 +239,8 @@ static int snd_ac97_ymf753_get_speaker(struct snd_kcontrol *kcontrol, struct snd | |||
234 | return 0; | 239 | return 0; |
235 | } | 240 | } |
236 | 241 | ||
237 | static int snd_ac97_ymf753_put_speaker(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 242 | static int snd_ac97_ymf7x3_put_speaker(struct snd_kcontrol *kcontrol, |
243 | struct snd_ctl_elem_value *ucontrol) | ||
238 | { | 244 | { |
239 | struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); | 245 | struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); |
240 | unsigned short val; | 246 | unsigned short val; |
@@ -242,20 +248,22 @@ static int snd_ac97_ymf753_put_speaker(struct snd_kcontrol *kcontrol, struct snd | |||
242 | if (ucontrol->value.enumerated.item[0] > 2) | 248 | if (ucontrol->value.enumerated.item[0] > 2) |
243 | return -EINVAL; | 249 | return -EINVAL; |
244 | val = (ucontrol->value.enumerated.item[0] + 1) << 10; | 250 | val = (ucontrol->value.enumerated.item[0] + 1) << 10; |
245 | return snd_ac97_update(ac97, AC97_YMF753_3D_MODE_SEL, val); | 251 | return snd_ac97_update(ac97, AC97_YMF7X3_3D_MODE_SEL, val); |
246 | } | 252 | } |
247 | 253 | ||
248 | static const struct snd_kcontrol_new snd_ac97_ymf753_controls_speaker = | 254 | static const struct snd_kcontrol_new snd_ac97_ymf7x3_controls_speaker = |
249 | { | 255 | { |
250 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 256 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
251 | .name = "3D Control - Speaker", | 257 | .name = "3D Control - Speaker", |
252 | .info = snd_ac97_ymf753_info_speaker, | 258 | .info = snd_ac97_ymf7x3_info_speaker, |
253 | .get = snd_ac97_ymf753_get_speaker, | 259 | .get = snd_ac97_ymf7x3_get_speaker, |
254 | .put = snd_ac97_ymf753_put_speaker, | 260 | .put = snd_ac97_ymf7x3_put_speaker, |
255 | }; | 261 | }; |
256 | 262 | ||
257 | /* It is possible to indicate to the Yamaha YMF753 the source to direct to the S/PDIF output. */ | 263 | /* It is possible to indicate to the Yamaha YMF7x3 the source to |
258 | static int snd_ac97_ymf753_spdif_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 264 | direct to the S/PDIF output. */ |
265 | static int snd_ac97_ymf7x3_spdif_source_info(struct snd_kcontrol *kcontrol, | ||
266 | struct snd_ctl_elem_info *uinfo) | ||
259 | { | 267 | { |
260 | static char *texts[2] = { "AC-Link", "A/D Converter" }; | 268 | static char *texts[2] = { "AC-Link", "A/D Converter" }; |
261 | 269 | ||
@@ -268,17 +276,19 @@ static int snd_ac97_ymf753_spdif_source_info(struct snd_kcontrol *kcontrol, stru | |||
268 | return 0; | 276 | return 0; |
269 | } | 277 | } |
270 | 278 | ||
271 | static int snd_ac97_ymf753_spdif_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 279 | static int snd_ac97_ymf7x3_spdif_source_get(struct snd_kcontrol *kcontrol, |
280 | struct snd_ctl_elem_value *ucontrol) | ||
272 | { | 281 | { |
273 | struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); | 282 | struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); |
274 | unsigned short val; | 283 | unsigned short val; |
275 | 284 | ||
276 | val = ac97->regs[AC97_YMF753_DIT_CTRL2]; | 285 | val = ac97->regs[AC97_YMF7X3_DIT_CTRL]; |
277 | ucontrol->value.enumerated.item[0] = (val >> 1) & 1; | 286 | ucontrol->value.enumerated.item[0] = (val >> 1) & 1; |
278 | return 0; | 287 | return 0; |
279 | } | 288 | } |
280 | 289 | ||
281 | static int snd_ac97_ymf753_spdif_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 290 | static int snd_ac97_ymf7x3_spdif_source_put(struct snd_kcontrol *kcontrol, |
291 | struct snd_ctl_elem_value *ucontrol) | ||
282 | { | 292 | { |
283 | struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); | 293 | struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); |
284 | unsigned short val; | 294 | unsigned short val; |
@@ -286,7 +296,75 @@ static int snd_ac97_ymf753_spdif_source_put(struct snd_kcontrol *kcontrol, struc | |||
286 | if (ucontrol->value.enumerated.item[0] > 1) | 296 | if (ucontrol->value.enumerated.item[0] > 1) |
287 | return -EINVAL; | 297 | return -EINVAL; |
288 | val = ucontrol->value.enumerated.item[0] << 1; | 298 | val = ucontrol->value.enumerated.item[0] << 1; |
289 | return snd_ac97_update_bits(ac97, AC97_YMF753_DIT_CTRL2, 0x0002, val); | 299 | return snd_ac97_update_bits(ac97, AC97_YMF7X3_DIT_CTRL, 0x0002, val); |
300 | } | ||
301 | |||
302 | static int patch_yamaha_ymf7x3_3d(struct snd_ac97 *ac97) | ||
303 | { | ||
304 | struct snd_kcontrol *kctl; | ||
305 | int err; | ||
306 | |||
307 | kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97); | ||
308 | err = snd_ctl_add(ac97->bus->card, kctl); | ||
309 | if (err < 0) | ||
310 | return err; | ||
311 | strcpy(kctl->id.name, "3D Control - Wide"); | ||
312 | kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 9, 7, 0); | ||
313 | snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000); | ||
314 | err = snd_ctl_add(ac97->bus->card, | ||
315 | snd_ac97_cnew(&snd_ac97_ymf7x3_controls_speaker, | ||
316 | ac97)); | ||
317 | if (err < 0) | ||
318 | return err; | ||
319 | snd_ac97_write_cache(ac97, AC97_YMF7X3_3D_MODE_SEL, 0x0c00); | ||
320 | return 0; | ||
321 | } | ||
322 | |||
323 | static const struct snd_kcontrol_new snd_ac97_yamaha_ymf743_controls_spdif[3] = | ||
324 | { | ||
325 | AC97_SINGLE(SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH), | ||
326 | AC97_YMF7X3_DIT_CTRL, 0, 1, 0), | ||
327 | { | ||
328 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
329 | .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, NONE) "Source", | ||
330 | .info = snd_ac97_ymf7x3_spdif_source_info, | ||
331 | .get = snd_ac97_ymf7x3_spdif_source_get, | ||
332 | .put = snd_ac97_ymf7x3_spdif_source_put, | ||
333 | }, | ||
334 | AC97_SINGLE(SNDRV_CTL_NAME_IEC958("", NONE, NONE) "Mute", | ||
335 | AC97_YMF7X3_DIT_CTRL, 2, 1, 1) | ||
336 | }; | ||
337 | |||
338 | static int patch_yamaha_ymf743_build_spdif(struct snd_ac97 *ac97) | ||
339 | { | ||
340 | int err; | ||
341 | |||
342 | err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3); | ||
343 | if (err < 0) | ||
344 | return err; | ||
345 | err = patch_build_controls(ac97, | ||
346 | snd_ac97_yamaha_ymf743_controls_spdif, 3); | ||
347 | if (err < 0) | ||
348 | return err; | ||
349 | /* set default PCM S/PDIF params */ | ||
350 | /* PCM audio,no copyright,no preemphasis,PCM coder,original */ | ||
351 | snd_ac97_write_cache(ac97, AC97_YMF7X3_DIT_CTRL, 0xa201); | ||
352 | return 0; | ||
353 | } | ||
354 | |||
355 | static struct snd_ac97_build_ops patch_yamaha_ymf743_ops = { | ||
356 | .build_spdif = patch_yamaha_ymf743_build_spdif, | ||
357 | .build_3d = patch_yamaha_ymf7x3_3d, | ||
358 | }; | ||
359 | |||
360 | static int patch_yamaha_ymf743(struct snd_ac97 *ac97) | ||
361 | { | ||
362 | ac97->build_ops = &patch_yamaha_ymf743_ops; | ||
363 | ac97->caps |= AC97_BC_BASS_TREBLE; | ||
364 | ac97->caps |= 0x04 << 10; /* Yamaha 3D enhancement */ | ||
365 | ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */ | ||
366 | ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */ | ||
367 | return 0; | ||
290 | } | 368 | } |
291 | 369 | ||
292 | /* The AC'97 spec states that the S/PDIF signal is to be output at pin 48. | 370 | /* The AC'97 spec states that the S/PDIF signal is to be output at pin 48. |
@@ -311,7 +389,7 @@ static int snd_ac97_ymf753_spdif_output_pin_get(struct snd_kcontrol *kcontrol, s | |||
311 | struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); | 389 | struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); |
312 | unsigned short val; | 390 | unsigned short val; |
313 | 391 | ||
314 | val = ac97->regs[AC97_YMF753_DIT_CTRL2]; | 392 | val = ac97->regs[AC97_YMF7X3_DIT_CTRL]; |
315 | ucontrol->value.enumerated.item[0] = (val & 0x0008) ? 2 : (val & 0x0020) ? 1 : 0; | 393 | ucontrol->value.enumerated.item[0] = (val & 0x0008) ? 2 : (val & 0x0020) ? 1 : 0; |
316 | return 0; | 394 | return 0; |
317 | } | 395 | } |
@@ -325,7 +403,7 @@ static int snd_ac97_ymf753_spdif_output_pin_put(struct snd_kcontrol *kcontrol, s | |||
325 | return -EINVAL; | 403 | return -EINVAL; |
326 | val = (ucontrol->value.enumerated.item[0] == 2) ? 0x0008 : | 404 | val = (ucontrol->value.enumerated.item[0] == 2) ? 0x0008 : |
327 | (ucontrol->value.enumerated.item[0] == 1) ? 0x0020 : 0; | 405 | (ucontrol->value.enumerated.item[0] == 1) ? 0x0020 : 0; |
328 | return snd_ac97_update_bits(ac97, AC97_YMF753_DIT_CTRL2, 0x0028, val); | 406 | return snd_ac97_update_bits(ac97, AC97_YMF7X3_DIT_CTRL, 0x0028, val); |
329 | /* The following can be used to direct S/PDIF output to pin 47 (EAPD). | 407 | /* The following can be used to direct S/PDIF output to pin 47 (EAPD). |
330 | snd_ac97_write_cache(ac97, 0x62, snd_ac97_read(ac97, 0x62) | 0x0008); */ | 408 | snd_ac97_write_cache(ac97, 0x62, snd_ac97_read(ac97, 0x62) | 0x0008); */ |
331 | } | 409 | } |
@@ -334,9 +412,9 @@ static const struct snd_kcontrol_new snd_ac97_ymf753_controls_spdif[3] = { | |||
334 | { | 412 | { |
335 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 413 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
336 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", | 414 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", |
337 | .info = snd_ac97_ymf753_spdif_source_info, | 415 | .info = snd_ac97_ymf7x3_spdif_source_info, |
338 | .get = snd_ac97_ymf753_spdif_source_get, | 416 | .get = snd_ac97_ymf7x3_spdif_source_get, |
339 | .put = snd_ac97_ymf753_spdif_source_put, | 417 | .put = snd_ac97_ymf7x3_spdif_source_put, |
340 | }, | 418 | }, |
341 | { | 419 | { |
342 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 420 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -345,25 +423,10 @@ static const struct snd_kcontrol_new snd_ac97_ymf753_controls_spdif[3] = { | |||
345 | .get = snd_ac97_ymf753_spdif_output_pin_get, | 423 | .get = snd_ac97_ymf753_spdif_output_pin_get, |
346 | .put = snd_ac97_ymf753_spdif_output_pin_put, | 424 | .put = snd_ac97_ymf753_spdif_output_pin_put, |
347 | }, | 425 | }, |
348 | AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",NONE,NONE) "Mute", AC97_YMF753_DIT_CTRL2, 2, 1, 1) | 426 | AC97_SINGLE(SNDRV_CTL_NAME_IEC958("", NONE, NONE) "Mute", |
427 | AC97_YMF7X3_DIT_CTRL, 2, 1, 1) | ||
349 | }; | 428 | }; |
350 | 429 | ||
351 | static int patch_yamaha_ymf753_3d(struct snd_ac97 * ac97) | ||
352 | { | ||
353 | struct snd_kcontrol *kctl; | ||
354 | int err; | ||
355 | |||
356 | if ((err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0) | ||
357 | return err; | ||
358 | strcpy(kctl->id.name, "3D Control - Wide"); | ||
359 | kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 9, 7, 0); | ||
360 | snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000); | ||
361 | if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&snd_ac97_ymf753_controls_speaker, ac97))) < 0) | ||
362 | return err; | ||
363 | snd_ac97_write_cache(ac97, AC97_YMF753_3D_MODE_SEL, 0x0c00); | ||
364 | return 0; | ||
365 | } | ||
366 | |||
367 | static int patch_yamaha_ymf753_post_spdif(struct snd_ac97 * ac97) | 430 | static int patch_yamaha_ymf753_post_spdif(struct snd_ac97 * ac97) |
368 | { | 431 | { |
369 | int err; | 432 | int err; |
@@ -374,7 +437,7 @@ static int patch_yamaha_ymf753_post_spdif(struct snd_ac97 * ac97) | |||
374 | } | 437 | } |
375 | 438 | ||
376 | static struct snd_ac97_build_ops patch_yamaha_ymf753_ops = { | 439 | static struct snd_ac97_build_ops patch_yamaha_ymf753_ops = { |
377 | .build_3d = patch_yamaha_ymf753_3d, | 440 | .build_3d = patch_yamaha_ymf7x3_3d, |
378 | .build_post_spdif = patch_yamaha_ymf753_post_spdif | 441 | .build_post_spdif = patch_yamaha_ymf753_post_spdif |
379 | }; | 442 | }; |
380 | 443 | ||
@@ -1880,14 +1943,7 @@ static int patch_ad1981b(struct snd_ac97 *ac97) | |||
1880 | return 0; | 1943 | return 0; |
1881 | } | 1944 | } |
1882 | 1945 | ||
1883 | static int snd_ac97_ad1888_lohpsel_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1946 | #define snd_ac97_ad1888_lohpsel_info snd_ctl_boolean_mono_info |
1884 | { | ||
1885 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1886 | uinfo->count = 1; | ||
1887 | uinfo->value.integer.min = 0; | ||
1888 | uinfo->value.integer.max = 1; | ||
1889 | return 0; | ||
1890 | } | ||
1891 | 1947 | ||
1892 | static int snd_ac97_ad1888_lohpsel_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1948 | static int snd_ac97_ad1888_lohpsel_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1893 | { | 1949 | { |
@@ -2186,15 +2242,7 @@ static int patch_ad1985(struct snd_ac97 * ac97) | |||
2186 | return 0; | 2242 | return 0; |
2187 | } | 2243 | } |
2188 | 2244 | ||
2189 | static int snd_ac97_ad1986_bool_info(struct snd_kcontrol *kcontrol, | 2245 | #define snd_ac97_ad1986_bool_info snd_ctl_boolean_mono_info |
2190 | struct snd_ctl_elem_info *uinfo) | ||
2191 | { | ||
2192 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
2193 | uinfo->count = 1; | ||
2194 | uinfo->value.integer.min = 0; | ||
2195 | uinfo->value.integer.max = 1; | ||
2196 | return 0; | ||
2197 | } | ||
2198 | 2246 | ||
2199 | static int snd_ac97_ad1986_lososel_get(struct snd_kcontrol *kcontrol, | 2247 | static int snd_ac97_ad1986_lososel_get(struct snd_kcontrol *kcontrol, |
2200 | struct snd_ctl_elem_value *ucontrol) | 2248 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/pci/ac97/ac97_patch.h b/sound/pci/ac97/ac97_patch.h index fd341ce63762..9cccc27ea1b5 100644 --- a/sound/pci/ac97/ac97_patch.h +++ b/sound/pci/ac97/ac97_patch.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Universal interface for Audio Codec '97 | 3 | * Universal interface for Audio Codec '97 |
4 | * | 4 | * |
5 | * For more details look to AC '97 component specification revision 2.2 | 5 | * For more details look to AC '97 component specification revision 2.2 |
diff --git a/sound/pci/ac97/ac97_pcm.c b/sound/pci/ac97/ac97_pcm.c index 4281e6d0c5b6..8cbc03332b01 100644 --- a/sound/pci/ac97/ac97_pcm.c +++ b/sound/pci/ac97/ac97_pcm.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Universal interface for Audio Codec '97 | 3 | * Universal interface for Audio Codec '97 |
4 | * | 4 | * |
5 | * For more details look to AC '97 component specification revision 2.2 | 5 | * For more details look to AC '97 component specification revision 2.2 |
diff --git a/sound/pci/ac97/ac97_proc.c b/sound/pci/ac97/ac97_proc.c index a3fdd7da911c..fed4a2c3d8a1 100644 --- a/sound/pci/ac97/ac97_proc.c +++ b/sound/pci/ac97/ac97_proc.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Universal interface for Audio Codec '97 | 3 | * Universal interface for Audio Codec '97 |
4 | * | 4 | * |
5 | * For more details look to AC '97 component specification revision 2.2 | 5 | * For more details look to AC '97 component specification revision 2.2 |
@@ -236,10 +236,14 @@ static void snd_ac97_proc_read_main(struct snd_ac97 *ac97, struct snd_info_buffe | |||
236 | val = snd_ac97_read(ac97, AC97_PCM_MIC_ADC_RATE); | 236 | val = snd_ac97_read(ac97, AC97_PCM_MIC_ADC_RATE); |
237 | snd_iprintf(buffer, "PCM MIC ADC : %iHz\n", val); | 237 | snd_iprintf(buffer, "PCM MIC ADC : %iHz\n", val); |
238 | } | 238 | } |
239 | if ((ext & AC97_EI_SPDIF) || (ac97->flags & AC97_CS_SPDIF)) { | 239 | if ((ext & AC97_EI_SPDIF) || (ac97->flags & AC97_CS_SPDIF) || |
240 | (ac97->id == AC97_ID_YMF743)) { | ||
240 | if (ac97->flags & AC97_CS_SPDIF) | 241 | if (ac97->flags & AC97_CS_SPDIF) |
241 | val = snd_ac97_read(ac97, AC97_CSR_SPDIF); | 242 | val = snd_ac97_read(ac97, AC97_CSR_SPDIF); |
242 | else | 243 | else if (ac97->id == AC97_ID_YMF743) { |
244 | val = snd_ac97_read(ac97, AC97_YMF7X3_DIT_CTRL); | ||
245 | val = 0x2000 | (val & 0xff00) >> 4 | (val & 0x38) >> 2; | ||
246 | } else | ||
243 | val = snd_ac97_read(ac97, AC97_SPDIF); | 247 | val = snd_ac97_read(ac97, AC97_SPDIF); |
244 | 248 | ||
245 | snd_iprintf(buffer, "SPDIF Control :%s%s%s%s Category=0x%x Generation=%i%s%s%s\n", | 249 | snd_iprintf(buffer, "SPDIF Control :%s%s%s%s Category=0x%x Generation=%i%s%s%s\n", |
diff --git a/sound/pci/ac97/ak4531_codec.c b/sound/pci/ac97/ak4531_codec.c index dc26820a03a5..722de451d15f 100644 --- a/sound/pci/ac97/ak4531_codec.c +++ b/sound/pci/ac97/ak4531_codec.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Universal routines for AK4531 codec | 3 | * Universal routines for AK4531 codec |
4 | * | 4 | * |
5 | * | 5 | * |
@@ -29,7 +29,7 @@ | |||
29 | #include <sound/ak4531_codec.h> | 29 | #include <sound/ak4531_codec.h> |
30 | #include <sound/tlv.h> | 30 | #include <sound/tlv.h> |
31 | 31 | ||
32 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 32 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
33 | MODULE_DESCRIPTION("Universal routines for AK4531 codec"); | 33 | MODULE_DESCRIPTION("Universal routines for AK4531 codec"); |
34 | MODULE_LICENSE("GPL"); | 34 | MODULE_LICENSE("GPL"); |
35 | 35 | ||
diff --git a/sound/pci/ali5451/Makefile b/sound/pci/ali5451/Makefile index 2e1831597474..713459c12d22 100644 --- a/sound/pci/ali5451/Makefile +++ b/sound/pci/ali5451/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-ali5451-objs := ali5451.o | 6 | snd-ali5451-objs := ali5451.o |
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index 05b4c8696941..4c2bd7adf674 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c | |||
@@ -1804,15 +1804,7 @@ static int __devinit snd_ali_build_pcms(struct snd_ali *codec) | |||
1804 | .info = snd_ali5451_spdif_info, .get = snd_ali5451_spdif_get, \ | 1804 | .info = snd_ali5451_spdif_info, .get = snd_ali5451_spdif_get, \ |
1805 | .put = snd_ali5451_spdif_put, .private_value = value} | 1805 | .put = snd_ali5451_spdif_put, .private_value = value} |
1806 | 1806 | ||
1807 | static int snd_ali5451_spdif_info(struct snd_kcontrol *kcontrol, | 1807 | #define snd_ali5451_spdif_info snd_ctl_boolean_mono_info |
1808 | struct snd_ctl_elem_info *uinfo) | ||
1809 | { | ||
1810 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1811 | uinfo->count = 1; | ||
1812 | uinfo->value.integer.min = 0; | ||
1813 | uinfo->value.integer.max = 1; | ||
1814 | return 0; | ||
1815 | } | ||
1816 | 1808 | ||
1817 | static int snd_ali5451_spdif_get(struct snd_kcontrol *kcontrol, | 1809 | static int snd_ali5451_spdif_get(struct snd_kcontrol *kcontrol, |
1818 | struct snd_ctl_elem_value *ucontrol) | 1810 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c index 8fb55d3b454b..1190ef366a41 100644 --- a/sound/pci/als4000.c +++ b/sound/pci/als4000.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * card-als4000.c - driver for Avance Logic ALS4000 based soundcards. | 2 | * card-als4000.c - driver for Avance Logic ALS4000 based soundcards. |
3 | * Copyright (C) 2000 by Bart Hartgers <bart@etpmod.phys.tue.nl>, | 3 | * Copyright (C) 2000 by Bart Hartgers <bart@etpmod.phys.tue.nl>, |
4 | * Jaroslav Kysela <perex@suse.cz> | 4 | * Jaroslav Kysela <perex@perex.cz> |
5 | * Copyright (C) 2002 by Andreas Mohr <hw7oshyuv3001@sneakemail.com> | 5 | * Copyright (C) 2002 by Andreas Mohr <hw7oshyuv3001@sneakemail.com> |
6 | * | 6 | * |
7 | * Framework borrowed from Massimo Piccioni's card-als100.c. | 7 | * Framework borrowed from Massimo Piccioni's card-als100.c. |
diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c index 5ec1b6fcd548..f70286a7364a 100644 --- a/sound/pci/au88x0/au88x0.c +++ b/sound/pci/au88x0/au88x0.c | |||
@@ -232,6 +232,7 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip) | |||
232 | pci_disable_device(chip->pci_dev); | 232 | pci_disable_device(chip->pci_dev); |
233 | //FIXME: this not the right place to unregister the gameport | 233 | //FIXME: this not the right place to unregister the gameport |
234 | vortex_gameport_unregister(chip); | 234 | vortex_gameport_unregister(chip); |
235 | kfree(chip); | ||
235 | return err; | 236 | return err; |
236 | } | 237 | } |
237 | 238 | ||
diff --git a/sound/pci/au88x0/au88x0_eq.c b/sound/pci/au88x0/au88x0_eq.c index 0c86a31c4336..38602b85874d 100644 --- a/sound/pci/au88x0/au88x0_eq.c +++ b/sound/pci/au88x0/au88x0_eq.c | |||
@@ -728,15 +728,7 @@ static void vortex_Eqlzr_shutdown(vortex_t * vortex) | |||
728 | /* ALSA interface */ | 728 | /* ALSA interface */ |
729 | 729 | ||
730 | /* Control interface */ | 730 | /* Control interface */ |
731 | static int | 731 | #define snd_vortex_eqtoggle_info snd_ctl_boolean_mono_info |
732 | snd_vortex_eqtoggle_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | ||
733 | { | ||
734 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
735 | uinfo->count = 1; | ||
736 | uinfo->value.integer.min = 0; | ||
737 | uinfo->value.integer.max = 1; | ||
738 | return 0; | ||
739 | } | ||
740 | 732 | ||
741 | static int | 733 | static int |
742 | snd_vortex_eqtoggle_get(struct snd_kcontrol *kcontrol, | 734 | snd_vortex_eqtoggle_get(struct snd_kcontrol *kcontrol, |
diff --git a/sound/pci/au88x0/au88x0_mpu401.c b/sound/pci/au88x0/au88x0_mpu401.c index c75d368ea087..8db3d3e6f7bb 100644 --- a/sound/pci/au88x0/au88x0_mpu401.c +++ b/sound/pci/au88x0/au88x0_mpu401.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Routines for control of MPU-401 in UART mode | 3 | * Routines for control of MPU-401 in UART mode |
4 | * | 4 | * |
5 | * Modified for the Aureal Vortex based Soundcards | 5 | * Modified for the Aureal Vortex based Soundcards |
diff --git a/sound/pci/au88x0/au88x0_synth.c b/sound/pci/au88x0/au88x0_synth.c index d3e662a1285d..978b856f5621 100644 --- a/sound/pci/au88x0/au88x0_synth.c +++ b/sound/pci/au88x0/au88x0_synth.c | |||
@@ -370,8 +370,8 @@ static void vortex_wt_SetFrequency(vortex_t * vortex, int wt, unsigned int sr) | |||
370 | while ((edx & 0x80000000) == 0) { | 370 | while ((edx & 0x80000000) == 0) { |
371 | edx <<= 1; | 371 | edx <<= 1; |
372 | eax--; | 372 | eax--; |
373 | if (eax == 0) ; | 373 | if (eax == 0) |
374 | break; | 374 | break; |
375 | } | 375 | } |
376 | if (eax) | 376 | if (eax) |
377 | edx <<= 1; | 377 | edx <<= 1; |
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c index 131952f55857..91f9e6a112ff 100644 --- a/sound/pci/bt87x.c +++ b/sound/pci/bt87x.c | |||
@@ -147,15 +147,56 @@ MODULE_PARM_DESC(load_all, "Allow to load the non-whitelisted cards"); | |||
147 | /* SYNC, one WRITE per line, one extra WRITE per page boundary, SYNC, JUMP */ | 147 | /* SYNC, one WRITE per line, one extra WRITE per page boundary, SYNC, JUMP */ |
148 | #define MAX_RISC_SIZE ((1 + 255 + (PAGE_ALIGN(255 * 4092) / PAGE_SIZE - 1) + 1 + 1) * 8) | 148 | #define MAX_RISC_SIZE ((1 + 255 + (PAGE_ALIGN(255 * 4092) / PAGE_SIZE - 1) + 1 + 1) * 8) |
149 | 149 | ||
150 | /* Cards with configuration information */ | ||
151 | enum snd_bt87x_boardid { | ||
152 | SND_BT87X_BOARD_UNKNOWN, | ||
153 | SND_BT87X_BOARD_GENERIC, /* both an & dig interfaces, 32kHz */ | ||
154 | SND_BT87X_BOARD_ANALOG, /* board with no external A/D */ | ||
155 | SND_BT87X_BOARD_OSPREY2x0, | ||
156 | SND_BT87X_BOARD_OSPREY440, | ||
157 | SND_BT87X_BOARD_AVPHONE98, | ||
158 | }; | ||
159 | |||
160 | /* Card configuration */ | ||
161 | struct snd_bt87x_board { | ||
162 | int dig_rate; /* Digital input sampling rate */ | ||
163 | u32 digital_fmt; /* Register settings for digital input */ | ||
164 | unsigned no_analog:1; /* No analog input */ | ||
165 | unsigned no_digital:1; /* No digital input */ | ||
166 | }; | ||
167 | |||
168 | static const __devinitdata struct snd_bt87x_board snd_bt87x_boards[] = { | ||
169 | [SND_BT87X_BOARD_UNKNOWN] = { | ||
170 | .dig_rate = 32000, /* just a guess */ | ||
171 | }, | ||
172 | [SND_BT87X_BOARD_GENERIC] = { | ||
173 | .dig_rate = 32000, | ||
174 | }, | ||
175 | [SND_BT87X_BOARD_ANALOG] = { | ||
176 | .no_digital = 1, | ||
177 | }, | ||
178 | [SND_BT87X_BOARD_OSPREY2x0] = { | ||
179 | .dig_rate = 44100, | ||
180 | .digital_fmt = CTL_DA_LRI | (1 << CTL_DA_LRD_SHIFT), | ||
181 | }, | ||
182 | [SND_BT87X_BOARD_OSPREY440] = { | ||
183 | .dig_rate = 32000, | ||
184 | .digital_fmt = CTL_DA_LRI | (1 << CTL_DA_LRD_SHIFT), | ||
185 | .no_analog = 1, | ||
186 | }, | ||
187 | [SND_BT87X_BOARD_AVPHONE98] = { | ||
188 | .dig_rate = 48000, | ||
189 | }, | ||
190 | }; | ||
191 | |||
150 | struct snd_bt87x { | 192 | struct snd_bt87x { |
151 | struct snd_card *card; | 193 | struct snd_card *card; |
152 | struct pci_dev *pci; | 194 | struct pci_dev *pci; |
195 | struct snd_bt87x_board board; | ||
153 | 196 | ||
154 | void __iomem *mmio; | 197 | void __iomem *mmio; |
155 | int irq; | 198 | int irq; |
156 | 199 | ||
157 | int dig_rate; | ||
158 | |||
159 | spinlock_t reg_lock; | 200 | spinlock_t reg_lock; |
160 | unsigned long opened; | 201 | unsigned long opened; |
161 | struct snd_pcm_substream *substream; | 202 | struct snd_pcm_substream *substream; |
@@ -340,30 +381,11 @@ static struct snd_pcm_hardware snd_bt87x_analog_hw = { | |||
340 | 381 | ||
341 | static int snd_bt87x_set_digital_hw(struct snd_bt87x *chip, struct snd_pcm_runtime *runtime) | 382 | static int snd_bt87x_set_digital_hw(struct snd_bt87x *chip, struct snd_pcm_runtime *runtime) |
342 | { | 383 | { |
343 | static struct { | 384 | chip->reg_control |= CTL_DA_IOM_DA | CTL_A_PWRDN; |
344 | int rate; | ||
345 | unsigned int bit; | ||
346 | } ratebits[] = { | ||
347 | {8000, SNDRV_PCM_RATE_8000}, | ||
348 | {11025, SNDRV_PCM_RATE_11025}, | ||
349 | {16000, SNDRV_PCM_RATE_16000}, | ||
350 | {22050, SNDRV_PCM_RATE_22050}, | ||
351 | {32000, SNDRV_PCM_RATE_32000}, | ||
352 | {44100, SNDRV_PCM_RATE_44100}, | ||
353 | {48000, SNDRV_PCM_RATE_48000} | ||
354 | }; | ||
355 | int i; | ||
356 | |||
357 | chip->reg_control |= CTL_DA_IOM_DA; | ||
358 | runtime->hw = snd_bt87x_digital_hw; | 385 | runtime->hw = snd_bt87x_digital_hw; |
359 | runtime->hw.rates = SNDRV_PCM_RATE_KNOT; | 386 | runtime->hw.rates = snd_pcm_rate_to_rate_bit(chip->board.dig_rate); |
360 | for (i = 0; i < ARRAY_SIZE(ratebits); ++i) | 387 | runtime->hw.rate_min = chip->board.dig_rate; |
361 | if (chip->dig_rate == ratebits[i].rate) { | 388 | runtime->hw.rate_max = chip->board.dig_rate; |
362 | runtime->hw.rates = ratebits[i].bit; | ||
363 | break; | ||
364 | } | ||
365 | runtime->hw.rate_min = chip->dig_rate; | ||
366 | runtime->hw.rate_max = chip->dig_rate; | ||
367 | return 0; | 389 | return 0; |
368 | } | 390 | } |
369 | 391 | ||
@@ -380,7 +402,7 @@ static int snd_bt87x_set_analog_hw(struct snd_bt87x *chip, struct snd_pcm_runtim | |||
380 | .rats = &analog_clock | 402 | .rats = &analog_clock |
381 | }; | 403 | }; |
382 | 404 | ||
383 | chip->reg_control &= ~CTL_DA_IOM_DA; | 405 | chip->reg_control &= ~(CTL_DA_IOM_DA | CTL_A_PWRDN); |
384 | runtime->hw = snd_bt87x_analog_hw; | 406 | runtime->hw = snd_bt87x_analog_hw; |
385 | return snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | 407 | return snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, |
386 | &constraint_rates); | 408 | &constraint_rates); |
@@ -419,6 +441,11 @@ static int snd_bt87x_close(struct snd_pcm_substream *substream) | |||
419 | { | 441 | { |
420 | struct snd_bt87x *chip = snd_pcm_substream_chip(substream); | 442 | struct snd_bt87x *chip = snd_pcm_substream_chip(substream); |
421 | 443 | ||
444 | spin_lock_irq(&chip->reg_lock); | ||
445 | chip->reg_control |= CTL_A_PWRDN; | ||
446 | snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control); | ||
447 | spin_unlock_irq(&chip->reg_lock); | ||
448 | |||
422 | chip->substream = NULL; | 449 | chip->substream = NULL; |
423 | clear_bit(0, &chip->opened); | 450 | clear_bit(0, &chip->opened); |
424 | smp_mb__after_clear_bit(); | 451 | smp_mb__after_clear_bit(); |
@@ -569,15 +596,7 @@ static struct snd_kcontrol_new snd_bt87x_capture_volume = { | |||
569 | .put = snd_bt87x_capture_volume_put, | 596 | .put = snd_bt87x_capture_volume_put, |
570 | }; | 597 | }; |
571 | 598 | ||
572 | static int snd_bt87x_capture_boost_info(struct snd_kcontrol *kcontrol, | 599 | #define snd_bt87x_capture_boost_info snd_ctl_boolean_mono_info |
573 | struct snd_ctl_elem_info *info) | ||
574 | { | ||
575 | info->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
576 | info->count = 1; | ||
577 | info->value.integer.min = 0; | ||
578 | info->value.integer.max = 1; | ||
579 | return 0; | ||
580 | } | ||
581 | 600 | ||
582 | static int snd_bt87x_capture_boost_get(struct snd_kcontrol *kcontrol, | 601 | static int snd_bt87x_capture_boost_get(struct snd_kcontrol *kcontrol, |
583 | struct snd_ctl_elem_value *value) | 602 | struct snd_ctl_elem_value *value) |
@@ -736,61 +755,69 @@ static int __devinit snd_bt87x_create(struct snd_card *card, | |||
736 | chip->mmio = ioremap_nocache(pci_resource_start(pci, 0), | 755 | chip->mmio = ioremap_nocache(pci_resource_start(pci, 0), |
737 | pci_resource_len(pci, 0)); | 756 | pci_resource_len(pci, 0)); |
738 | if (!chip->mmio) { | 757 | if (!chip->mmio) { |
739 | snd_bt87x_free(chip); | ||
740 | snd_printk(KERN_ERR "cannot remap io memory\n"); | 758 | snd_printk(KERN_ERR "cannot remap io memory\n"); |
741 | return -ENOMEM; | 759 | err = -ENOMEM; |
760 | goto fail; | ||
742 | } | 761 | } |
743 | 762 | ||
744 | chip->reg_control = CTL_DA_ES2 | CTL_PKTP_16 | (15 << CTL_DA_SDR_SHIFT); | 763 | chip->reg_control = CTL_A_PWRDN | CTL_DA_ES2 | |
764 | CTL_PKTP_16 | (15 << CTL_DA_SDR_SHIFT); | ||
745 | chip->interrupt_mask = MY_INTERRUPTS; | 765 | chip->interrupt_mask = MY_INTERRUPTS; |
746 | snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control); | 766 | snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control); |
747 | snd_bt87x_writel(chip, REG_INT_MASK, 0); | 767 | snd_bt87x_writel(chip, REG_INT_MASK, 0); |
748 | snd_bt87x_writel(chip, REG_INT_STAT, MY_INTERRUPTS); | 768 | snd_bt87x_writel(chip, REG_INT_STAT, MY_INTERRUPTS); |
749 | 769 | ||
750 | if (request_irq(pci->irq, snd_bt87x_interrupt, IRQF_SHARED, | 770 | err = request_irq(pci->irq, snd_bt87x_interrupt, IRQF_SHARED, |
751 | "Bt87x audio", chip)) { | 771 | "Bt87x audio", chip); |
752 | snd_bt87x_free(chip); | 772 | if (err < 0) { |
753 | snd_printk(KERN_ERR "cannot grab irq\n"); | 773 | snd_printk(KERN_ERR "cannot grab irq %d\n", pci->irq); |
754 | return -EBUSY; | 774 | goto fail; |
755 | } | 775 | } |
756 | chip->irq = pci->irq; | 776 | chip->irq = pci->irq; |
757 | pci_set_master(pci); | 777 | pci_set_master(pci); |
758 | synchronize_irq(chip->irq); | 778 | synchronize_irq(chip->irq); |
759 | 779 | ||
760 | err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); | 780 | err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); |
761 | if (err < 0) { | 781 | if (err < 0) |
762 | snd_bt87x_free(chip); | 782 | goto fail; |
763 | return err; | 783 | |
764 | } | ||
765 | snd_card_set_dev(card, &pci->dev); | 784 | snd_card_set_dev(card, &pci->dev); |
766 | *rchip = chip; | 785 | *rchip = chip; |
767 | return 0; | 786 | return 0; |
787 | |||
788 | fail: | ||
789 | snd_bt87x_free(chip); | ||
790 | return err; | ||
768 | } | 791 | } |
769 | 792 | ||
770 | #define BT_DEVICE(chip, subvend, subdev, rate) \ | 793 | #define BT_DEVICE(chip, subvend, subdev, id) \ |
771 | { .vendor = PCI_VENDOR_ID_BROOKTREE, \ | 794 | { .vendor = PCI_VENDOR_ID_BROOKTREE, \ |
772 | .device = chip, \ | 795 | .device = chip, \ |
773 | .subvendor = subvend, .subdevice = subdev, \ | 796 | .subvendor = subvend, .subdevice = subdev, \ |
774 | .driver_data = rate } | 797 | .driver_data = SND_BT87X_BOARD_ ## id } |
798 | /* driver_data is the card id for that device */ | ||
775 | 799 | ||
776 | /* driver_data is the default digital_rate value for that device */ | ||
777 | static struct pci_device_id snd_bt87x_ids[] = { | 800 | static struct pci_device_id snd_bt87x_ids[] = { |
778 | /* Hauppauge WinTV series */ | 801 | /* Hauppauge WinTV series */ |
779 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0x13eb, 32000), | 802 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0x13eb, GENERIC), |
780 | /* Hauppauge WinTV series */ | 803 | /* Hauppauge WinTV series */ |
781 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, 0x0070, 0x13eb, 32000), | 804 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, 0x0070, 0x13eb, GENERIC), |
782 | /* Viewcast Osprey 200 */ | 805 | /* Viewcast Osprey 200 */ |
783 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0xff01, 44100), | 806 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0xff01, OSPREY2x0), |
784 | /* Viewcast Osprey 440 (rate is configurable via gpio) */ | 807 | /* Viewcast Osprey 440 (rate is configurable via gpio) */ |
785 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0xff07, 32000), | 808 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0xff07, OSPREY440), |
786 | /* ATI TV-Wonder */ | 809 | /* ATI TV-Wonder */ |
787 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1002, 0x0001, 32000), | 810 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1002, 0x0001, GENERIC), |
788 | /* Leadtek Winfast tv 2000xp delux */ | 811 | /* Leadtek Winfast tv 2000xp delux */ |
789 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x107d, 0x6606, 32000), | 812 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x107d, 0x6606, GENERIC), |
790 | /* Voodoo TV 200 */ | 813 | /* Voodoo TV 200 */ |
791 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x121a, 0x3000, 32000), | 814 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x121a, 0x3000, GENERIC), |
792 | /* AVerMedia Studio No. 103, 203, ...? */ | 815 | /* AVerMedia Studio No. 103, 203, ...? */ |
793 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1461, 0x0003, 48000), | 816 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1461, 0x0003, AVPHONE98), |
817 | /* Prolink PixelView PV-M4900 */ | ||
818 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1554, 0x4011, GENERIC), | ||
819 | /* Pinnacle Studio PCTV rave */ | ||
820 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0xbd11, 0x1200, GENERIC), | ||
794 | { } | 821 | { } |
795 | }; | 822 | }; |
796 | MODULE_DEVICE_TABLE(pci, snd_bt87x_ids); | 823 | MODULE_DEVICE_TABLE(pci, snd_bt87x_ids); |
@@ -815,7 +842,7 @@ static struct { | |||
815 | 842 | ||
816 | static struct pci_driver driver; | 843 | static struct pci_driver driver; |
817 | 844 | ||
818 | /* return the rate of the card, or a negative value if it's blacklisted */ | 845 | /* return the id of the card, or a negative value if it's blacklisted */ |
819 | static int __devinit snd_bt87x_detect_card(struct pci_dev *pci) | 846 | static int __devinit snd_bt87x_detect_card(struct pci_dev *pci) |
820 | { | 847 | { |
821 | int i; | 848 | int i; |
@@ -833,12 +860,12 @@ static int __devinit snd_bt87x_detect_card(struct pci_dev *pci) | |||
833 | return -EBUSY; | 860 | return -EBUSY; |
834 | } | 861 | } |
835 | 862 | ||
836 | snd_printk(KERN_INFO "unknown card %#04x-%#04x:%#04x, using default rate 32000\n", | 863 | snd_printk(KERN_INFO "unknown card %#04x-%#04x:%#04x\n", |
837 | pci->device, pci->subsystem_vendor, pci->subsystem_device); | 864 | pci->device, pci->subsystem_vendor, pci->subsystem_device); |
838 | snd_printk(KERN_DEBUG "please mail id, board name, and, " | 865 | snd_printk(KERN_DEBUG "please mail id, board name, and, " |
839 | "if it works, the correct digital_rate option to " | 866 | "if it works, the correct digital_rate option to " |
840 | "<alsa-devel@alsa-project.org>\n"); | 867 | "<alsa-devel@alsa-project.org>\n"); |
841 | return 32000; /* default rate */ | 868 | return SND_BT87X_BOARD_UNKNOWN; |
842 | } | 869 | } |
843 | 870 | ||
844 | static int __devinit snd_bt87x_probe(struct pci_dev *pci, | 871 | static int __devinit snd_bt87x_probe(struct pci_dev *pci, |
@@ -847,12 +874,16 @@ static int __devinit snd_bt87x_probe(struct pci_dev *pci, | |||
847 | static int dev; | 874 | static int dev; |
848 | struct snd_card *card; | 875 | struct snd_card *card; |
849 | struct snd_bt87x *chip; | 876 | struct snd_bt87x *chip; |
850 | int err, rate; | 877 | int err; |
878 | enum snd_bt87x_boardid boardid; | ||
851 | 879 | ||
852 | rate = pci_id->driver_data; | 880 | if (!pci_id->driver_data) { |
853 | if (! rate) | 881 | err = snd_bt87x_detect_card(pci); |
854 | if ((rate = snd_bt87x_detect_card(pci)) <= 0) | 882 | if (err < 0) |
855 | return -ENODEV; | 883 | return -ENODEV; |
884 | boardid = err; | ||
885 | } else | ||
886 | boardid = pci_id->driver_data; | ||
856 | 887 | ||
857 | if (dev >= SNDRV_CARDS) | 888 | if (dev >= SNDRV_CARDS) |
858 | return -ENODEV; | 889 | return -ENODEV; |
@@ -869,27 +900,39 @@ static int __devinit snd_bt87x_probe(struct pci_dev *pci, | |||
869 | if (err < 0) | 900 | if (err < 0) |
870 | goto _error; | 901 | goto _error; |
871 | 902 | ||
872 | if (digital_rate[dev] > 0) | 903 | memcpy(&chip->board, &snd_bt87x_boards[boardid], sizeof(chip->board)); |
873 | chip->dig_rate = digital_rate[dev]; | ||
874 | else | ||
875 | chip->dig_rate = rate; | ||
876 | 904 | ||
877 | err = snd_bt87x_pcm(chip, DEVICE_DIGITAL, "Bt87x Digital"); | 905 | if (!chip->board.no_digital) { |
878 | if (err < 0) | 906 | if (digital_rate[dev] > 0) |
879 | goto _error; | 907 | chip->board.dig_rate = digital_rate[dev]; |
880 | err = snd_bt87x_pcm(chip, DEVICE_ANALOG, "Bt87x Analog"); | ||
881 | if (err < 0) | ||
882 | goto _error; | ||
883 | 908 | ||
884 | err = snd_ctl_add(card, snd_ctl_new1(&snd_bt87x_capture_volume, chip)); | 909 | chip->reg_control |= chip->board.digital_fmt; |
885 | if (err < 0) | 910 | |
886 | goto _error; | 911 | err = snd_bt87x_pcm(chip, DEVICE_DIGITAL, "Bt87x Digital"); |
887 | err = snd_ctl_add(card, snd_ctl_new1(&snd_bt87x_capture_boost, chip)); | 912 | if (err < 0) |
888 | if (err < 0) | 913 | goto _error; |
889 | goto _error; | 914 | } |
890 | err = snd_ctl_add(card, snd_ctl_new1(&snd_bt87x_capture_source, chip)); | 915 | if (!chip->board.no_analog) { |
891 | if (err < 0) | 916 | err = snd_bt87x_pcm(chip, DEVICE_ANALOG, "Bt87x Analog"); |
892 | goto _error; | 917 | if (err < 0) |
918 | goto _error; | ||
919 | err = snd_ctl_add(card, snd_ctl_new1( | ||
920 | &snd_bt87x_capture_volume, chip)); | ||
921 | if (err < 0) | ||
922 | goto _error; | ||
923 | err = snd_ctl_add(card, snd_ctl_new1( | ||
924 | &snd_bt87x_capture_boost, chip)); | ||
925 | if (err < 0) | ||
926 | goto _error; | ||
927 | err = snd_ctl_add(card, snd_ctl_new1( | ||
928 | &snd_bt87x_capture_source, chip)); | ||
929 | if (err < 0) | ||
930 | goto _error; | ||
931 | } | ||
932 | snd_printk(KERN_INFO "bt87x%d: Using board %d, %sanalog, %sdigital " | ||
933 | "(rate %d Hz)\n", dev, boardid, | ||
934 | chip->board.no_analog ? "no " : "", | ||
935 | chip->board.no_digital ? "no " : "", chip->board.dig_rate); | ||
893 | 936 | ||
894 | strcpy(card->driver, "Bt87x"); | 937 | strcpy(card->driver, "Bt87x"); |
895 | sprintf(card->shortname, "Brooktree Bt%x", pci->device); | 938 | sprintf(card->shortname, "Brooktree Bt%x", pci->device); |
@@ -920,8 +963,8 @@ static void __devexit snd_bt87x_remove(struct pci_dev *pci) | |||
920 | /* default entries for all Bt87x cards - it's not exported */ | 963 | /* default entries for all Bt87x cards - it's not exported */ |
921 | /* driver_data is set to 0 to call detection */ | 964 | /* driver_data is set to 0 to call detection */ |
922 | static struct pci_device_id snd_bt87x_default_ids[] __devinitdata = { | 965 | static struct pci_device_id snd_bt87x_default_ids[] __devinitdata = { |
923 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, PCI_ANY_ID, PCI_ANY_ID, 0), | 966 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, PCI_ANY_ID, PCI_ANY_ID, UNKNOWN), |
924 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, PCI_ANY_ID, PCI_ANY_ID, 0), | 967 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, PCI_ANY_ID, PCI_ANY_ID, UNKNOWN), |
925 | { } | 968 | { } |
926 | }; | 969 | }; |
927 | 970 | ||
diff --git a/sound/pci/ca0106/ca0106.h b/sound/pci/ca0106/ca0106.h index a0420bc63f0b..75da1746e758 100644 --- a/sound/pci/ca0106/ca0106.h +++ b/sound/pci/ca0106/ca0106.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk> | 2 | * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk> |
3 | * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit | 3 | * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit |
4 | * Version: 0.0.21 | 4 | * Version: 0.0.22 |
5 | * | 5 | * |
6 | * FEATURES currently supported: | 6 | * FEATURES currently supported: |
7 | * See ca0106_main.c for features. | 7 | * See ca0106_main.c for features. |
@@ -47,6 +47,8 @@ | |||
47 | * Added GPIO info for SB Live 24bit. | 47 | * Added GPIO info for SB Live 24bit. |
48 | * 0.0.21 | 48 | * 0.0.21 |
49 | * Implement support for Line-in capture on SB Live 24bit. | 49 | * Implement support for Line-in capture on SB Live 24bit. |
50 | * 0.0.22 | ||
51 | * Add support for mute control on SB Live 24bit (cards w/ SPI DAC) | ||
50 | * | 52 | * |
51 | * | 53 | * |
52 | * This code was initally based on code from ALSA's emu10k1x.c which is: | 54 | * This code was initally based on code from ALSA's emu10k1x.c which is: |
@@ -552,6 +554,95 @@ | |||
552 | #define CONTROL_CENTER_LFE_CHANNEL 1 | 554 | #define CONTROL_CENTER_LFE_CHANNEL 1 |
553 | #define CONTROL_UNKNOWN_CHANNEL 2 | 555 | #define CONTROL_UNKNOWN_CHANNEL 2 |
554 | 556 | ||
557 | |||
558 | /* Based on WM8768 Datasheet Rev 4.2 page 32 */ | ||
559 | #define SPI_REG_MASK 0x1ff /* 16-bit SPI writes have a 7-bit address */ | ||
560 | #define SPI_REG_SHIFT 9 /* followed by 9 bits of data */ | ||
561 | |||
562 | #define SPI_LDA1_REG 0 /* digital attenuation */ | ||
563 | #define SPI_RDA1_REG 1 | ||
564 | #define SPI_LDA2_REG 4 | ||
565 | #define SPI_RDA2_REG 5 | ||
566 | #define SPI_LDA3_REG 6 | ||
567 | #define SPI_RDA3_REG 7 | ||
568 | #define SPI_LDA4_REG 13 | ||
569 | #define SPI_RDA4_REG 14 | ||
570 | #define SPI_MASTDA_REG 8 | ||
571 | |||
572 | #define SPI_DA_BIT_UPDATE (1<<8) /* update attenuation values */ | ||
573 | #define SPI_DA_BIT_0dB 0xff /* 0 dB */ | ||
574 | #define SPI_DA_BIT_infdB 0x00 /* inf dB attenuation (mute) */ | ||
575 | |||
576 | #define SPI_PL_REG 2 | ||
577 | #define SPI_PL_BIT_L_M (0<<5) /* left channel = mute */ | ||
578 | #define SPI_PL_BIT_L_L (1<<5) /* left channel = left */ | ||
579 | #define SPI_PL_BIT_L_R (2<<5) /* left channel = right */ | ||
580 | #define SPI_PL_BIT_L_C (3<<5) /* left channel = (L+R)/2 */ | ||
581 | #define SPI_PL_BIT_R_M (0<<7) /* right channel = mute */ | ||
582 | #define SPI_PL_BIT_R_L (1<<7) /* right channel = left */ | ||
583 | #define SPI_PL_BIT_R_R (2<<7) /* right channel = right */ | ||
584 | #define SPI_PL_BIT_R_C (3<<7) /* right channel = (L+R)/2 */ | ||
585 | #define SPI_IZD_REG 2 | ||
586 | #define SPI_IZD_BIT (1<<4) /* infinite zero detect */ | ||
587 | |||
588 | #define SPI_FMT_REG 3 | ||
589 | #define SPI_FMT_BIT_RJ (0<<0) /* right justified mode */ | ||
590 | #define SPI_FMT_BIT_LJ (1<<0) /* left justified mode */ | ||
591 | #define SPI_FMT_BIT_I2S (2<<0) /* I2S mode */ | ||
592 | #define SPI_FMT_BIT_DSP (3<<0) /* DSP Modes A or B */ | ||
593 | #define SPI_LRP_REG 3 | ||
594 | #define SPI_LRP_BIT (1<<2) /* invert LRCLK polarity */ | ||
595 | #define SPI_BCP_REG 3 | ||
596 | #define SPI_BCP_BIT (1<<3) /* invert BCLK polarity */ | ||
597 | #define SPI_IWL_REG 3 | ||
598 | #define SPI_IWL_BIT_16 (0<<4) /* 16-bit world length */ | ||
599 | #define SPI_IWL_BIT_20 (1<<4) /* 20-bit world length */ | ||
600 | #define SPI_IWL_BIT_24 (2<<4) /* 24-bit world length */ | ||
601 | #define SPI_IWL_BIT_32 (3<<4) /* 32-bit world length */ | ||
602 | |||
603 | #define SPI_MS_REG 10 | ||
604 | #define SPI_MS_BIT (1<<5) /* master mode */ | ||
605 | #define SPI_RATE_REG 10 /* only applies in master mode */ | ||
606 | #define SPI_RATE_BIT_128 (0<<6) /* MCLK = LRCLK * 128 */ | ||
607 | #define SPI_RATE_BIT_192 (1<<6) | ||
608 | #define SPI_RATE_BIT_256 (2<<6) | ||
609 | #define SPI_RATE_BIT_384 (3<<6) | ||
610 | #define SPI_RATE_BIT_512 (4<<6) | ||
611 | #define SPI_RATE_BIT_768 (5<<6) | ||
612 | |||
613 | /* They really do label the bit for the 4th channel "4" and not "3" */ | ||
614 | #define SPI_DMUTE0_REG 9 | ||
615 | #define SPI_DMUTE1_REG 9 | ||
616 | #define SPI_DMUTE2_REG 9 | ||
617 | #define SPI_DMUTE4_REG 15 | ||
618 | #define SPI_DMUTE0_BIT (1<<3) | ||
619 | #define SPI_DMUTE1_BIT (1<<4) | ||
620 | #define SPI_DMUTE2_BIT (1<<5) | ||
621 | #define SPI_DMUTE4_BIT (1<<2) | ||
622 | |||
623 | #define SPI_PHASE0_REG 3 | ||
624 | #define SPI_PHASE1_REG 3 | ||
625 | #define SPI_PHASE2_REG 3 | ||
626 | #define SPI_PHASE4_REG 15 | ||
627 | #define SPI_PHASE0_BIT (1<<6) | ||
628 | #define SPI_PHASE1_BIT (1<<7) | ||
629 | #define SPI_PHASE2_BIT (1<<8) | ||
630 | #define SPI_PHASE4_BIT (1<<3) | ||
631 | |||
632 | #define SPI_PDWN_REG 2 /* power down all DACs */ | ||
633 | #define SPI_PDWN_BIT (1<<2) | ||
634 | #define SPI_DACD0_REG 10 /* power down individual DACs */ | ||
635 | #define SPI_DACD1_REG 10 | ||
636 | #define SPI_DACD2_REG 10 | ||
637 | #define SPI_DACD4_REG 15 | ||
638 | #define SPI_DACD0_BIT (1<<1) | ||
639 | #define SPI_DACD1_BIT (1<<2) | ||
640 | #define SPI_DACD2_BIT (1<<3) | ||
641 | #define SPI_DACD4_BIT (1<<0) /* datasheet error says it's 1 */ | ||
642 | |||
643 | #define SPI_PWRDNALL_REG 10 /* power down everything */ | ||
644 | #define SPI_PWRDNALL_BIT (1<<4) | ||
645 | |||
555 | #include "ca_midi.h" | 646 | #include "ca_midi.h" |
556 | 647 | ||
557 | struct snd_ca0106; | 648 | struct snd_ca0106; |
@@ -611,6 +702,8 @@ struct snd_ca0106 { | |||
611 | 702 | ||
612 | struct snd_ca_midi midi; | 703 | struct snd_ca_midi midi; |
613 | struct snd_ca_midi midi2; | 704 | struct snd_ca_midi midi2; |
705 | |||
706 | u16 spi_dac_reg[16]; | ||
614 | }; | 707 | }; |
615 | 708 | ||
616 | int snd_ca0106_mixer(struct snd_ca0106 *emu); | 709 | int snd_ca0106_mixer(struct snd_ca0106 *emu); |
@@ -627,4 +720,5 @@ void snd_ca0106_ptr_write(struct snd_ca0106 *emu, | |||
627 | 720 | ||
628 | int snd_ca0106_i2c_write(struct snd_ca0106 *emu, u32 reg, u32 value); | 721 | int snd_ca0106_i2c_write(struct snd_ca0106 *emu, u32 reg, u32 value); |
629 | 722 | ||
630 | 723 | int snd_ca0106_spi_write(struct snd_ca0106 * emu, | |
724 | unsigned int data); | ||
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index fcab8fb97e38..31d8db9f7a4c 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk> | 2 | * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk> |
3 | * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit | 3 | * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit |
4 | * Version: 0.0.23 | 4 | * Version: 0.0.25 |
5 | * | 5 | * |
6 | * FEATURES currently supported: | 6 | * FEATURES currently supported: |
7 | * Front, Rear and Center/LFE. | 7 | * Front, Rear and Center/LFE. |
@@ -79,6 +79,10 @@ | |||
79 | * Add support for MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97. From kiksen, bug #901 | 79 | * Add support for MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97. From kiksen, bug #901 |
80 | * 0.0.23 | 80 | * 0.0.23 |
81 | * Implement support for Line-in capture on SB Live 24bit. | 81 | * Implement support for Line-in capture on SB Live 24bit. |
82 | * 0.0.24 | ||
83 | * Add support for mute control on SB Live 24bit (cards w/ SPI DAC) | ||
84 | * 0.0.25 | ||
85 | * Powerdown SPI DAC channels when not in use | ||
82 | * | 86 | * |
83 | * BUGS: | 87 | * BUGS: |
84 | * Some stability problems when unloading the snd-ca0106 kernel module. | 88 | * Some stability problems when unloading the snd-ca0106 kernel module. |
@@ -170,6 +174,15 @@ MODULE_PARM_DESC(subsystem, "Force card subsystem model."); | |||
170 | static struct snd_ca0106_details ca0106_chip_details[] = { | 174 | static struct snd_ca0106_details ca0106_chip_details[] = { |
171 | /* Sound Blaster X-Fi Extreme Audio. This does not have an AC97. 53SB079000000 */ | 175 | /* Sound Blaster X-Fi Extreme Audio. This does not have an AC97. 53SB079000000 */ |
172 | /* It is really just a normal SB Live 24bit. */ | 176 | /* It is really just a normal SB Live 24bit. */ |
177 | /* Tested: | ||
178 | * See ALSA bug#3251 | ||
179 | */ | ||
180 | { .serial = 0x10131102, | ||
181 | .name = "X-Fi Extreme Audio [SBxxxx]", | ||
182 | .gpio_type = 1, | ||
183 | .i2c_adc = 1 } , | ||
184 | /* Sound Blaster X-Fi Extreme Audio. This does not have an AC97. 53SB079000000 */ | ||
185 | /* It is really just a normal SB Live 24bit. */ | ||
173 | /* | 186 | /* |
174 | * CTRL:CA0111-WTLF | 187 | * CTRL:CA0111-WTLF |
175 | * ADC: WM8775SEDS | 188 | * ADC: WM8775SEDS |
@@ -261,10 +274,11 @@ static struct snd_ca0106_details ca0106_chip_details[] = { | |||
261 | 274 | ||
262 | /* hardware definition */ | 275 | /* hardware definition */ |
263 | static struct snd_pcm_hardware snd_ca0106_playback_hw = { | 276 | static struct snd_pcm_hardware snd_ca0106_playback_hw = { |
264 | .info = (SNDRV_PCM_INFO_MMAP | | 277 | .info = SNDRV_PCM_INFO_MMAP | |
265 | SNDRV_PCM_INFO_INTERLEAVED | | 278 | SNDRV_PCM_INFO_INTERLEAVED | |
266 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 279 | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
267 | SNDRV_PCM_INFO_MMAP_VALID), | 280 | SNDRV_PCM_INFO_MMAP_VALID | |
281 | SNDRV_PCM_INFO_SYNC_START, | ||
268 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, | 282 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, |
269 | .rates = (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | | 283 | .rates = (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | |
270 | SNDRV_PCM_RATE_192000), | 284 | SNDRV_PCM_RATE_192000), |
@@ -447,6 +461,19 @@ static void snd_ca0106_pcm_free_substream(struct snd_pcm_runtime *runtime) | |||
447 | kfree(runtime->private_data); | 461 | kfree(runtime->private_data); |
448 | } | 462 | } |
449 | 463 | ||
464 | static const int spi_dacd_reg[] = { | ||
465 | [PCM_FRONT_CHANNEL] = SPI_DACD4_REG, | ||
466 | [PCM_REAR_CHANNEL] = SPI_DACD0_REG, | ||
467 | [PCM_CENTER_LFE_CHANNEL]= SPI_DACD2_REG, | ||
468 | [PCM_UNKNOWN_CHANNEL] = SPI_DACD1_REG, | ||
469 | }; | ||
470 | static const int spi_dacd_bit[] = { | ||
471 | [PCM_FRONT_CHANNEL] = SPI_DACD4_BIT, | ||
472 | [PCM_REAR_CHANNEL] = SPI_DACD0_BIT, | ||
473 | [PCM_CENTER_LFE_CHANNEL]= SPI_DACD2_BIT, | ||
474 | [PCM_UNKNOWN_CHANNEL] = SPI_DACD1_BIT, | ||
475 | }; | ||
476 | |||
450 | /* open_playback callback */ | 477 | /* open_playback callback */ |
451 | static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substream, | 478 | static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substream, |
452 | int channel_id) | 479 | int channel_id) |
@@ -481,6 +508,17 @@ static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substr | |||
481 | return err; | 508 | return err; |
482 | if ((err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64)) < 0) | 509 | if ((err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64)) < 0) |
483 | return err; | 510 | return err; |
511 | snd_pcm_set_sync(substream); | ||
512 | |||
513 | if (chip->details->spi_dac && channel_id != PCM_FRONT_CHANNEL) { | ||
514 | const int reg = spi_dacd_reg[channel_id]; | ||
515 | |||
516 | /* Power up dac */ | ||
517 | chip->spi_dac_reg[reg] &= ~spi_dacd_bit[channel_id]; | ||
518 | err = snd_ca0106_spi_write(chip, chip->spi_dac_reg[reg]); | ||
519 | if (err < 0) | ||
520 | return err; | ||
521 | } | ||
484 | return 0; | 522 | return 0; |
485 | } | 523 | } |
486 | 524 | ||
@@ -491,6 +529,14 @@ static int snd_ca0106_pcm_close_playback(struct snd_pcm_substream *substream) | |||
491 | struct snd_pcm_runtime *runtime = substream->runtime; | 529 | struct snd_pcm_runtime *runtime = substream->runtime; |
492 | struct snd_ca0106_pcm *epcm = runtime->private_data; | 530 | struct snd_ca0106_pcm *epcm = runtime->private_data; |
493 | chip->playback_channels[epcm->channel_id].use = 0; | 531 | chip->playback_channels[epcm->channel_id].use = 0; |
532 | |||
533 | if (chip->details->spi_dac && epcm->channel_id != PCM_FRONT_CHANNEL) { | ||
534 | const int reg = spi_dacd_reg[epcm->channel_id]; | ||
535 | |||
536 | /* Power down DAC */ | ||
537 | chip->spi_dac_reg[reg] |= spi_dacd_bit[epcm->channel_id]; | ||
538 | snd_ca0106_spi_write(chip, chip->spi_dac_reg[reg]); | ||
539 | } | ||
494 | /* FIXME: maybe zero others */ | 540 | /* FIXME: maybe zero others */ |
495 | return 0; | 541 | return 0; |
496 | } | 542 | } |
@@ -809,6 +855,9 @@ static int snd_ca0106_pcm_trigger_playback(struct snd_pcm_substream *substream, | |||
809 | break; | 855 | break; |
810 | } | 856 | } |
811 | snd_pcm_group_for_each_entry(s, substream) { | 857 | snd_pcm_group_for_each_entry(s, substream) { |
858 | if (snd_pcm_substream_chip(s) != emu || | ||
859 | s->stream != SNDRV_PCM_STREAM_PLAYBACK) | ||
860 | continue; | ||
812 | runtime = s->runtime; | 861 | runtime = s->runtime; |
813 | epcm = runtime->private_data; | 862 | epcm = runtime->private_data; |
814 | channel = epcm->channel_id; | 863 | channel = epcm->channel_id; |
@@ -1214,28 +1263,23 @@ static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device, struct s | |||
1214 | return 0; | 1263 | return 0; |
1215 | } | 1264 | } |
1216 | 1265 | ||
1266 | #define SPI_REG(reg, value) (((reg) << SPI_REG_SHIFT) | (value)) | ||
1217 | static unsigned int spi_dac_init[] = { | 1267 | static unsigned int spi_dac_init[] = { |
1218 | 0x00ff, | 1268 | SPI_REG(SPI_LDA1_REG, SPI_DA_BIT_0dB), /* 0dB dig. attenuation */ |
1219 | 0x02ff, | 1269 | SPI_REG(SPI_RDA1_REG, SPI_DA_BIT_0dB), |
1220 | 0x0400, | 1270 | SPI_REG(SPI_PL_REG, SPI_PL_BIT_L_L | SPI_PL_BIT_R_R | SPI_IZD_BIT), |
1221 | 0x0520, | 1271 | SPI_REG(SPI_FMT_REG, SPI_FMT_BIT_I2S | SPI_IWL_BIT_24), |
1222 | 0x0620, /* Set 24 bit. Was 0x0600 */ | 1272 | SPI_REG(SPI_LDA2_REG, SPI_DA_BIT_0dB), |
1223 | 0x08ff, | 1273 | SPI_REG(SPI_RDA2_REG, SPI_DA_BIT_0dB), |
1224 | 0x0aff, | 1274 | SPI_REG(SPI_LDA3_REG, SPI_DA_BIT_0dB), |
1225 | 0x0cff, | 1275 | SPI_REG(SPI_RDA3_REG, SPI_DA_BIT_0dB), |
1226 | 0x0eff, | 1276 | SPI_REG(SPI_MASTDA_REG, SPI_DA_BIT_0dB), |
1227 | 0x10ff, | 1277 | SPI_REG(9, 0x00), |
1228 | 0x1200, | 1278 | SPI_REG(SPI_MS_REG, SPI_DACD0_BIT | SPI_DACD1_BIT | SPI_DACD2_BIT), |
1229 | 0x1400, | 1279 | SPI_REG(12, 0x00), |
1230 | 0x1480, | 1280 | SPI_REG(SPI_LDA4_REG, SPI_DA_BIT_0dB), |
1231 | 0x1800, | 1281 | SPI_REG(SPI_RDA4_REG, SPI_DA_BIT_0dB | SPI_DA_BIT_UPDATE), |
1232 | 0x1aff, | 1282 | SPI_REG(SPI_DACD4_REG, 0x00), |
1233 | 0x1cff, | ||
1234 | 0x1e00, | ||
1235 | 0x0530, | ||
1236 | 0x0602, | ||
1237 | 0x0622, | ||
1238 | 0x1400, | ||
1239 | }; | 1283 | }; |
1240 | 1284 | ||
1241 | static unsigned int i2c_adc_init[][2] = { | 1285 | static unsigned int i2c_adc_init[][2] = { |
@@ -1475,8 +1519,13 @@ static int __devinit snd_ca0106_create(int dev, struct snd_card *card, | |||
1475 | int size, n; | 1519 | int size, n; |
1476 | 1520 | ||
1477 | size = ARRAY_SIZE(spi_dac_init); | 1521 | size = ARRAY_SIZE(spi_dac_init); |
1478 | for (n=0; n < size; n++) | 1522 | for (n = 0; n < size; n++) { |
1523 | int reg = spi_dac_init[n] >> SPI_REG_SHIFT; | ||
1524 | |||
1479 | snd_ca0106_spi_write(chip, spi_dac_init[n]); | 1525 | snd_ca0106_spi_write(chip, spi_dac_init[n]); |
1526 | if (reg < ARRAY_SIZE(chip->spi_dac_reg)) | ||
1527 | chip->spi_dac_reg[reg] = spi_dac_init[n]; | ||
1528 | } | ||
1480 | } | 1529 | } |
1481 | 1530 | ||
1482 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, | 1531 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, |
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c index 9c3a9c8d1dc2..be519a17dfa5 100644 --- a/sound/pci/ca0106/ca0106_mixer.c +++ b/sound/pci/ca0106/ca0106_mixer.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk> | 2 | * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk> |
3 | * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit | 3 | * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit |
4 | * Version: 0.0.17 | 4 | * Version: 0.0.18 |
5 | * | 5 | * |
6 | * FEATURES currently supported: | 6 | * FEATURES currently supported: |
7 | * See ca0106_main.c for features. | 7 | * See ca0106_main.c for features. |
@@ -39,6 +39,8 @@ | |||
39 | * Modified Copyright message. | 39 | * Modified Copyright message. |
40 | * 0.0.17 | 40 | * 0.0.17 |
41 | * Implement Mic and Line in Capture. | 41 | * Implement Mic and Line in Capture. |
42 | * 0.0.18 | ||
43 | * Add support for mute control on SB Live 24bit (cards w/ SPI DAC) | ||
42 | * | 44 | * |
43 | * This code was initally based on code from ALSA's emu10k1x.c which is: | 45 | * This code was initally based on code from ALSA's emu10k1x.c which is: |
44 | * Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com> | 46 | * Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com> |
@@ -77,15 +79,7 @@ | |||
77 | static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale1, -5175, 25, 1); | 79 | static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale1, -5175, 25, 1); |
78 | static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale2, -10350, 50, 1); | 80 | static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale2, -10350, 50, 1); |
79 | 81 | ||
80 | static int snd_ca0106_shared_spdif_info(struct snd_kcontrol *kcontrol, | 82 | #define snd_ca0106_shared_spdif_info snd_ctl_boolean_mono_info |
81 | struct snd_ctl_elem_info *uinfo) | ||
82 | { | ||
83 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
84 | uinfo->count = 1; | ||
85 | uinfo->value.integer.min = 0; | ||
86 | uinfo->value.integer.max = 1; | ||
87 | return 0; | ||
88 | } | ||
89 | 83 | ||
90 | static int snd_ca0106_shared_spdif_get(struct snd_kcontrol *kcontrol, | 84 | static int snd_ca0106_shared_spdif_get(struct snd_kcontrol *kcontrol, |
91 | struct snd_ctl_elem_value *ucontrol) | 85 | struct snd_ctl_elem_value *ucontrol) |
@@ -470,6 +464,42 @@ static int snd_ca0106_i2c_volume_put(struct snd_kcontrol *kcontrol, | |||
470 | return change; | 464 | return change; |
471 | } | 465 | } |
472 | 466 | ||
467 | #define spi_mute_info snd_ctl_boolean_mono_info | ||
468 | |||
469 | static int spi_mute_get(struct snd_kcontrol *kcontrol, | ||
470 | struct snd_ctl_elem_value *ucontrol) | ||
471 | { | ||
472 | struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); | ||
473 | unsigned int reg = kcontrol->private_value >> SPI_REG_SHIFT; | ||
474 | unsigned int bit = kcontrol->private_value & SPI_REG_MASK; | ||
475 | |||
476 | ucontrol->value.integer.value[0] = !(emu->spi_dac_reg[reg] & bit); | ||
477 | return 0; | ||
478 | } | ||
479 | |||
480 | static int spi_mute_put(struct snd_kcontrol *kcontrol, | ||
481 | struct snd_ctl_elem_value *ucontrol) | ||
482 | { | ||
483 | struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); | ||
484 | unsigned int reg = kcontrol->private_value >> SPI_REG_SHIFT; | ||
485 | unsigned int bit = kcontrol->private_value & SPI_REG_MASK; | ||
486 | int ret; | ||
487 | |||
488 | ret = emu->spi_dac_reg[reg] & bit; | ||
489 | if (ucontrol->value.integer.value[0]) { | ||
490 | if (!ret) /* bit already cleared, do nothing */ | ||
491 | return 0; | ||
492 | emu->spi_dac_reg[reg] &= ~bit; | ||
493 | } else { | ||
494 | if (ret) /* bit already set, do nothing */ | ||
495 | return 0; | ||
496 | emu->spi_dac_reg[reg] |= bit; | ||
497 | } | ||
498 | |||
499 | ret = snd_ca0106_spi_write(emu, emu->spi_dac_reg[reg]); | ||
500 | return ret ? -1 : 1; | ||
501 | } | ||
502 | |||
473 | #define CA_VOLUME(xname,chid,reg) \ | 503 | #define CA_VOLUME(xname,chid,reg) \ |
474 | { \ | 504 | { \ |
475 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | 505 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ |
@@ -562,6 +592,28 @@ static struct snd_kcontrol_new snd_ca0106_volume_i2c_adc_ctls[] __devinitdata = | |||
562 | I2C_VOLUME("Aux Capture Volume", 3), | 592 | I2C_VOLUME("Aux Capture Volume", 3), |
563 | }; | 593 | }; |
564 | 594 | ||
595 | #define SPI_SWITCH(xname,reg,bit) \ | ||
596 | { \ | ||
597 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | ||
598 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ | ||
599 | .info = spi_mute_info, \ | ||
600 | .get = spi_mute_get, \ | ||
601 | .put = spi_mute_put, \ | ||
602 | .private_value = (reg<<SPI_REG_SHIFT) | (bit) \ | ||
603 | } | ||
604 | |||
605 | static struct snd_kcontrol_new snd_ca0106_volume_spi_dac_ctls[] | ||
606 | __devinitdata = { | ||
607 | SPI_SWITCH("Analog Front Playback Switch", | ||
608 | SPI_DMUTE4_REG, SPI_DMUTE4_BIT), | ||
609 | SPI_SWITCH("Analog Rear Playback Switch", | ||
610 | SPI_DMUTE0_REG, SPI_DMUTE0_BIT), | ||
611 | SPI_SWITCH("Analog Center/LFE Playback Switch", | ||
612 | SPI_DMUTE2_REG, SPI_DMUTE2_BIT), | ||
613 | SPI_SWITCH("Analog Side Playback Switch", | ||
614 | SPI_DMUTE1_REG, SPI_DMUTE1_BIT), | ||
615 | }; | ||
616 | |||
565 | static int __devinit remove_ctl(struct snd_card *card, const char *name) | 617 | static int __devinit remove_ctl(struct snd_card *card, const char *name) |
566 | { | 618 | { |
567 | struct snd_ctl_elem_id id; | 619 | struct snd_ctl_elem_id id; |
@@ -591,9 +643,19 @@ static int __devinit rename_ctl(struct snd_card *card, const char *src, const ch | |||
591 | return -ENOENT; | 643 | return -ENOENT; |
592 | } | 644 | } |
593 | 645 | ||
646 | #define ADD_CTLS(emu, ctls) \ | ||
647 | do { \ | ||
648 | int i, err; \ | ||
649 | for (i = 0; i < ARRAY_SIZE(ctls); i++) { \ | ||
650 | err = snd_ctl_add(card, snd_ctl_new1(&ctls[i], emu)); \ | ||
651 | if (err < 0) \ | ||
652 | return err; \ | ||
653 | } \ | ||
654 | } while (0) | ||
655 | |||
594 | int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu) | 656 | int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu) |
595 | { | 657 | { |
596 | int i, err; | 658 | int err; |
597 | struct snd_card *card = emu->card; | 659 | struct snd_card *card = emu->card; |
598 | char **c; | 660 | char **c; |
599 | static char *ca0106_remove_ctls[] = { | 661 | static char *ca0106_remove_ctls[] = { |
@@ -640,17 +702,9 @@ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu) | |||
640 | rename_ctl(card, c[0], c[1]); | 702 | rename_ctl(card, c[0], c[1]); |
641 | #endif | 703 | #endif |
642 | 704 | ||
643 | for (i = 0; i < ARRAY_SIZE(snd_ca0106_volume_ctls); i++) { | 705 | ADD_CTLS(emu, snd_ca0106_volume_ctls); |
644 | err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_volume_ctls[i], emu)); | ||
645 | if (err < 0) | ||
646 | return err; | ||
647 | } | ||
648 | if (emu->details->i2c_adc == 1) { | 706 | if (emu->details->i2c_adc == 1) { |
649 | for (i = 0; i < ARRAY_SIZE(snd_ca0106_volume_i2c_adc_ctls); i++) { | 707 | ADD_CTLS(emu, snd_ca0106_volume_i2c_adc_ctls); |
650 | err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_volume_i2c_adc_ctls[i], emu)); | ||
651 | if (err < 0) | ||
652 | return err; | ||
653 | } | ||
654 | if (emu->details->gpio_type == 1) | 708 | if (emu->details->gpio_type == 1) |
655 | err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu)); | 709 | err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu)); |
656 | else /* gpio_type == 2 */ | 710 | else /* gpio_type == 2 */ |
@@ -658,6 +712,8 @@ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu) | |||
658 | if (err < 0) | 712 | if (err < 0) |
659 | return err; | 713 | return err; |
660 | } | 714 | } |
715 | if (emu->details->spi_dac == 1) | ||
716 | ADD_CTLS(emu, snd_ca0106_volume_spi_dac_ctls); | ||
661 | return 0; | 717 | return 0; |
662 | } | 718 | } |
663 | 719 | ||
diff --git a/sound/pci/ca0106/ca_midi.c b/sound/pci/ca0106/ca_midi.c index 2e6eab1f1189..ad32eff2713f 100644 --- a/sound/pci/ca0106/ca_midi.c +++ b/sound/pci/ca0106/ca_midi.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * Changelog: | 6 | * Changelog: |
7 | * Implementation is based on mpu401 and emu10k1x and | 7 | * Implementation is based on mpu401 and emu10k1x and |
8 | * tested with ca0106. | 8 | * tested with ca0106. |
9 | * mpu401: Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 9 | * mpu401: Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
10 | * emu10k1x: Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com> | 10 | * emu10k1x: Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com> |
11 | * | 11 | * |
12 | * This program is free software; you can redistribute it and/or modify | 12 | * This program is free software; you can redistribute it and/or modify |
diff --git a/sound/pci/ca0106/ca_midi.h b/sound/pci/ca0106/ca_midi.h index b72c0933bd22..922ed3e3731e 100644 --- a/sound/pci/ca0106/ca_midi.h +++ b/sound/pci/ca0106/ca_midi.h | |||
@@ -22,9 +22,9 @@ | |||
22 | * | 22 | * |
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include<linux/spinlock.h> | 25 | #include <linux/spinlock.h> |
26 | #include<sound/rawmidi.h> | 26 | #include <sound/rawmidi.h> |
27 | #include<sound/mpu401.h> | 27 | #include <sound/mpu401.h> |
28 | 28 | ||
29 | #define CA_MIDI_MODE_INPUT MPU401_MODE_INPUT | 29 | #define CA_MIDI_MODE_INPUT MPU401_MODE_INPUT |
30 | #define CA_MIDI_MODE_OUTPUT MPU401_MODE_OUTPUT | 30 | #define CA_MIDI_MODE_OUTPUT MPU401_MODE_OUTPUT |
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index 7d3c5ee0005c..6832649879ce 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c | |||
@@ -95,30 +95,34 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address."); | |||
95 | #define CM_CHADC0 0x00000001 /* ch0, 0:playback, 1:record */ | 95 | #define CM_CHADC0 0x00000001 /* ch0, 0:playback, 1:record */ |
96 | 96 | ||
97 | #define CM_REG_FUNCTRL1 0x04 | 97 | #define CM_REG_FUNCTRL1 0x04 |
98 | #define CM_ASFC_MASK 0x0000E000 /* ADC sampling frequency */ | 98 | #define CM_DSFC_MASK 0x0000E000 /* channel 1 (DAC?) sampling frequency */ |
99 | #define CM_ASFC_SHIFT 13 | 99 | #define CM_DSFC_SHIFT 13 |
100 | #define CM_DSFC_MASK 0x00001C00 /* DAC sampling frequency */ | 100 | #define CM_ASFC_MASK 0x00001C00 /* channel 0 (ADC?) sampling frequency */ |
101 | #define CM_DSFC_SHIFT 10 | 101 | #define CM_ASFC_SHIFT 10 |
102 | #define CM_SPDF_1 0x00000200 /* SPDIF IN/OUT at channel B */ | 102 | #define CM_SPDF_1 0x00000200 /* SPDIF IN/OUT at channel B */ |
103 | #define CM_SPDF_0 0x00000100 /* SPDIF OUT only channel A */ | 103 | #define CM_SPDF_0 0x00000100 /* SPDIF OUT only channel A */ |
104 | #define CM_SPDFLOOP 0x00000080 /* ext. SPDIIF/OUT -> IN loopback */ | 104 | #define CM_SPDFLOOP 0x00000080 /* ext. SPDIIF/IN -> OUT loopback */ |
105 | #define CM_SPDO2DAC 0x00000040 /* SPDIF/OUT can be heard from internal DAC */ | 105 | #define CM_SPDO2DAC 0x00000040 /* SPDIF/OUT can be heard from internal DAC */ |
106 | #define CM_INTRM 0x00000020 /* master control block (MCB) interrupt enabled */ | 106 | #define CM_INTRM 0x00000020 /* master control block (MCB) interrupt enabled */ |
107 | #define CM_BREQ 0x00000010 /* bus master enabled */ | 107 | #define CM_BREQ 0x00000010 /* bus master enabled */ |
108 | #define CM_VOICE_EN 0x00000008 /* legacy voice (SB16,FM) */ | 108 | #define CM_VOICE_EN 0x00000008 /* legacy voice (SB16,FM) */ |
109 | #define CM_UART_EN 0x00000004 /* UART */ | 109 | #define CM_UART_EN 0x00000004 /* legacy UART */ |
110 | #define CM_JYSTK_EN 0x00000002 /* joy stick */ | 110 | #define CM_JYSTK_EN 0x00000002 /* legacy joystick */ |
111 | #define CM_ZVPORT 0x00000001 /* ZVPORT */ | ||
111 | 112 | ||
112 | #define CM_REG_CHFORMAT 0x08 | 113 | #define CM_REG_CHFORMAT 0x08 |
113 | 114 | ||
114 | #define CM_CHB3D5C 0x80000000 /* 5,6 channels */ | 115 | #define CM_CHB3D5C 0x80000000 /* 5,6 channels */ |
116 | #define CM_FMOFFSET2 0x40000000 /* initial FM PCM offset 2 when Fmute=1 */ | ||
115 | #define CM_CHB3D 0x20000000 /* 4 channels */ | 117 | #define CM_CHB3D 0x20000000 /* 4 channels */ |
116 | 118 | ||
117 | #define CM_CHIP_MASK1 0x1f000000 | 119 | #define CM_CHIP_MASK1 0x1f000000 |
118 | #define CM_CHIP_037 0x01000000 | 120 | #define CM_CHIP_037 0x01000000 |
119 | 121 | #define CM_SETLAT48 0x00800000 /* set latency timer 48h */ | |
120 | #define CM_SPDIF_SELECT1 0x00080000 /* for model <= 037 ? */ | 122 | #define CM_EDGEIRQ 0x00400000 /* emulated edge trigger legacy IRQ */ |
123 | #define CM_SPD24SEL39 0x00200000 /* 24-bit spdif: model 039 */ | ||
121 | #define CM_AC3EN1 0x00100000 /* enable AC3: model 037 */ | 124 | #define CM_AC3EN1 0x00100000 /* enable AC3: model 037 */ |
125 | #define CM_SPDIF_SELECT1 0x00080000 /* for model <= 037 ? */ | ||
122 | #define CM_SPD24SEL 0x00020000 /* 24bit spdif: model 037 */ | 126 | #define CM_SPD24SEL 0x00020000 /* 24bit spdif: model 037 */ |
123 | /* #define CM_SPDIF_INVERSE 0x00010000 */ /* ??? */ | 127 | /* #define CM_SPDIF_INVERSE 0x00010000 */ /* ??? */ |
124 | 128 | ||
@@ -128,35 +132,45 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address."); | |||
128 | #define CM_ADCBITLEN_14 0x00008000 | 132 | #define CM_ADCBITLEN_14 0x00008000 |
129 | #define CM_ADCBITLEN_13 0x0000C000 | 133 | #define CM_ADCBITLEN_13 0x0000C000 |
130 | 134 | ||
131 | #define CM_ADCDACLEN_MASK 0x00003000 | 135 | #define CM_ADCDACLEN_MASK 0x00003000 /* model 037 */ |
132 | #define CM_ADCDACLEN_060 0x00000000 | 136 | #define CM_ADCDACLEN_060 0x00000000 |
133 | #define CM_ADCDACLEN_066 0x00001000 | 137 | #define CM_ADCDACLEN_066 0x00001000 |
134 | #define CM_ADCDACLEN_130 0x00002000 | 138 | #define CM_ADCDACLEN_130 0x00002000 |
135 | #define CM_ADCDACLEN_280 0x00003000 | 139 | #define CM_ADCDACLEN_280 0x00003000 |
136 | 140 | ||
141 | #define CM_ADCDLEN_MASK 0x00003000 /* model 039 */ | ||
142 | #define CM_ADCDLEN_ORIGINAL 0x00000000 | ||
143 | #define CM_ADCDLEN_EXTRA 0x00001000 | ||
144 | #define CM_ADCDLEN_24K 0x00002000 | ||
145 | #define CM_ADCDLEN_WEIGHT 0x00003000 | ||
146 | |||
137 | #define CM_CH1_SRATE_176K 0x00000800 | 147 | #define CM_CH1_SRATE_176K 0x00000800 |
148 | #define CM_CH1_SRATE_96K 0x00000800 /* model 055? */ | ||
138 | #define CM_CH1_SRATE_88K 0x00000400 | 149 | #define CM_CH1_SRATE_88K 0x00000400 |
139 | #define CM_CH0_SRATE_176K 0x00000200 | 150 | #define CM_CH0_SRATE_176K 0x00000200 |
151 | #define CM_CH0_SRATE_96K 0x00000200 /* model 055? */ | ||
140 | #define CM_CH0_SRATE_88K 0x00000100 | 152 | #define CM_CH0_SRATE_88K 0x00000100 |
141 | 153 | ||
142 | #define CM_SPDIF_INVERSE2 0x00000080 /* model 055? */ | 154 | #define CM_SPDIF_INVERSE2 0x00000080 /* model 055? */ |
155 | #define CM_DBLSPDS 0x00000040 /* double SPDIF sample rate 88.2/96 */ | ||
156 | #define CM_POLVALID 0x00000020 /* inverse SPDIF/IN valid bit */ | ||
157 | #define CM_SPDLOCKED 0x00000010 | ||
143 | 158 | ||
144 | #define CM_CH1FMT_MASK 0x0000000C | 159 | #define CM_CH1FMT_MASK 0x0000000C /* bit 3: 16 bits, bit 2: stereo */ |
145 | #define CM_CH1FMT_SHIFT 2 | 160 | #define CM_CH1FMT_SHIFT 2 |
146 | #define CM_CH0FMT_MASK 0x00000003 | 161 | #define CM_CH0FMT_MASK 0x00000003 /* bit 1: 16 bits, bit 0: stereo */ |
147 | #define CM_CH0FMT_SHIFT 0 | 162 | #define CM_CH0FMT_SHIFT 0 |
148 | 163 | ||
149 | #define CM_REG_INT_HLDCLR 0x0C | 164 | #define CM_REG_INT_HLDCLR 0x0C |
150 | #define CM_CHIP_MASK2 0xff000000 | 165 | #define CM_CHIP_MASK2 0xff000000 |
166 | #define CM_CHIP_8768 0x20000000 | ||
167 | #define CM_CHIP_055 0x08000000 | ||
151 | #define CM_CHIP_039 0x04000000 | 168 | #define CM_CHIP_039 0x04000000 |
152 | #define CM_CHIP_039_6CH 0x01000000 | 169 | #define CM_CHIP_039_6CH 0x01000000 |
153 | #define CM_CHIP_055 0x08000000 | 170 | #define CM_UNKNOWN_INT_EN 0x00080000 /* ? */ |
154 | #define CM_CHIP_8768 0x20000000 | ||
155 | #define CM_TDMA_INT_EN 0x00040000 | 171 | #define CM_TDMA_INT_EN 0x00040000 |
156 | #define CM_CH1_INT_EN 0x00020000 | 172 | #define CM_CH1_INT_EN 0x00020000 |
157 | #define CM_CH0_INT_EN 0x00010000 | 173 | #define CM_CH0_INT_EN 0x00010000 |
158 | #define CM_INT_HOLD 0x00000002 | ||
159 | #define CM_INT_CLEAR 0x00000001 | ||
160 | 174 | ||
161 | #define CM_REG_INT_STATUS 0x10 | 175 | #define CM_REG_INT_STATUS 0x10 |
162 | #define CM_INTR 0x80000000 | 176 | #define CM_INTR 0x80000000 |
@@ -175,12 +189,13 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address."); | |||
175 | #define CM_CHINT0 0x00000001 | 189 | #define CM_CHINT0 0x00000001 |
176 | 190 | ||
177 | #define CM_REG_LEGACY_CTRL 0x14 | 191 | #define CM_REG_LEGACY_CTRL 0x14 |
178 | #define CM_NXCHG 0x80000000 /* h/w multi channels? */ | 192 | #define CM_NXCHG 0x80000000 /* don't map base reg dword->sample */ |
179 | #define CM_VMPU_MASK 0x60000000 /* MPU401 i/o port address */ | 193 | #define CM_VMPU_MASK 0x60000000 /* MPU401 i/o port address */ |
180 | #define CM_VMPU_330 0x00000000 | 194 | #define CM_VMPU_330 0x00000000 |
181 | #define CM_VMPU_320 0x20000000 | 195 | #define CM_VMPU_320 0x20000000 |
182 | #define CM_VMPU_310 0x40000000 | 196 | #define CM_VMPU_310 0x40000000 |
183 | #define CM_VMPU_300 0x60000000 | 197 | #define CM_VMPU_300 0x60000000 |
198 | #define CM_ENWR8237 0x10000000 /* enable bus master to write 8237 base reg */ | ||
184 | #define CM_VSBSEL_MASK 0x0C000000 /* SB16 base address */ | 199 | #define CM_VSBSEL_MASK 0x0C000000 /* SB16 base address */ |
185 | #define CM_VSBSEL_220 0x00000000 | 200 | #define CM_VSBSEL_220 0x00000000 |
186 | #define CM_VSBSEL_240 0x04000000 | 201 | #define CM_VSBSEL_240 0x04000000 |
@@ -191,44 +206,74 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address."); | |||
191 | #define CM_FMSEL_3C8 0x01000000 | 206 | #define CM_FMSEL_3C8 0x01000000 |
192 | #define CM_FMSEL_3E0 0x02000000 | 207 | #define CM_FMSEL_3E0 0x02000000 |
193 | #define CM_FMSEL_3E8 0x03000000 | 208 | #define CM_FMSEL_3E8 0x03000000 |
194 | #define CM_ENSPDOUT 0x00800000 /* enable XPDIF/OUT to I/O interface */ | 209 | #define CM_ENSPDOUT 0x00800000 /* enable XSPDIF/OUT to I/O interface */ |
195 | #define CM_SPDCOPYRHT 0x00400000 /* set copyright spdif in/out */ | 210 | #define CM_SPDCOPYRHT 0x00400000 /* spdif in/out copyright bit */ |
196 | #define CM_DAC2SPDO 0x00200000 /* enable wave+fm_midi -> SPDIF/OUT */ | 211 | #define CM_DAC2SPDO 0x00200000 /* enable wave+fm_midi -> SPDIF/OUT */ |
197 | #define CM_SETRETRY 0x00010000 /* 0: legacy i/o wait (default), 1: legacy i/o bus retry */ | 212 | #define CM_INVIDWEN 0x00100000 /* internal vendor ID write enable, model 039? */ |
213 | #define CM_SETRETRY 0x00100000 /* 0: legacy i/o wait (default), 1: legacy i/o bus retry */ | ||
214 | #define CM_C_EEACCESS 0x00080000 /* direct programming eeprom regs */ | ||
215 | #define CM_C_EECS 0x00040000 | ||
216 | #define CM_C_EEDI46 0x00020000 | ||
217 | #define CM_C_EECK46 0x00010000 | ||
198 | #define CM_CHB3D6C 0x00008000 /* 5.1 channels support */ | 218 | #define CM_CHB3D6C 0x00008000 /* 5.1 channels support */ |
199 | #define CM_LINE_AS_BASS 0x00006000 /* use line-in as bass */ | 219 | #define CM_CENTR2LIN 0x00004000 /* line-in as center out */ |
220 | #define CM_BASE2LIN 0x00002000 /* line-in as bass out */ | ||
221 | #define CM_EXBASEN 0x00001000 /* external bass input enable */ | ||
200 | 222 | ||
201 | #define CM_REG_MISC_CTRL 0x18 | 223 | #define CM_REG_MISC_CTRL 0x18 |
202 | #define CM_PWD 0x80000000 | 224 | #define CM_PWD 0x80000000 /* power down */ |
203 | #define CM_RESET 0x40000000 | 225 | #define CM_RESET 0x40000000 |
204 | #define CM_SFIL_MASK 0x30000000 | 226 | #define CM_SFIL_MASK 0x30000000 /* filter control at front end DAC, model 037? */ |
205 | #define CM_TXVX 0x08000000 | 227 | #define CM_VMGAIN 0x10000000 /* analog master amp +6dB, model 039? */ |
206 | #define CM_N4SPK3D 0x04000000 /* 4ch output */ | 228 | #define CM_TXVX 0x08000000 /* model 037? */ |
229 | #define CM_N4SPK3D 0x04000000 /* copy front to rear */ | ||
207 | #define CM_SPDO5V 0x02000000 /* 5V spdif output (1 = 0.5v (coax)) */ | 230 | #define CM_SPDO5V 0x02000000 /* 5V spdif output (1 = 0.5v (coax)) */ |
208 | #define CM_SPDIF48K 0x01000000 /* write */ | 231 | #define CM_SPDIF48K 0x01000000 /* write */ |
209 | #define CM_SPATUS48K 0x01000000 /* read */ | 232 | #define CM_SPATUS48K 0x01000000 /* read */ |
210 | #define CM_ENDBDAC 0x00800000 /* enable dual dac */ | 233 | #define CM_ENDBDAC 0x00800000 /* enable double dac */ |
211 | #define CM_XCHGDAC 0x00400000 /* 0: front=ch0, 1: front=ch1 */ | 234 | #define CM_XCHGDAC 0x00400000 /* 0: front=ch0, 1: front=ch1 */ |
212 | #define CM_SPD32SEL 0x00200000 /* 0: 16bit SPDIF, 1: 32bit */ | 235 | #define CM_SPD32SEL 0x00200000 /* 0: 16bit SPDIF, 1: 32bit */ |
213 | #define CM_SPDFLOOPI 0x00100000 /* int. SPDIF-IN -> int. OUT */ | 236 | #define CM_SPDFLOOPI 0x00100000 /* int. SPDIF-OUT -> int. IN */ |
214 | #define CM_FM_EN 0x00080000 /* enalbe FM */ | 237 | #define CM_FM_EN 0x00080000 /* enable legacy FM */ |
215 | #define CM_AC3EN2 0x00040000 /* enable AC3: model 039 */ | 238 | #define CM_AC3EN2 0x00040000 /* enable AC3: model 039 */ |
216 | #define CM_VIDWPDSB 0x00010000 | 239 | #define CM_ENWRASID 0x00010000 /* choose writable internal SUBID (audio) */ |
240 | #define CM_VIDWPDSB 0x00010000 /* model 037? */ | ||
217 | #define CM_SPDF_AC97 0x00008000 /* 0: SPDIF/OUT 44.1K, 1: 48K */ | 241 | #define CM_SPDF_AC97 0x00008000 /* 0: SPDIF/OUT 44.1K, 1: 48K */ |
218 | #define CM_MASK_EN 0x00004000 | 242 | #define CM_MASK_EN 0x00004000 /* activate channel mask on legacy DMA */ |
219 | #define CM_VIDWPPRT 0x00002000 | 243 | #define CM_ENWRMSID 0x00002000 /* choose writable internal SUBID (modem) */ |
220 | #define CM_SFILENB 0x00001000 | 244 | #define CM_VIDWPPRT 0x00002000 /* model 037? */ |
221 | #define CM_MMODE_MASK 0x00000E00 | 245 | #define CM_SFILENB 0x00001000 /* filter stepping at front end DAC, model 037? */ |
246 | #define CM_MMODE_MASK 0x00000E00 /* model DAA interface mode */ | ||
222 | #define CM_SPDIF_SELECT2 0x00000100 /* for model > 039 ? */ | 247 | #define CM_SPDIF_SELECT2 0x00000100 /* for model > 039 ? */ |
223 | #define CM_ENCENTER 0x00000080 | 248 | #define CM_ENCENTER 0x00000080 |
224 | #define CM_FLINKON 0x00000040 | 249 | #define CM_FLINKON 0x00000080 /* force modem link detection on, model 037 */ |
225 | #define CM_FLINKOFF 0x00000020 | 250 | #define CM_MUTECH1 0x00000040 /* mute PCI ch1 to DAC */ |
226 | #define CM_MIDSMP 0x00000010 | 251 | #define CM_FLINKOFF 0x00000040 /* force modem link detection off, model 037 */ |
227 | #define CM_UPDDMA_MASK 0x0000000C | 252 | #define CM_UNKNOWN_18_5 0x00000020 /* ? */ |
228 | #define CM_TWAIT_MASK 0x00000003 | 253 | #define CM_MIDSMP 0x00000010 /* 1/2 interpolation at front end DAC */ |
254 | #define CM_UPDDMA_MASK 0x0000000C /* TDMA position update notification */ | ||
255 | #define CM_UPDDMA_2048 0x00000000 | ||
256 | #define CM_UPDDMA_1024 0x00000004 | ||
257 | #define CM_UPDDMA_512 0x00000008 | ||
258 | #define CM_UPDDMA_256 0x0000000C | ||
259 | #define CM_TWAIT_MASK 0x00000003 /* model 037 */ | ||
260 | #define CM_TWAIT1 0x00000002 /* FM i/o cycle, 0: 48, 1: 64 PCICLKs */ | ||
261 | #define CM_TWAIT0 0x00000001 /* i/o cycle, 0: 4, 1: 6 PCICLKs */ | ||
262 | |||
263 | #define CM_REG_TDMA_POSITION 0x1C | ||
264 | #define CM_TDMA_CNT_MASK 0xFFFF0000 /* current byte/word count */ | ||
265 | #define CM_TDMA_ADR_MASK 0x0000FFFF /* current address */ | ||
229 | 266 | ||
230 | /* byte */ | 267 | /* byte */ |
231 | #define CM_REG_MIXER0 0x20 | 268 | #define CM_REG_MIXER0 0x20 |
269 | #define CM_REG_SBVR 0x20 /* write: sb16 version */ | ||
270 | #define CM_REG_DEV 0x20 /* read: hardware device version */ | ||
271 | |||
272 | #define CM_REG_MIXER21 0x21 | ||
273 | #define CM_UNKNOWN_21_MASK 0x78 /* ? */ | ||
274 | #define CM_X_ADPCM 0x04 /* SB16 ADPCM enable */ | ||
275 | #define CM_PROINV 0x02 /* SBPro left/right channel switching */ | ||
276 | #define CM_X_SB16 0x01 /* SB16 compatible */ | ||
232 | 277 | ||
233 | #define CM_REG_SB16_DATA 0x22 | 278 | #define CM_REG_SB16_DATA 0x22 |
234 | #define CM_REG_SB16_ADDR 0x23 | 279 | #define CM_REG_SB16_ADDR 0x23 |
@@ -243,8 +288,8 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address."); | |||
243 | #define CM_FMMUTE_SHIFT 7 | 288 | #define CM_FMMUTE_SHIFT 7 |
244 | #define CM_WSMUTE 0x40 /* mute PCM */ | 289 | #define CM_WSMUTE 0x40 /* mute PCM */ |
245 | #define CM_WSMUTE_SHIFT 6 | 290 | #define CM_WSMUTE_SHIFT 6 |
246 | #define CM_SPK4 0x20 /* lin-in -> rear line out */ | 291 | #define CM_REAR2LIN 0x20 /* lin-in -> rear line out */ |
247 | #define CM_SPK4_SHIFT 5 | 292 | #define CM_REAR2LIN_SHIFT 5 |
248 | #define CM_REAR2FRONT 0x10 /* exchange rear/front */ | 293 | #define CM_REAR2FRONT 0x10 /* exchange rear/front */ |
249 | #define CM_REAR2FRONT_SHIFT 4 | 294 | #define CM_REAR2FRONT_SHIFT 4 |
250 | #define CM_WAVEINL 0x08 /* digital wave rec. left chan */ | 295 | #define CM_WAVEINL 0x08 /* digital wave rec. left chan */ |
@@ -276,12 +321,13 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address."); | |||
276 | #define CM_VAUXR_MASK 0x0f | 321 | #define CM_VAUXR_MASK 0x0f |
277 | 322 | ||
278 | #define CM_REG_MISC 0x27 | 323 | #define CM_REG_MISC 0x27 |
324 | #define CM_UNKNOWN_27_MASK 0xd8 /* ? */ | ||
279 | #define CM_XGPO1 0x20 | 325 | #define CM_XGPO1 0x20 |
280 | // #define CM_XGPBIO 0x04 | 326 | // #define CM_XGPBIO 0x04 |
281 | #define CM_MIC_CENTER_LFE 0x04 /* mic as center/lfe out? (model 039 or later?) */ | 327 | #define CM_MIC_CENTER_LFE 0x04 /* mic as center/lfe out? (model 039 or later?) */ |
282 | #define CM_SPDIF_INVERSE 0x04 /* spdif input phase inverse (model 037) */ | 328 | #define CM_SPDIF_INVERSE 0x04 /* spdif input phase inverse (model 037) */ |
283 | #define CM_SPDVALID 0x02 /* spdif input valid check */ | 329 | #define CM_SPDVALID 0x02 /* spdif input valid check */ |
284 | #define CM_DMAUTO 0x01 | 330 | #define CM_DMAUTO 0x01 /* SB16 DMA auto detect */ |
285 | 331 | ||
286 | #define CM_REG_AC97 0x28 /* hmmm.. do we have ac97 link? */ | 332 | #define CM_REG_AC97 0x28 /* hmmm.. do we have ac97 link? */ |
287 | /* | 333 | /* |
@@ -322,18 +368,20 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address."); | |||
322 | /* | 368 | /* |
323 | * extended registers | 369 | * extended registers |
324 | */ | 370 | */ |
325 | #define CM_REG_CH0_FRAME1 0x80 /* base address */ | 371 | #define CM_REG_CH0_FRAME1 0x80 /* write: base address */ |
326 | #define CM_REG_CH0_FRAME2 0x84 | 372 | #define CM_REG_CH0_FRAME2 0x84 /* read: current address */ |
327 | #define CM_REG_CH1_FRAME1 0x88 /* 0-15: count of samples at bus master; buffer size */ | 373 | #define CM_REG_CH1_FRAME1 0x88 /* 0-15: count of samples at bus master; buffer size */ |
328 | #define CM_REG_CH1_FRAME2 0x8C /* 16-31: count of samples at codec; fragment size */ | 374 | #define CM_REG_CH1_FRAME2 0x8C /* 16-31: count of samples at codec; fragment size */ |
375 | |||
329 | #define CM_REG_EXT_MISC 0x90 | 376 | #define CM_REG_EXT_MISC 0x90 |
330 | #define CM_REG_MISC_CTRL_8768 0x92 /* reg. name the same as 0x18 */ | 377 | #define CM_ADC48K44K 0x10000000 /* ADC parameters group, 0: 44k, 1: 48k */ |
331 | #define CM_CHB3D8C 0x20 /* 7.1 channels support */ | 378 | #define CM_CHB3D8C 0x00200000 /* 7.1 channels support */ |
332 | #define CM_SPD32FMT 0x10 /* SPDIF/IN 32k */ | 379 | #define CM_SPD32FMT 0x00100000 /* SPDIF/IN 32k sample rate */ |
333 | #define CM_ADC2SPDIF 0x08 /* ADC output to SPDIF/OUT */ | 380 | #define CM_ADC2SPDIF 0x00080000 /* ADC output to SPDIF/OUT */ |
334 | #define CM_SHAREADC 0x04 /* DAC in ADC as Center/LFE */ | 381 | #define CM_SHAREADC 0x00040000 /* DAC in ADC as Center/LFE */ |
335 | #define CM_REALTCMP 0x02 /* monitor the CMPL/CMPR of ADC */ | 382 | #define CM_REALTCMP 0x00020000 /* monitor the CMPL/CMPR of ADC */ |
336 | #define CM_INVLRCK 0x01 /* invert ZVPORT's LRCK */ | 383 | #define CM_INVLRCK 0x00010000 /* invert ZVPORT's LRCK */ |
384 | #define CM_UNKNOWN_90_MASK 0x0000FFFF /* ? */ | ||
337 | 385 | ||
338 | /* | 386 | /* |
339 | * size of i/o region | 387 | * size of i/o region |
@@ -383,15 +431,14 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address."); | |||
383 | 431 | ||
384 | struct cmipci_pcm { | 432 | struct cmipci_pcm { |
385 | struct snd_pcm_substream *substream; | 433 | struct snd_pcm_substream *substream; |
386 | int running; /* dac/adc running? */ | 434 | u8 running; /* dac/adc running? */ |
435 | u8 fmt; /* format bits */ | ||
436 | u8 is_dac; | ||
437 | u8 needs_silencing; | ||
387 | unsigned int dma_size; /* in frames */ | 438 | unsigned int dma_size; /* in frames */ |
388 | unsigned int period_size; /* in frames */ | 439 | unsigned int shift; |
440 | unsigned int ch; /* channel (0/1) */ | ||
389 | unsigned int offset; /* physical address of the buffer */ | 441 | unsigned int offset; /* physical address of the buffer */ |
390 | unsigned int fmt; /* format bits */ | ||
391 | int ch; /* channel (0/1) */ | ||
392 | unsigned int is_dac; /* is dac? */ | ||
393 | int bytes_per_frame; | ||
394 | int shift; | ||
395 | }; | 442 | }; |
396 | 443 | ||
397 | /* mixer elements toggled/resumed during ac3 playback */ | 444 | /* mixer elements toggled/resumed during ac3 playback */ |
@@ -424,7 +471,6 @@ struct cmipci { | |||
424 | 471 | ||
425 | int chip_version; | 472 | int chip_version; |
426 | int max_channels; | 473 | int max_channels; |
427 | unsigned int has_dual_dac: 1; | ||
428 | unsigned int can_ac3_sw: 1; | 474 | unsigned int can_ac3_sw: 1; |
429 | unsigned int can_ac3_hw: 1; | 475 | unsigned int can_ac3_hw: 1; |
430 | unsigned int can_multi_ch: 1; | 476 | unsigned int can_multi_ch: 1; |
@@ -557,6 +603,9 @@ static unsigned int rates[] = { 5512, 11025, 22050, 44100, 8000, 16000, 32000, 4 | |||
557 | static unsigned int snd_cmipci_rate_freq(unsigned int rate) | 603 | static unsigned int snd_cmipci_rate_freq(unsigned int rate) |
558 | { | 604 | { |
559 | unsigned int i; | 605 | unsigned int i; |
606 | |||
607 | if (rate > 48000) | ||
608 | rate /= 2; | ||
560 | for (i = 0; i < ARRAY_SIZE(rates); i++) { | 609 | for (i = 0; i < ARRAY_SIZE(rates); i++) { |
561 | if (rates[i] == rate) | 610 | if (rates[i] == rate) |
562 | return i; | 611 | return i; |
@@ -671,19 +720,19 @@ static int snd_cmipci_hw_free(struct snd_pcm_substream *substream) | |||
671 | /* | 720 | /* |
672 | */ | 721 | */ |
673 | 722 | ||
674 | static unsigned int hw_channels[] = {1, 2, 4, 5, 6, 8}; | 723 | static unsigned int hw_channels[] = {1, 2, 4, 6, 8}; |
675 | static struct snd_pcm_hw_constraint_list hw_constraints_channels_4 = { | 724 | static struct snd_pcm_hw_constraint_list hw_constraints_channels_4 = { |
676 | .count = 3, | 725 | .count = 3, |
677 | .list = hw_channels, | 726 | .list = hw_channels, |
678 | .mask = 0, | 727 | .mask = 0, |
679 | }; | 728 | }; |
680 | static struct snd_pcm_hw_constraint_list hw_constraints_channels_6 = { | 729 | static struct snd_pcm_hw_constraint_list hw_constraints_channels_6 = { |
681 | .count = 5, | 730 | .count = 4, |
682 | .list = hw_channels, | 731 | .list = hw_channels, |
683 | .mask = 0, | 732 | .mask = 0, |
684 | }; | 733 | }; |
685 | static struct snd_pcm_hw_constraint_list hw_constraints_channels_8 = { | 734 | static struct snd_pcm_hw_constraint_list hw_constraints_channels_8 = { |
686 | .count = 6, | 735 | .count = 5, |
687 | .list = hw_channels, | 736 | .list = hw_channels, |
688 | .mask = 0, | 737 | .mask = 0, |
689 | }; | 738 | }; |
@@ -691,48 +740,37 @@ static struct snd_pcm_hw_constraint_list hw_constraints_channels_8 = { | |||
691 | static int set_dac_channels(struct cmipci *cm, struct cmipci_pcm *rec, int channels) | 740 | static int set_dac_channels(struct cmipci *cm, struct cmipci_pcm *rec, int channels) |
692 | { | 741 | { |
693 | if (channels > 2) { | 742 | if (channels > 2) { |
694 | if (! cm->can_multi_ch) | 743 | if (!cm->can_multi_ch || !rec->ch) |
695 | return -EINVAL; | 744 | return -EINVAL; |
696 | if (rec->fmt != 0x03) /* stereo 16bit only */ | 745 | if (rec->fmt != 0x03) /* stereo 16bit only */ |
697 | return -EINVAL; | 746 | return -EINVAL; |
747 | } | ||
698 | 748 | ||
749 | if (cm->can_multi_ch) { | ||
699 | spin_lock_irq(&cm->reg_lock); | 750 | spin_lock_irq(&cm->reg_lock); |
700 | snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_NXCHG); | 751 | if (channels > 2) { |
701 | snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_XCHGDAC); | 752 | snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_NXCHG); |
702 | if (channels > 4) { | 753 | snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_XCHGDAC); |
703 | snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_CHB3D); | ||
704 | snd_cmipci_set_bit(cm, CM_REG_CHFORMAT, CM_CHB3D5C); | ||
705 | } else { | 754 | } else { |
706 | snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_CHB3D5C); | 755 | snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_NXCHG); |
707 | snd_cmipci_set_bit(cm, CM_REG_CHFORMAT, CM_CHB3D); | 756 | snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_XCHGDAC); |
708 | } | 757 | } |
709 | if (channels >= 6) { | 758 | if (channels == 8) |
759 | snd_cmipci_set_bit(cm, CM_REG_EXT_MISC, CM_CHB3D8C); | ||
760 | else | ||
761 | snd_cmipci_clear_bit(cm, CM_REG_EXT_MISC, CM_CHB3D8C); | ||
762 | if (channels == 6) { | ||
763 | snd_cmipci_set_bit(cm, CM_REG_CHFORMAT, CM_CHB3D5C); | ||
710 | snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_CHB3D6C); | 764 | snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_CHB3D6C); |
711 | snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_ENCENTER); | ||
712 | } else { | 765 | } else { |
713 | snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_CHB3D6C); | ||
714 | snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_ENCENTER); | ||
715 | } | ||
716 | if (cm->chip_version == 68) { | ||
717 | if (channels == 8) { | ||
718 | snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL_8768, CM_CHB3D8C); | ||
719 | } else { | ||
720 | snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL_8768, CM_CHB3D8C); | ||
721 | } | ||
722 | } | ||
723 | spin_unlock_irq(&cm->reg_lock); | ||
724 | |||
725 | } else { | ||
726 | if (cm->can_multi_ch) { | ||
727 | spin_lock_irq(&cm->reg_lock); | ||
728 | snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_NXCHG); | ||
729 | snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_CHB3D); | ||
730 | snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_CHB3D5C); | 766 | snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_CHB3D5C); |
731 | snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_CHB3D6C); | 767 | snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_CHB3D6C); |
732 | snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_ENCENTER); | ||
733 | snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_XCHGDAC); | ||
734 | spin_unlock_irq(&cm->reg_lock); | ||
735 | } | 768 | } |
769 | if (channels == 4) | ||
770 | snd_cmipci_set_bit(cm, CM_REG_CHFORMAT, CM_CHB3D); | ||
771 | else | ||
772 | snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_CHB3D); | ||
773 | spin_unlock_irq(&cm->reg_lock); | ||
736 | } | 774 | } |
737 | return 0; | 775 | return 0; |
738 | } | 776 | } |
@@ -746,6 +784,7 @@ static int snd_cmipci_pcm_prepare(struct cmipci *cm, struct cmipci_pcm *rec, | |||
746 | struct snd_pcm_substream *substream) | 784 | struct snd_pcm_substream *substream) |
747 | { | 785 | { |
748 | unsigned int reg, freq, val; | 786 | unsigned int reg, freq, val; |
787 | unsigned int period_size; | ||
749 | struct snd_pcm_runtime *runtime = substream->runtime; | 788 | struct snd_pcm_runtime *runtime = substream->runtime; |
750 | 789 | ||
751 | rec->fmt = 0; | 790 | rec->fmt = 0; |
@@ -765,11 +804,11 @@ static int snd_cmipci_pcm_prepare(struct cmipci *cm, struct cmipci_pcm *rec, | |||
765 | rec->offset = runtime->dma_addr; | 804 | rec->offset = runtime->dma_addr; |
766 | /* buffer and period sizes in frame */ | 805 | /* buffer and period sizes in frame */ |
767 | rec->dma_size = runtime->buffer_size << rec->shift; | 806 | rec->dma_size = runtime->buffer_size << rec->shift; |
768 | rec->period_size = runtime->period_size << rec->shift; | 807 | period_size = runtime->period_size << rec->shift; |
769 | if (runtime->channels > 2) { | 808 | if (runtime->channels > 2) { |
770 | /* multi-channels */ | 809 | /* multi-channels */ |
771 | rec->dma_size = (rec->dma_size * runtime->channels) / 2; | 810 | rec->dma_size = (rec->dma_size * runtime->channels) / 2; |
772 | rec->period_size = (rec->period_size * runtime->channels) / 2; | 811 | period_size = (period_size * runtime->channels) / 2; |
773 | } | 812 | } |
774 | 813 | ||
775 | spin_lock_irq(&cm->reg_lock); | 814 | spin_lock_irq(&cm->reg_lock); |
@@ -780,7 +819,7 @@ static int snd_cmipci_pcm_prepare(struct cmipci *cm, struct cmipci_pcm *rec, | |||
780 | /* program sample counts */ | 819 | /* program sample counts */ |
781 | reg = rec->ch ? CM_REG_CH1_FRAME2 : CM_REG_CH0_FRAME2; | 820 | reg = rec->ch ? CM_REG_CH1_FRAME2 : CM_REG_CH0_FRAME2; |
782 | snd_cmipci_write_w(cm, reg, rec->dma_size - 1); | 821 | snd_cmipci_write_w(cm, reg, rec->dma_size - 1); |
783 | snd_cmipci_write_w(cm, reg + 2, rec->period_size - 1); | 822 | snd_cmipci_write_w(cm, reg + 2, period_size - 1); |
784 | 823 | ||
785 | /* set adc/dac flag */ | 824 | /* set adc/dac flag */ |
786 | val = rec->ch ? CM_CHADC1 : CM_CHADC0; | 825 | val = rec->ch ? CM_CHADC1 : CM_CHADC0; |
@@ -795,11 +834,11 @@ static int snd_cmipci_pcm_prepare(struct cmipci *cm, struct cmipci_pcm *rec, | |||
795 | freq = snd_cmipci_rate_freq(runtime->rate); | 834 | freq = snd_cmipci_rate_freq(runtime->rate); |
796 | val = snd_cmipci_read(cm, CM_REG_FUNCTRL1); | 835 | val = snd_cmipci_read(cm, CM_REG_FUNCTRL1); |
797 | if (rec->ch) { | 836 | if (rec->ch) { |
798 | val &= ~CM_ASFC_MASK; | ||
799 | val |= (freq << CM_ASFC_SHIFT) & CM_ASFC_MASK; | ||
800 | } else { | ||
801 | val &= ~CM_DSFC_MASK; | 837 | val &= ~CM_DSFC_MASK; |
802 | val |= (freq << CM_DSFC_SHIFT) & CM_DSFC_MASK; | 838 | val |= (freq << CM_DSFC_SHIFT) & CM_DSFC_MASK; |
839 | } else { | ||
840 | val &= ~CM_ASFC_MASK; | ||
841 | val |= (freq << CM_ASFC_SHIFT) & CM_ASFC_MASK; | ||
803 | } | 842 | } |
804 | snd_cmipci_write(cm, CM_REG_FUNCTRL1, val); | 843 | snd_cmipci_write(cm, CM_REG_FUNCTRL1, val); |
805 | //snd_printd("cmipci: functrl1 = %08x\n", val); | 844 | //snd_printd("cmipci: functrl1 = %08x\n", val); |
@@ -813,6 +852,16 @@ static int snd_cmipci_pcm_prepare(struct cmipci *cm, struct cmipci_pcm *rec, | |||
813 | val &= ~CM_CH0FMT_MASK; | 852 | val &= ~CM_CH0FMT_MASK; |
814 | val |= rec->fmt << CM_CH0FMT_SHIFT; | 853 | val |= rec->fmt << CM_CH0FMT_SHIFT; |
815 | } | 854 | } |
855 | if (cm->chip_version == 68) { | ||
856 | if (runtime->rate == 88200) | ||
857 | val |= CM_CH0_SRATE_88K << (rec->ch * 2); | ||
858 | else | ||
859 | val &= ~(CM_CH0_SRATE_88K << (rec->ch * 2)); | ||
860 | if (runtime->rate == 96000) | ||
861 | val |= CM_CH0_SRATE_96K << (rec->ch * 2); | ||
862 | else | ||
863 | val &= ~(CM_CH0_SRATE_96K << (rec->ch * 2)); | ||
864 | } | ||
816 | snd_cmipci_write(cm, CM_REG_CHFORMAT, val); | 865 | snd_cmipci_write(cm, CM_REG_CHFORMAT, val); |
817 | //snd_printd("cmipci: chformat = %08x\n", val); | 866 | //snd_printd("cmipci: chformat = %08x\n", val); |
818 | 867 | ||
@@ -826,7 +875,7 @@ static int snd_cmipci_pcm_prepare(struct cmipci *cm, struct cmipci_pcm *rec, | |||
826 | * PCM trigger/stop | 875 | * PCM trigger/stop |
827 | */ | 876 | */ |
828 | static int snd_cmipci_pcm_trigger(struct cmipci *cm, struct cmipci_pcm *rec, | 877 | static int snd_cmipci_pcm_trigger(struct cmipci *cm, struct cmipci_pcm *rec, |
829 | struct snd_pcm_substream *substream, int cmd) | 878 | int cmd) |
830 | { | 879 | { |
831 | unsigned int inthld, chen, reset, pause; | 880 | unsigned int inthld, chen, reset, pause; |
832 | int result = 0; | 881 | int result = 0; |
@@ -855,6 +904,7 @@ static int snd_cmipci_pcm_trigger(struct cmipci *cm, struct cmipci_pcm *rec, | |||
855 | cm->ctrl &= ~chen; | 904 | cm->ctrl &= ~chen; |
856 | snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl | reset); | 905 | snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl | reset); |
857 | snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl & ~reset); | 906 | snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl & ~reset); |
907 | rec->needs_silencing = rec->is_dac; | ||
858 | break; | 908 | break; |
859 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 909 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
860 | case SNDRV_PCM_TRIGGER_SUSPEND: | 910 | case SNDRV_PCM_TRIGGER_SUSPEND: |
@@ -906,7 +956,7 @@ static int snd_cmipci_playback_trigger(struct snd_pcm_substream *substream, | |||
906 | int cmd) | 956 | int cmd) |
907 | { | 957 | { |
908 | struct cmipci *cm = snd_pcm_substream_chip(substream); | 958 | struct cmipci *cm = snd_pcm_substream_chip(substream); |
909 | return snd_cmipci_pcm_trigger(cm, &cm->channel[CM_CH_PLAY], substream, cmd); | 959 | return snd_cmipci_pcm_trigger(cm, &cm->channel[CM_CH_PLAY], cmd); |
910 | } | 960 | } |
911 | 961 | ||
912 | static snd_pcm_uframes_t snd_cmipci_playback_pointer(struct snd_pcm_substream *substream) | 962 | static snd_pcm_uframes_t snd_cmipci_playback_pointer(struct snd_pcm_substream *substream) |
@@ -925,7 +975,7 @@ static int snd_cmipci_capture_trigger(struct snd_pcm_substream *substream, | |||
925 | int cmd) | 975 | int cmd) |
926 | { | 976 | { |
927 | struct cmipci *cm = snd_pcm_substream_chip(substream); | 977 | struct cmipci *cm = snd_pcm_substream_chip(substream); |
928 | return snd_cmipci_pcm_trigger(cm, &cm->channel[CM_CH_CAPT], substream, cmd); | 978 | return snd_cmipci_pcm_trigger(cm, &cm->channel[CM_CH_CAPT], cmd); |
929 | } | 979 | } |
930 | 980 | ||
931 | static snd_pcm_uframes_t snd_cmipci_capture_pointer(struct snd_pcm_substream *substream) | 981 | static snd_pcm_uframes_t snd_cmipci_capture_pointer(struct snd_pcm_substream *substream) |
@@ -1199,15 +1249,19 @@ static int setup_spdif_playback(struct cmipci *cm, struct snd_pcm_substream *sub | |||
1199 | snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_PLAYBACK_SPDF); | 1249 | snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_PLAYBACK_SPDF); |
1200 | setup_ac3(cm, subs, do_ac3, rate); | 1250 | setup_ac3(cm, subs, do_ac3, rate); |
1201 | 1251 | ||
1202 | if (rate == 48000) | 1252 | if (rate == 48000 || rate == 96000) |
1203 | snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_SPDIF48K | CM_SPDF_AC97); | 1253 | snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_SPDIF48K | CM_SPDF_AC97); |
1204 | else | 1254 | else |
1205 | snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_SPDIF48K | CM_SPDF_AC97); | 1255 | snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_SPDIF48K | CM_SPDF_AC97); |
1206 | 1256 | if (rate > 48000) | |
1257 | snd_cmipci_set_bit(cm, CM_REG_CHFORMAT, CM_DBLSPDS); | ||
1258 | else | ||
1259 | snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_DBLSPDS); | ||
1207 | } else { | 1260 | } else { |
1208 | /* they are controlled via "IEC958 Output Switch" */ | 1261 | /* they are controlled via "IEC958 Output Switch" */ |
1209 | /* snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_ENSPDOUT); */ | 1262 | /* snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_ENSPDOUT); */ |
1210 | /* snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_SPDO2DAC); */ | 1263 | /* snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_SPDO2DAC); */ |
1264 | snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_DBLSPDS); | ||
1211 | snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_PLAYBACK_SPDF); | 1265 | snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_PLAYBACK_SPDF); |
1212 | setup_ac3(cm, subs, 0, 0); | 1266 | setup_ac3(cm, subs, 0, 0); |
1213 | } | 1267 | } |
@@ -1227,7 +1281,7 @@ static int snd_cmipci_playback_prepare(struct snd_pcm_substream *substream) | |||
1227 | int rate = substream->runtime->rate; | 1281 | int rate = substream->runtime->rate; |
1228 | int err, do_spdif, do_ac3 = 0; | 1282 | int err, do_spdif, do_ac3 = 0; |
1229 | 1283 | ||
1230 | do_spdif = ((rate == 44100 || rate == 48000) && | 1284 | do_spdif = (rate >= 44100 && |
1231 | substream->runtime->format == SNDRV_PCM_FORMAT_S16_LE && | 1285 | substream->runtime->format == SNDRV_PCM_FORMAT_S16_LE && |
1232 | substream->runtime->channels == 2); | 1286 | substream->runtime->channels == 2); |
1233 | if (do_spdif && cm->can_ac3_hw) | 1287 | if (do_spdif && cm->can_ac3_hw) |
@@ -1252,11 +1306,75 @@ static int snd_cmipci_playback_spdif_prepare(struct snd_pcm_substream *substream | |||
1252 | return snd_cmipci_pcm_prepare(cm, &cm->channel[CM_CH_PLAY], substream); | 1306 | return snd_cmipci_pcm_prepare(cm, &cm->channel[CM_CH_PLAY], substream); |
1253 | } | 1307 | } |
1254 | 1308 | ||
1309 | /* | ||
1310 | * Apparently, the samples last played on channel A stay in some buffer, even | ||
1311 | * after the channel is reset, and get added to the data for the rear DACs when | ||
1312 | * playing a multichannel stream on channel B. This is likely to generate | ||
1313 | * wraparounds and thus distortions. | ||
1314 | * To avoid this, we play at least one zero sample after the actual stream has | ||
1315 | * stopped. | ||
1316 | */ | ||
1317 | static void snd_cmipci_silence_hack(struct cmipci *cm, struct cmipci_pcm *rec) | ||
1318 | { | ||
1319 | struct snd_pcm_runtime *runtime = rec->substream->runtime; | ||
1320 | unsigned int reg, val; | ||
1321 | |||
1322 | if (rec->needs_silencing && runtime && runtime->dma_area) { | ||
1323 | /* set up a small silence buffer */ | ||
1324 | memset(runtime->dma_area, 0, PAGE_SIZE); | ||
1325 | reg = rec->ch ? CM_REG_CH1_FRAME2 : CM_REG_CH0_FRAME2; | ||
1326 | val = ((PAGE_SIZE / 4) - 1) | (((PAGE_SIZE / 4) / 2 - 1) << 16); | ||
1327 | snd_cmipci_write(cm, reg, val); | ||
1328 | |||
1329 | /* configure for 16 bits, 2 channels, 8 kHz */ | ||
1330 | if (runtime->channels > 2) | ||
1331 | set_dac_channels(cm, rec, 2); | ||
1332 | spin_lock_irq(&cm->reg_lock); | ||
1333 | val = snd_cmipci_read(cm, CM_REG_FUNCTRL1); | ||
1334 | val &= ~(CM_ASFC_MASK << (rec->ch * 3)); | ||
1335 | val |= (4 << CM_ASFC_SHIFT) << (rec->ch * 3); | ||
1336 | snd_cmipci_write(cm, CM_REG_FUNCTRL1, val); | ||
1337 | val = snd_cmipci_read(cm, CM_REG_CHFORMAT); | ||
1338 | val &= ~(CM_CH0FMT_MASK << (rec->ch * 2)); | ||
1339 | val |= (3 << CM_CH0FMT_SHIFT) << (rec->ch * 2); | ||
1340 | if (cm->chip_version == 68) { | ||
1341 | val &= ~(CM_CH0_SRATE_88K << (rec->ch * 2)); | ||
1342 | val &= ~(CM_CH0_SRATE_96K << (rec->ch * 2)); | ||
1343 | } | ||
1344 | snd_cmipci_write(cm, CM_REG_CHFORMAT, val); | ||
1345 | |||
1346 | /* start stream (we don't need interrupts) */ | ||
1347 | cm->ctrl |= CM_CHEN0 << rec->ch; | ||
1348 | snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl); | ||
1349 | spin_unlock_irq(&cm->reg_lock); | ||
1350 | |||
1351 | msleep(1); | ||
1352 | |||
1353 | /* stop and reset stream */ | ||
1354 | spin_lock_irq(&cm->reg_lock); | ||
1355 | cm->ctrl &= ~(CM_CHEN0 << rec->ch); | ||
1356 | val = CM_RST_CH0 << rec->ch; | ||
1357 | snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl | val); | ||
1358 | snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl & ~val); | ||
1359 | spin_unlock_irq(&cm->reg_lock); | ||
1360 | |||
1361 | rec->needs_silencing = 0; | ||
1362 | } | ||
1363 | } | ||
1364 | |||
1255 | static int snd_cmipci_playback_hw_free(struct snd_pcm_substream *substream) | 1365 | static int snd_cmipci_playback_hw_free(struct snd_pcm_substream *substream) |
1256 | { | 1366 | { |
1257 | struct cmipci *cm = snd_pcm_substream_chip(substream); | 1367 | struct cmipci *cm = snd_pcm_substream_chip(substream); |
1258 | setup_spdif_playback(cm, substream, 0, 0); | 1368 | setup_spdif_playback(cm, substream, 0, 0); |
1259 | restore_mixer_state(cm); | 1369 | restore_mixer_state(cm); |
1370 | snd_cmipci_silence_hack(cm, &cm->channel[0]); | ||
1371 | return snd_cmipci_hw_free(substream); | ||
1372 | } | ||
1373 | |||
1374 | static int snd_cmipci_playback2_hw_free(struct snd_pcm_substream *substream) | ||
1375 | { | ||
1376 | struct cmipci *cm = snd_pcm_substream_chip(substream); | ||
1377 | snd_cmipci_silence_hack(cm, &cm->channel[1]); | ||
1260 | return snd_cmipci_hw_free(substream); | 1378 | return snd_cmipci_hw_free(substream); |
1261 | } | 1379 | } |
1262 | 1380 | ||
@@ -1515,7 +1633,11 @@ static int snd_cmipci_playback_open(struct snd_pcm_substream *substream) | |||
1515 | if ((err = open_device_check(cm, CM_OPEN_PLAYBACK, substream)) < 0) | 1633 | if ((err = open_device_check(cm, CM_OPEN_PLAYBACK, substream)) < 0) |
1516 | return err; | 1634 | return err; |
1517 | runtime->hw = snd_cmipci_playback; | 1635 | runtime->hw = snd_cmipci_playback; |
1518 | runtime->hw.channels_max = cm->max_channels; | 1636 | if (cm->chip_version == 68) { |
1637 | runtime->hw.rates |= SNDRV_PCM_RATE_88200 | | ||
1638 | SNDRV_PCM_RATE_96000; | ||
1639 | runtime->hw.rate_max = 96000; | ||
1640 | } | ||
1519 | snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x10000); | 1641 | snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x10000); |
1520 | cm->dig_pcm_status = cm->dig_status; | 1642 | cm->dig_pcm_status = cm->dig_status; |
1521 | return 0; | 1643 | return 0; |
@@ -1558,9 +1680,14 @@ static int snd_cmipci_playback2_open(struct snd_pcm_substream *substream) | |||
1558 | else if (cm->max_channels == 8) | 1680 | else if (cm->max_channels == 8) |
1559 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_channels_8); | 1681 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_channels_8); |
1560 | } | 1682 | } |
1561 | snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x10000); | ||
1562 | } | 1683 | } |
1563 | mutex_unlock(&cm->open_mutex); | 1684 | mutex_unlock(&cm->open_mutex); |
1685 | if (cm->chip_version == 68) { | ||
1686 | runtime->hw.rates |= SNDRV_PCM_RATE_88200 | | ||
1687 | SNDRV_PCM_RATE_96000; | ||
1688 | runtime->hw.rate_max = 96000; | ||
1689 | } | ||
1690 | snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x10000); | ||
1564 | return 0; | 1691 | return 0; |
1565 | } | 1692 | } |
1566 | 1693 | ||
@@ -1574,8 +1701,15 @@ static int snd_cmipci_playback_spdif_open(struct snd_pcm_substream *substream) | |||
1574 | return err; | 1701 | return err; |
1575 | if (cm->can_ac3_hw) { | 1702 | if (cm->can_ac3_hw) { |
1576 | runtime->hw = snd_cmipci_playback_spdif; | 1703 | runtime->hw = snd_cmipci_playback_spdif; |
1577 | if (cm->chip_version >= 37) | 1704 | if (cm->chip_version >= 37) { |
1578 | runtime->hw.formats |= SNDRV_PCM_FMTBIT_S32_LE; | 1705 | runtime->hw.formats |= SNDRV_PCM_FMTBIT_S32_LE; |
1706 | snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); | ||
1707 | } | ||
1708 | if (cm->chip_version == 68) { | ||
1709 | runtime->hw.rates |= SNDRV_PCM_RATE_88200 | | ||
1710 | SNDRV_PCM_RATE_96000; | ||
1711 | runtime->hw.rate_max = 96000; | ||
1712 | } | ||
1579 | } else { | 1713 | } else { |
1580 | runtime->hw = snd_cmipci_playback_iec958_subframe; | 1714 | runtime->hw = snd_cmipci_playback_iec958_subframe; |
1581 | } | 1715 | } |
@@ -1668,7 +1802,7 @@ static struct snd_pcm_ops snd_cmipci_playback2_ops = { | |||
1668 | .close = snd_cmipci_playback2_close, | 1802 | .close = snd_cmipci_playback2_close, |
1669 | .ioctl = snd_pcm_lib_ioctl, | 1803 | .ioctl = snd_pcm_lib_ioctl, |
1670 | .hw_params = snd_cmipci_playback2_hw_params, | 1804 | .hw_params = snd_cmipci_playback2_hw_params, |
1671 | .hw_free = snd_cmipci_hw_free, | 1805 | .hw_free = snd_cmipci_playback2_hw_free, |
1672 | .prepare = snd_cmipci_capture_prepare, /* channel B */ | 1806 | .prepare = snd_cmipci_capture_prepare, /* channel B */ |
1673 | .trigger = snd_cmipci_capture_trigger, /* channel B */ | 1807 | .trigger = snd_cmipci_capture_trigger, /* channel B */ |
1674 | .pointer = snd_cmipci_capture_pointer, /* channel B */ | 1808 | .pointer = snd_cmipci_capture_pointer, /* channel B */ |
@@ -2139,15 +2273,7 @@ struct cmipci_switch_args { | |||
2139 | */ | 2273 | */ |
2140 | }; | 2274 | }; |
2141 | 2275 | ||
2142 | static int snd_cmipci_uswitch_info(struct snd_kcontrol *kcontrol, | 2276 | #define snd_cmipci_uswitch_info snd_ctl_boolean_mono_info |
2143 | struct snd_ctl_elem_info *uinfo) | ||
2144 | { | ||
2145 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
2146 | uinfo->count = 1; | ||
2147 | uinfo->value.integer.min = 0; | ||
2148 | uinfo->value.integer.max = 1; | ||
2149 | return 0; | ||
2150 | } | ||
2151 | 2277 | ||
2152 | static int _snd_cmipci_uswitch_get(struct snd_kcontrol *kcontrol, | 2278 | static int _snd_cmipci_uswitch_get(struct snd_kcontrol *kcontrol, |
2153 | struct snd_ctl_elem_value *ucontrol, | 2279 | struct snd_ctl_elem_value *ucontrol, |
@@ -2260,8 +2386,8 @@ DEFINE_SWITCH_ARG(exchange_dac, CM_REG_MISC_CTRL, CM_XCHGDAC, 0, 0, 0); /* rever | |||
2260 | DEFINE_SWITCH_ARG(exchange_dac, CM_REG_MISC_CTRL, CM_XCHGDAC, CM_XCHGDAC, 0, 0); | 2386 | DEFINE_SWITCH_ARG(exchange_dac, CM_REG_MISC_CTRL, CM_XCHGDAC, CM_XCHGDAC, 0, 0); |
2261 | #endif | 2387 | #endif |
2262 | DEFINE_BIT_SWITCH_ARG(fourch, CM_REG_MISC_CTRL, CM_N4SPK3D, 0, 0); | 2388 | DEFINE_BIT_SWITCH_ARG(fourch, CM_REG_MISC_CTRL, CM_N4SPK3D, 0, 0); |
2263 | // DEFINE_BIT_SWITCH_ARG(line_rear, CM_REG_MIXER1, CM_SPK4, 1, 0); | 2389 | // DEFINE_BIT_SWITCH_ARG(line_rear, CM_REG_MIXER1, CM_REAR2LIN, 1, 0); |
2264 | // DEFINE_BIT_SWITCH_ARG(line_bass, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS, 0, 0); | 2390 | // DEFINE_BIT_SWITCH_ARG(line_bass, CM_REG_LEGACY_CTRL, CM_CENTR2LIN|CM_BASE2LIN, 0, 0); |
2265 | // DEFINE_BIT_SWITCH_ARG(joystick, CM_REG_FUNCTRL1, CM_JYSTK_EN, 0, 0); /* now module option */ | 2391 | // DEFINE_BIT_SWITCH_ARG(joystick, CM_REG_FUNCTRL1, CM_JYSTK_EN, 0, 0); /* now module option */ |
2266 | DEFINE_SWITCH_ARG(modem, CM_REG_MISC_CTRL, CM_FLINKON|CM_FLINKOFF, CM_FLINKON, 0, 0); | 2392 | DEFINE_SWITCH_ARG(modem, CM_REG_MISC_CTRL, CM_FLINKON|CM_FLINKOFF, CM_FLINKON, 0, 0); |
2267 | 2393 | ||
@@ -2331,11 +2457,11 @@ static inline unsigned int get_line_in_mode(struct cmipci *cm) | |||
2331 | unsigned int val; | 2457 | unsigned int val; |
2332 | if (cm->chip_version >= 39) { | 2458 | if (cm->chip_version >= 39) { |
2333 | val = snd_cmipci_read(cm, CM_REG_LEGACY_CTRL); | 2459 | val = snd_cmipci_read(cm, CM_REG_LEGACY_CTRL); |
2334 | if (val & CM_LINE_AS_BASS) | 2460 | if (val & (CM_CENTR2LIN | CM_BASE2LIN)) |
2335 | return 2; | 2461 | return 2; |
2336 | } | 2462 | } |
2337 | val = snd_cmipci_read_b(cm, CM_REG_MIXER1); | 2463 | val = snd_cmipci_read_b(cm, CM_REG_MIXER1); |
2338 | if (val & CM_SPK4) | 2464 | if (val & CM_REAR2LIN) |
2339 | return 1; | 2465 | return 1; |
2340 | return 0; | 2466 | return 0; |
2341 | } | 2467 | } |
@@ -2359,13 +2485,13 @@ static int snd_cmipci_line_in_mode_put(struct snd_kcontrol *kcontrol, | |||
2359 | 2485 | ||
2360 | spin_lock_irq(&cm->reg_lock); | 2486 | spin_lock_irq(&cm->reg_lock); |
2361 | if (ucontrol->value.enumerated.item[0] == 2) | 2487 | if (ucontrol->value.enumerated.item[0] == 2) |
2362 | change = snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS); | 2488 | change = snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_CENTR2LIN | CM_BASE2LIN); |
2363 | else | 2489 | else |
2364 | change = snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS); | 2490 | change = snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_CENTR2LIN | CM_BASE2LIN); |
2365 | if (ucontrol->value.enumerated.item[0] == 1) | 2491 | if (ucontrol->value.enumerated.item[0] == 1) |
2366 | change |= snd_cmipci_set_bit_b(cm, CM_REG_MIXER1, CM_SPK4); | 2492 | change |= snd_cmipci_set_bit_b(cm, CM_REG_MIXER1, CM_REAR2LIN); |
2367 | else | 2493 | else |
2368 | change |= snd_cmipci_clear_bit_b(cm, CM_REG_MIXER1, CM_SPK4); | 2494 | change |= snd_cmipci_clear_bit_b(cm, CM_REG_MIXER1, CM_REAR2LIN); |
2369 | spin_unlock_irq(&cm->reg_lock); | 2495 | spin_unlock_irq(&cm->reg_lock); |
2370 | return change; | 2496 | return change; |
2371 | } | 2497 | } |
@@ -2583,19 +2709,18 @@ static void snd_cmipci_proc_read(struct snd_info_entry *entry, | |||
2583 | struct snd_info_buffer *buffer) | 2709 | struct snd_info_buffer *buffer) |
2584 | { | 2710 | { |
2585 | struct cmipci *cm = entry->private_data; | 2711 | struct cmipci *cm = entry->private_data; |
2586 | int i; | 2712 | int i, v; |
2587 | 2713 | ||
2588 | snd_iprintf(buffer, "%s\n\n", cm->card->longname); | 2714 | snd_iprintf(buffer, "%s\n", cm->card->longname); |
2589 | for (i = 0; i < 0x40; i++) { | 2715 | for (i = 0; i < 0x94; i++) { |
2590 | int v = inb(cm->iobase + i); | 2716 | if (i == 0x28) |
2717 | i = 0x90; | ||
2718 | v = inb(cm->iobase + i); | ||
2591 | if (i % 4 == 0) | 2719 | if (i % 4 == 0) |
2592 | snd_iprintf(buffer, "%02x: ", i); | 2720 | snd_iprintf(buffer, "\n%02x:", i); |
2593 | snd_iprintf(buffer, "%02x", v); | 2721 | snd_iprintf(buffer, " %02x", v); |
2594 | if (i % 4 == 3) | ||
2595 | snd_iprintf(buffer, "\n"); | ||
2596 | else | ||
2597 | snd_iprintf(buffer, " "); | ||
2598 | } | 2722 | } |
2723 | snd_iprintf(buffer, "\n"); | ||
2599 | } | 2724 | } |
2600 | 2725 | ||
2601 | static void __devinit snd_cmipci_proc_init(struct cmipci *cm) | 2726 | static void __devinit snd_cmipci_proc_init(struct cmipci *cm) |
@@ -2633,46 +2758,40 @@ static void __devinit query_chip(struct cmipci *cm) | |||
2633 | if (! detect) { | 2758 | if (! detect) { |
2634 | /* check reg 08h, bit 24-28 */ | 2759 | /* check reg 08h, bit 24-28 */ |
2635 | detect = snd_cmipci_read(cm, CM_REG_CHFORMAT) & CM_CHIP_MASK1; | 2760 | detect = snd_cmipci_read(cm, CM_REG_CHFORMAT) & CM_CHIP_MASK1; |
2636 | if (! detect) { | 2761 | switch (detect) { |
2762 | case 0: | ||
2637 | cm->chip_version = 33; | 2763 | cm->chip_version = 33; |
2638 | cm->max_channels = 2; | ||
2639 | if (cm->do_soft_ac3) | 2764 | if (cm->do_soft_ac3) |
2640 | cm->can_ac3_sw = 1; | 2765 | cm->can_ac3_sw = 1; |
2641 | else | 2766 | else |
2642 | cm->can_ac3_hw = 1; | 2767 | cm->can_ac3_hw = 1; |
2643 | cm->has_dual_dac = 1; | 2768 | break; |
2644 | } else { | 2769 | case CM_CHIP_037: |
2645 | cm->chip_version = 37; | 2770 | cm->chip_version = 37; |
2646 | cm->max_channels = 2; | ||
2647 | cm->can_ac3_hw = 1; | 2771 | cm->can_ac3_hw = 1; |
2648 | cm->has_dual_dac = 1; | 2772 | break; |
2773 | default: | ||
2774 | cm->chip_version = 39; | ||
2775 | cm->can_ac3_hw = 1; | ||
2776 | break; | ||
2649 | } | 2777 | } |
2778 | cm->max_channels = 2; | ||
2650 | } else { | 2779 | } else { |
2651 | /* check reg 0Ch, bit 26 */ | 2780 | if (detect & CM_CHIP_039) { |
2652 | if (detect & CM_CHIP_8768) { | ||
2653 | cm->chip_version = 68; | ||
2654 | cm->max_channels = 8; | ||
2655 | cm->can_ac3_hw = 1; | ||
2656 | cm->has_dual_dac = 1; | ||
2657 | cm->can_multi_ch = 1; | ||
2658 | } else if (detect & CM_CHIP_055) { | ||
2659 | cm->chip_version = 55; | ||
2660 | cm->max_channels = 6; | ||
2661 | cm->can_ac3_hw = 1; | ||
2662 | cm->has_dual_dac = 1; | ||
2663 | cm->can_multi_ch = 1; | ||
2664 | } else if (detect & CM_CHIP_039) { | ||
2665 | cm->chip_version = 39; | 2781 | cm->chip_version = 39; |
2666 | if (detect & CM_CHIP_039_6CH) /* 4 or 6 channels */ | 2782 | if (detect & CM_CHIP_039_6CH) /* 4 or 6 channels */ |
2667 | cm->max_channels = 6; | 2783 | cm->max_channels = 6; |
2668 | else | 2784 | else |
2669 | cm->max_channels = 4; | 2785 | cm->max_channels = 4; |
2670 | cm->can_ac3_hw = 1; | 2786 | } else if (detect & CM_CHIP_8768) { |
2671 | cm->has_dual_dac = 1; | 2787 | cm->chip_version = 68; |
2672 | cm->can_multi_ch = 1; | 2788 | cm->max_channels = 8; |
2673 | } else { | 2789 | } else { |
2674 | printk(KERN_ERR "chip %x version not supported\n", detect); | 2790 | cm->chip_version = 55; |
2791 | cm->max_channels = 6; | ||
2675 | } | 2792 | } |
2793 | cm->can_ac3_hw = 1; | ||
2794 | cm->can_multi_ch = 1; | ||
2676 | } | 2795 | } |
2677 | } | 2796 | } |
2678 | 2797 | ||
@@ -2782,10 +2901,14 @@ static int __devinit snd_cmipci_create_fm(struct cmipci *cm, long fm_port) | |||
2782 | if (!fm_port) | 2901 | if (!fm_port) |
2783 | goto disable_fm; | 2902 | goto disable_fm; |
2784 | 2903 | ||
2785 | /* first try FM regs in PCI port range */ | 2904 | if (cm->chip_version >= 39) { |
2786 | iosynth = cm->iobase + CM_REG_FM_PCI; | 2905 | /* first try FM regs in PCI port range */ |
2787 | err = snd_opl3_create(cm->card, iosynth, iosynth + 2, | 2906 | iosynth = cm->iobase + CM_REG_FM_PCI; |
2788 | OPL3_HW_OPL3, 1, &opl3); | 2907 | err = snd_opl3_create(cm->card, iosynth, iosynth + 2, |
2908 | OPL3_HW_OPL3, 1, &opl3); | ||
2909 | } else { | ||
2910 | err = -EIO; | ||
2911 | } | ||
2789 | if (err < 0) { | 2912 | if (err < 0) { |
2790 | /* then try legacy ports */ | 2913 | /* then try legacy ports */ |
2791 | val = snd_cmipci_read(cm, CM_REG_LEGACY_CTRL) & ~CM_FMSEL_MASK; | 2914 | val = snd_cmipci_read(cm, CM_REG_LEGACY_CTRL) & ~CM_FMSEL_MASK; |
@@ -2829,9 +2952,10 @@ static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pc | |||
2829 | static struct snd_device_ops ops = { | 2952 | static struct snd_device_ops ops = { |
2830 | .dev_free = snd_cmipci_dev_free, | 2953 | .dev_free = snd_cmipci_dev_free, |
2831 | }; | 2954 | }; |
2832 | unsigned int val = 0; | 2955 | unsigned int val; |
2833 | long iomidi; | 2956 | long iomidi; |
2834 | int integrated_midi; | 2957 | int integrated_midi = 0; |
2958 | char modelstr[16]; | ||
2835 | int pcm_index, pcm_spdif_index; | 2959 | int pcm_index, pcm_spdif_index; |
2836 | static struct pci_device_id intel_82437vx[] = { | 2960 | static struct pci_device_id intel_82437vx[] = { |
2837 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437VX) }, | 2961 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437VX) }, |
@@ -2904,6 +3028,8 @@ static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pc | |||
2904 | #endif | 3028 | #endif |
2905 | 3029 | ||
2906 | /* initialize codec registers */ | 3030 | /* initialize codec registers */ |
3031 | snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_RESET); | ||
3032 | snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_RESET); | ||
2907 | snd_cmipci_write(cm, CM_REG_INT_HLDCLR, 0); /* disable ints */ | 3033 | snd_cmipci_write(cm, CM_REG_INT_HLDCLR, 0); /* disable ints */ |
2908 | snd_cmipci_ch_reset(cm, CM_CH_PLAY); | 3034 | snd_cmipci_ch_reset(cm, CM_CH_PLAY); |
2909 | snd_cmipci_ch_reset(cm, CM_CH_CAPT); | 3035 | snd_cmipci_ch_reset(cm, CM_CH_CAPT); |
@@ -2917,6 +3043,10 @@ static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pc | |||
2917 | #else | 3043 | #else |
2918 | snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_XCHGDAC); | 3044 | snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_XCHGDAC); |
2919 | #endif | 3045 | #endif |
3046 | if (cm->chip_version) { | ||
3047 | snd_cmipci_write_b(cm, CM_REG_EXT_MISC, 0x20); /* magic */ | ||
3048 | snd_cmipci_write_b(cm, CM_REG_EXT_MISC + 1, 0x09); /* more magic */ | ||
3049 | } | ||
2920 | /* Set Bus Master Request */ | 3050 | /* Set Bus Master Request */ |
2921 | snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_BREQ); | 3051 | snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_BREQ); |
2922 | 3052 | ||
@@ -2931,15 +3061,55 @@ static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pc | |||
2931 | break; | 3061 | break; |
2932 | } | 3062 | } |
2933 | 3063 | ||
3064 | if (cm->chip_version < 68) { | ||
3065 | val = pci->device < 0x110 ? 8338 : 8738; | ||
3066 | } else { | ||
3067 | switch (snd_cmipci_read_b(cm, CM_REG_INT_HLDCLR + 3) & 0x03) { | ||
3068 | case 0: | ||
3069 | val = 8769; | ||
3070 | break; | ||
3071 | case 2: | ||
3072 | val = 8762; | ||
3073 | break; | ||
3074 | default: | ||
3075 | switch ((pci->subsystem_vendor << 16) | | ||
3076 | pci->subsystem_device) { | ||
3077 | case 0x13f69761: | ||
3078 | case 0x584d3741: | ||
3079 | case 0x584d3751: | ||
3080 | case 0x584d3761: | ||
3081 | case 0x584d3771: | ||
3082 | case 0x72848384: | ||
3083 | val = 8770; | ||
3084 | break; | ||
3085 | default: | ||
3086 | val = 8768; | ||
3087 | break; | ||
3088 | } | ||
3089 | } | ||
3090 | } | ||
3091 | sprintf(card->shortname, "C-Media CMI%d", val); | ||
3092 | if (cm->chip_version < 68) | ||
3093 | sprintf(modelstr, " (model %d)", cm->chip_version); | ||
3094 | else | ||
3095 | modelstr[0] = '\0'; | ||
3096 | sprintf(card->longname, "%s%s at %#lx, irq %i", | ||
3097 | card->shortname, modelstr, cm->iobase, cm->irq); | ||
3098 | |||
2934 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, cm, &ops)) < 0) { | 3099 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, cm, &ops)) < 0) { |
2935 | snd_cmipci_free(cm); | 3100 | snd_cmipci_free(cm); |
2936 | return err; | 3101 | return err; |
2937 | } | 3102 | } |
2938 | 3103 | ||
2939 | integrated_midi = snd_cmipci_read_b(cm, CM_REG_MPU_PCI) != 0xff; | 3104 | if (cm->chip_version >= 39) { |
2940 | if (integrated_midi && mpu_port[dev] == 1) | 3105 | val = snd_cmipci_read_b(cm, CM_REG_MPU_PCI + 1); |
2941 | iomidi = cm->iobase + CM_REG_MPU_PCI; | 3106 | if (val != 0x00 && val != 0xff) { |
2942 | else { | 3107 | iomidi = cm->iobase + CM_REG_MPU_PCI; |
3108 | integrated_midi = 1; | ||
3109 | } | ||
3110 | } | ||
3111 | if (!integrated_midi) { | ||
3112 | val = 0; | ||
2943 | iomidi = mpu_port[dev]; | 3113 | iomidi = mpu_port[dev]; |
2944 | switch (iomidi) { | 3114 | switch (iomidi) { |
2945 | case 0x320: val = CM_VMPU_320; break; | 3115 | case 0x320: val = CM_VMPU_320; break; |
@@ -2953,11 +3123,21 @@ static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pc | |||
2953 | snd_cmipci_write(cm, CM_REG_LEGACY_CTRL, val); | 3123 | snd_cmipci_write(cm, CM_REG_LEGACY_CTRL, val); |
2954 | /* enable UART */ | 3124 | /* enable UART */ |
2955 | snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_UART_EN); | 3125 | snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_UART_EN); |
3126 | if (inb(iomidi + 1) == 0xff) { | ||
3127 | snd_printk(KERN_ERR "cannot enable MPU-401 port" | ||
3128 | " at %#lx\n", iomidi); | ||
3129 | snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, | ||
3130 | CM_UART_EN); | ||
3131 | iomidi = 0; | ||
3132 | } | ||
2956 | } | 3133 | } |
2957 | } | 3134 | } |
2958 | 3135 | ||
2959 | if ((err = snd_cmipci_create_fm(cm, fm_port[dev])) < 0) | 3136 | if (cm->chip_version < 68) { |
2960 | return err; | 3137 | err = snd_cmipci_create_fm(cm, fm_port[dev]); |
3138 | if (err < 0) | ||
3139 | return err; | ||
3140 | } | ||
2961 | 3141 | ||
2962 | /* reset mixer */ | 3142 | /* reset mixer */ |
2963 | snd_cmipci_mixer_write(cm, 0, 0); | 3143 | snd_cmipci_mixer_write(cm, 0, 0); |
@@ -2969,11 +3149,9 @@ static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pc | |||
2969 | if ((err = snd_cmipci_pcm_new(cm, pcm_index)) < 0) | 3149 | if ((err = snd_cmipci_pcm_new(cm, pcm_index)) < 0) |
2970 | return err; | 3150 | return err; |
2971 | pcm_index++; | 3151 | pcm_index++; |
2972 | if (cm->has_dual_dac) { | 3152 | if ((err = snd_cmipci_pcm2_new(cm, pcm_index)) < 0) |
2973 | if ((err = snd_cmipci_pcm2_new(cm, pcm_index)) < 0) | 3153 | return err; |
2974 | return err; | 3154 | pcm_index++; |
2975 | pcm_index++; | ||
2976 | } | ||
2977 | if (cm->can_ac3_hw || cm->can_ac3_sw) { | 3155 | if (cm->can_ac3_hw || cm->can_ac3_sw) { |
2978 | pcm_spdif_index = pcm_index; | 3156 | pcm_spdif_index = pcm_index; |
2979 | if ((err = snd_cmipci_pcm_spdif_new(cm, pcm_index)) < 0) | 3157 | if ((err = snd_cmipci_pcm_spdif_new(cm, pcm_index)) < 0) |
@@ -3057,15 +3235,6 @@ static int __devinit snd_cmipci_probe(struct pci_dev *pci, | |||
3057 | } | 3235 | } |
3058 | card->private_data = cm; | 3236 | card->private_data = cm; |
3059 | 3237 | ||
3060 | sprintf(card->shortname, "C-Media PCI %s", card->driver); | ||
3061 | sprintf(card->longname, "%s (model %d) at 0x%lx, irq %i", | ||
3062 | card->shortname, | ||
3063 | cm->chip_version, | ||
3064 | cm->iobase, | ||
3065 | cm->irq); | ||
3066 | |||
3067 | //snd_printd("%s is detected\n", card->longname); | ||
3068 | |||
3069 | if ((err = snd_card_register(card)) < 0) { | 3238 | if ((err = snd_card_register(card)) < 0) { |
3070 | snd_card_free(card); | 3239 | snd_card_free(card); |
3071 | return err; | 3240 | return err; |
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index 44cf54607647..9a55f4a9739b 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for Cirrus Logic CS4281 based PCI soundcard | 2 | * Driver for Cirrus Logic CS4281 based PCI soundcard |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz>, | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz>, |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -38,7 +38,7 @@ | |||
38 | #include <sound/initval.h> | 38 | #include <sound/initval.h> |
39 | 39 | ||
40 | 40 | ||
41 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 41 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
42 | MODULE_DESCRIPTION("Cirrus Logic CS4281"); | 42 | MODULE_DESCRIPTION("Cirrus Logic CS4281"); |
43 | MODULE_LICENSE("GPL"); | 43 | MODULE_LICENSE("GPL"); |
44 | MODULE_SUPPORTED_DEVICE("{{Cirrus Logic,CS4281}}"); | 44 | MODULE_SUPPORTED_DEVICE("{{Cirrus Logic,CS4281}}"); |
@@ -842,12 +842,11 @@ static snd_pcm_uframes_t snd_cs4281_pointer(struct snd_pcm_substream *substream) | |||
842 | 842 | ||
843 | static struct snd_pcm_hardware snd_cs4281_playback = | 843 | static struct snd_pcm_hardware snd_cs4281_playback = |
844 | { | 844 | { |
845 | .info = (SNDRV_PCM_INFO_MMAP | | 845 | .info = SNDRV_PCM_INFO_MMAP | |
846 | SNDRV_PCM_INFO_INTERLEAVED | | 846 | SNDRV_PCM_INFO_INTERLEAVED | |
847 | SNDRV_PCM_INFO_MMAP_VALID | | 847 | SNDRV_PCM_INFO_MMAP_VALID | |
848 | SNDRV_PCM_INFO_PAUSE | | 848 | SNDRV_PCM_INFO_PAUSE | |
849 | SNDRV_PCM_INFO_RESUME | | 849 | SNDRV_PCM_INFO_RESUME, |
850 | SNDRV_PCM_INFO_SYNC_START), | ||
851 | .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | | 850 | .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | |
852 | SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_S16_LE | | 851 | SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_S16_LE | |
853 | SNDRV_PCM_FMTBIT_U16_BE | SNDRV_PCM_FMTBIT_S16_BE | | 852 | SNDRV_PCM_FMTBIT_U16_BE | SNDRV_PCM_FMTBIT_S16_BE | |
@@ -868,12 +867,11 @@ static struct snd_pcm_hardware snd_cs4281_playback = | |||
868 | 867 | ||
869 | static struct snd_pcm_hardware snd_cs4281_capture = | 868 | static struct snd_pcm_hardware snd_cs4281_capture = |
870 | { | 869 | { |
871 | .info = (SNDRV_PCM_INFO_MMAP | | 870 | .info = SNDRV_PCM_INFO_MMAP | |
872 | SNDRV_PCM_INFO_INTERLEAVED | | 871 | SNDRV_PCM_INFO_INTERLEAVED | |
873 | SNDRV_PCM_INFO_MMAP_VALID | | 872 | SNDRV_PCM_INFO_MMAP_VALID | |
874 | SNDRV_PCM_INFO_PAUSE | | 873 | SNDRV_PCM_INFO_PAUSE | |
875 | SNDRV_PCM_INFO_RESUME | | 874 | SNDRV_PCM_INFO_RESUME, |
876 | SNDRV_PCM_INFO_SYNC_START), | ||
877 | .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | | 875 | .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | |
878 | SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_S16_LE | | 876 | SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_S16_LE | |
879 | SNDRV_PCM_FMTBIT_U16_BE | SNDRV_PCM_FMTBIT_S16_BE | | 877 | SNDRV_PCM_FMTBIT_U16_BE | SNDRV_PCM_FMTBIT_S16_BE | |
@@ -904,7 +902,6 @@ static int snd_cs4281_playback_open(struct snd_pcm_substream *substream) | |||
904 | dma->right_slot = 1; | 902 | dma->right_slot = 1; |
905 | runtime->private_data = dma; | 903 | runtime->private_data = dma; |
906 | runtime->hw = snd_cs4281_playback; | 904 | runtime->hw = snd_cs4281_playback; |
907 | snd_pcm_set_sync(substream); | ||
908 | /* should be detected from the AC'97 layer, but it seems | 905 | /* should be detected from the AC'97 layer, but it seems |
909 | that although CS4297A rev B reports 18-bit ADC resolution, | 906 | that although CS4297A rev B reports 18-bit ADC resolution, |
910 | samples are 20-bit */ | 907 | samples are 20-bit */ |
@@ -924,7 +921,6 @@ static int snd_cs4281_capture_open(struct snd_pcm_substream *substream) | |||
924 | dma->right_slot = 11; | 921 | dma->right_slot = 11; |
925 | runtime->private_data = dma; | 922 | runtime->private_data = dma; |
926 | runtime->hw = snd_cs4281_capture; | 923 | runtime->hw = snd_cs4281_capture; |
927 | snd_pcm_set_sync(substream); | ||
928 | /* should be detected from the AC'97 layer, but it seems | 924 | /* should be detected from the AC'97 layer, but it seems |
929 | that although CS4297A rev B reports 18-bit ADC resolution, | 925 | that although CS4297A rev B reports 18-bit ADC resolution, |
930 | samples are 20-bit */ | 926 | samples are 20-bit */ |
diff --git a/sound/pci/cs46xx/Makefile b/sound/pci/cs46xx/Makefile index d8b77b89aec4..67e811ec8539 100644 --- a/sound/pci/cs46xx/Makefile +++ b/sound/pci/cs46xx/Makefile | |||
@@ -1,12 +1,10 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-cs46xx-objs := cs46xx.o cs46xx_lib.o | 6 | snd-cs46xx-y := cs46xx.o cs46xx_lib.o |
7 | ifeq ($(CONFIG_SND_CS46XX_NEW_DSP),y) | 7 | snd-cs46xx-$(CONFIG_SND_CS46XX_NEW_DSP) += dsp_spos.o dsp_spos_scb_lib.o |
8 | snd-cs46xx-objs += dsp_spos.o dsp_spos_scb_lib.o | ||
9 | endif | ||
10 | 8 | ||
11 | # Toplevel Module Dependency | 9 | # Toplevel Module Dependency |
12 | obj-$(CONFIG_SND_CS46XX) += snd-cs46xx.o | 10 | obj-$(CONFIG_SND_CS46XX) += snd-cs46xx.o |
diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c index 8b6cd144d101..2699cb6c2cd6 100644 --- a/sound/pci/cs46xx/cs46xx.c +++ b/sound/pci/cs46xx/cs46xx.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * The driver for the Cirrus Logic's Sound Fusion CS46XX based soundcards | 2 | * The driver for the Cirrus Logic's Sound Fusion CS46XX based soundcards |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -34,7 +34,7 @@ | |||
34 | #include <sound/cs46xx.h> | 34 | #include <sound/cs46xx.h> |
35 | #include <sound/initval.h> | 35 | #include <sound/initval.h> |
36 | 36 | ||
37 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 37 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
38 | MODULE_DESCRIPTION("Cirrus Logic Sound Fusion CS46XX"); | 38 | MODULE_DESCRIPTION("Cirrus Logic Sound Fusion CS46XX"); |
39 | MODULE_LICENSE("GPL"); | 39 | MODULE_LICENSE("GPL"); |
40 | MODULE_SUPPORTED_DEVICE("{{Cirrus Logic,Sound Fusion (CS4280)}," | 40 | MODULE_SUPPORTED_DEVICE("{{Cirrus Logic,Sound Fusion (CS4280)}," |
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index 71d7aab9d869..2c7bfc9fef61 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Abramo Bagnara <abramo@alsa-project.org> | 3 | * Abramo Bagnara <abramo@alsa-project.org> |
4 | * Cirrus Logic, Inc. | 4 | * Cirrus Logic, Inc. |
5 | * Routines for control of Cirrus Logic CS461x chips | 5 | * Routines for control of Cirrus Logic CS461x chips |
@@ -1818,15 +1818,7 @@ static int snd_cs46xx_vol_iec958_put(struct snd_kcontrol *kcontrol, struct snd_c | |||
1818 | } | 1818 | } |
1819 | #endif | 1819 | #endif |
1820 | 1820 | ||
1821 | static int snd_mixer_boolean_info(struct snd_kcontrol *kcontrol, | 1821 | #define snd_mixer_boolean_info snd_ctl_boolean_mono_info |
1822 | struct snd_ctl_elem_info *uinfo) | ||
1823 | { | ||
1824 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1825 | uinfo->count = 1; | ||
1826 | uinfo->value.integer.min = 0; | ||
1827 | uinfo->value.integer.max = 1; | ||
1828 | return 0; | ||
1829 | } | ||
1830 | 1822 | ||
1831 | static int snd_cs46xx_iec958_get(struct snd_kcontrol *kcontrol, | 1823 | static int snd_cs46xx_iec958_get(struct snd_kcontrol *kcontrol, |
1832 | struct snd_ctl_elem_value *ucontrol) | 1824 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/pci/cs46xx/cs46xx_lib.h b/sound/pci/cs46xx/cs46xx_lib.h index 20dcd72f06c1..018a7de56017 100644 --- a/sound/pci/cs46xx/cs46xx_lib.h +++ b/sound/pci/cs46xx/cs46xx_lib.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * The driver for the Cirrus Logic's Sound Fusion CS46XX based soundcards | 2 | * The driver for the Cirrus Logic's Sound Fusion CS46XX based soundcards |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
diff --git a/sound/pci/cs46xx/dsp_spos.h b/sound/pci/cs46xx/dsp_spos.h index 0d246bca4184..f9e169d33c03 100644 --- a/sound/pci/cs46xx/dsp_spos.h +++ b/sound/pci/cs46xx/dsp_spos.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * The driver for the Cirrus Logic's Sound Fusion CS46XX based soundcards | 2 | * The driver for the Cirrus Logic's Sound Fusion CS46XX based soundcards |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
diff --git a/sound/pci/cs46xx/dsp_spos_scb_lib.c b/sound/pci/cs46xx/dsp_spos_scb_lib.c index 57e357de1500..eded4dfeba12 100644 --- a/sound/pci/cs46xx/dsp_spos_scb_lib.c +++ b/sound/pci/cs46xx/dsp_spos_scb_lib.c | |||
@@ -1480,7 +1480,7 @@ void cs46xx_dsp_destroy_pcm_channel (struct snd_cs46xx * chip, | |||
1480 | if (!pcm_channel->src_scb->ref_count) { | 1480 | if (!pcm_channel->src_scb->ref_count) { |
1481 | cs46xx_dsp_remove_scb(chip,pcm_channel->src_scb); | 1481 | cs46xx_dsp_remove_scb(chip,pcm_channel->src_scb); |
1482 | 1482 | ||
1483 | snd_assert (pcm_channel->src_slot >= 0 && pcm_channel->src_slot <= DSP_MAX_SRC_NR, | 1483 | snd_assert (pcm_channel->src_slot >= 0 && pcm_channel->src_slot < DSP_MAX_SRC_NR, |
1484 | return ); | 1484 | return ); |
1485 | 1485 | ||
1486 | ins->src_scb_slots[pcm_channel->src_slot] = 0; | 1486 | ins->src_scb_slots[pcm_channel->src_slot] = 0; |
diff --git a/sound/pci/cs5535audio/Makefile b/sound/pci/cs5535audio/Makefile index ad947b4c04cc..bb3d57e6a3cb 100644 --- a/sound/pci/cs5535audio/Makefile +++ b/sound/pci/cs5535audio/Makefile | |||
@@ -2,11 +2,8 @@ | |||
2 | # Makefile for cs5535audio | 2 | # Makefile for cs5535audio |
3 | # | 3 | # |
4 | 4 | ||
5 | snd-cs5535audio-objs := cs5535audio.o cs5535audio_pcm.o | 5 | snd-cs5535audio-y := cs5535audio.o cs5535audio_pcm.o |
6 | 6 | snd-cs5535audio-$(CONFIG_PM) += cs5535audio_pm.o | |
7 | ifeq ($(CONFIG_PM),y) | ||
8 | snd-cs5535audio-objs += cs5535audio_pm.o | ||
9 | endif | ||
10 | 7 | ||
11 | # Toplevel Module Dependency | 8 | # Toplevel Module Dependency |
12 | obj-$(CONFIG_SND_CS5535AUDIO) += snd-cs5535audio.o | 9 | obj-$(CONFIG_SND_CS5535AUDIO) += snd-cs5535audio.o |
diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c index b8e75ef9c1e6..2b35889787be 100644 --- a/sound/pci/cs5535audio/cs5535audio.c +++ b/sound/pci/cs5535audio/cs5535audio.c | |||
@@ -206,7 +206,6 @@ static void process_bm1_irq(struct cs5535audio *cs5535au) | |||
206 | static irqreturn_t snd_cs5535audio_interrupt(int irq, void *dev_id) | 206 | static irqreturn_t snd_cs5535audio_interrupt(int irq, void *dev_id) |
207 | { | 207 | { |
208 | u16 acc_irq_stat; | 208 | u16 acc_irq_stat; |
209 | u8 bm_stat; | ||
210 | unsigned char count; | 209 | unsigned char count; |
211 | struct cs5535audio *cs5535au = dev_id; | 210 | struct cs5535audio *cs5535au = dev_id; |
212 | 211 | ||
@@ -217,7 +216,7 @@ static irqreturn_t snd_cs5535audio_interrupt(int irq, void *dev_id) | |||
217 | 216 | ||
218 | if (!acc_irq_stat) | 217 | if (!acc_irq_stat) |
219 | return IRQ_NONE; | 218 | return IRQ_NONE; |
220 | for (count = 0; count < 10; count++) { | 219 | for (count = 0; count < 4; count++) { |
221 | if (acc_irq_stat & (1 << count)) { | 220 | if (acc_irq_stat & (1 << count)) { |
222 | switch (count) { | 221 | switch (count) { |
223 | case IRQ_STS: | 222 | case IRQ_STS: |
@@ -232,26 +231,9 @@ static irqreturn_t snd_cs5535audio_interrupt(int irq, void *dev_id) | |||
232 | case BM1_IRQ_STS: | 231 | case BM1_IRQ_STS: |
233 | process_bm1_irq(cs5535au); | 232 | process_bm1_irq(cs5535au); |
234 | break; | 233 | break; |
235 | case BM2_IRQ_STS: | ||
236 | bm_stat = cs_readb(cs5535au, ACC_BM2_STATUS); | ||
237 | break; | ||
238 | case BM3_IRQ_STS: | ||
239 | bm_stat = cs_readb(cs5535au, ACC_BM3_STATUS); | ||
240 | break; | ||
241 | case BM4_IRQ_STS: | ||
242 | bm_stat = cs_readb(cs5535au, ACC_BM4_STATUS); | ||
243 | break; | ||
244 | case BM5_IRQ_STS: | ||
245 | bm_stat = cs_readb(cs5535au, ACC_BM5_STATUS); | ||
246 | break; | ||
247 | case BM6_IRQ_STS: | ||
248 | bm_stat = cs_readb(cs5535au, ACC_BM6_STATUS); | ||
249 | break; | ||
250 | case BM7_IRQ_STS: | ||
251 | bm_stat = cs_readb(cs5535au, ACC_BM7_STATUS); | ||
252 | break; | ||
253 | default: | 234 | default: |
254 | snd_printk(KERN_ERR "Unexpected irq src\n"); | 235 | snd_printk(KERN_ERR "Unexpected irq src: " |
236 | "0x%x\n", acc_irq_stat); | ||
255 | break; | 237 | break; |
256 | } | 238 | } |
257 | } | 239 | } |
diff --git a/sound/pci/cs5535audio/cs5535audio.h b/sound/pci/cs5535audio/cs5535audio.h index 4fd1f31a6cf9..66bae7664193 100644 --- a/sound/pci/cs5535audio/cs5535audio.h +++ b/sound/pci/cs5535audio/cs5535audio.h | |||
@@ -16,57 +16,28 @@ | |||
16 | #define ACC_IRQ_STATUS 0x12 | 16 | #define ACC_IRQ_STATUS 0x12 |
17 | #define ACC_BM0_CMD 0x20 | 17 | #define ACC_BM0_CMD 0x20 |
18 | #define ACC_BM1_CMD 0x28 | 18 | #define ACC_BM1_CMD 0x28 |
19 | #define ACC_BM2_CMD 0x30 | ||
20 | #define ACC_BM3_CMD 0x38 | ||
21 | #define ACC_BM4_CMD 0x40 | ||
22 | #define ACC_BM5_CMD 0x48 | ||
23 | #define ACC_BM6_CMD 0x50 | ||
24 | #define ACC_BM7_CMD 0x58 | ||
25 | #define ACC_BM0_PRD 0x24 | 19 | #define ACC_BM0_PRD 0x24 |
26 | #define ACC_BM1_PRD 0x2C | 20 | #define ACC_BM1_PRD 0x2C |
27 | #define ACC_BM2_PRD 0x34 | ||
28 | #define ACC_BM3_PRD 0x3C | ||
29 | #define ACC_BM4_PRD 0x44 | ||
30 | #define ACC_BM5_PRD 0x4C | ||
31 | #define ACC_BM6_PRD 0x54 | ||
32 | #define ACC_BM7_PRD 0x5C | ||
33 | #define ACC_BM0_STATUS 0x21 | 21 | #define ACC_BM0_STATUS 0x21 |
34 | #define ACC_BM1_STATUS 0x29 | 22 | #define ACC_BM1_STATUS 0x29 |
35 | #define ACC_BM2_STATUS 0x31 | ||
36 | #define ACC_BM3_STATUS 0x39 | ||
37 | #define ACC_BM4_STATUS 0x41 | ||
38 | #define ACC_BM5_STATUS 0x49 | ||
39 | #define ACC_BM6_STATUS 0x51 | ||
40 | #define ACC_BM7_STATUS 0x59 | ||
41 | #define ACC_BM0_PNTR 0x60 | 23 | #define ACC_BM0_PNTR 0x60 |
42 | #define ACC_BM1_PNTR 0x64 | 24 | #define ACC_BM1_PNTR 0x64 |
43 | #define ACC_BM2_PNTR 0x68 | 25 | |
44 | #define ACC_BM3_PNTR 0x6C | ||
45 | #define ACC_BM4_PNTR 0x70 | ||
46 | #define ACC_BM5_PNTR 0x74 | ||
47 | #define ACC_BM6_PNTR 0x78 | ||
48 | #define ACC_BM7_PNTR 0x7C | ||
49 | /* acc_codec bar0 reg bits */ | 26 | /* acc_codec bar0 reg bits */ |
50 | /* ACC_IRQ_STATUS */ | 27 | /* ACC_IRQ_STATUS */ |
51 | #define IRQ_STS 0 | 28 | #define IRQ_STS 0 |
52 | #define WU_IRQ_STS 1 | 29 | #define WU_IRQ_STS 1 |
53 | #define BM0_IRQ_STS 2 | 30 | #define BM0_IRQ_STS 2 |
54 | #define BM1_IRQ_STS 3 | 31 | #define BM1_IRQ_STS 3 |
55 | #define BM2_IRQ_STS 4 | ||
56 | #define BM3_IRQ_STS 5 | ||
57 | #define BM4_IRQ_STS 6 | ||
58 | #define BM5_IRQ_STS 7 | ||
59 | #define BM6_IRQ_STS 8 | ||
60 | #define BM7_IRQ_STS 9 | ||
61 | /* ACC_BMX_STATUS */ | 32 | /* ACC_BMX_STATUS */ |
62 | #define EOP (1<<0) | 33 | #define EOP (1<<0) |
63 | #define BM_EOP_ERR (1<<1) | 34 | #define BM_EOP_ERR (1<<1) |
64 | /* ACC_BMX_CTL */ | 35 | /* ACC_BMX_CTL */ |
65 | #define BM_CTL_EN 0x00000001 | 36 | #define BM_CTL_EN 0x01 |
66 | #define BM_CTL_PAUSE 0x00000011 | 37 | #define BM_CTL_PAUSE 0x03 |
67 | #define BM_CTL_DIS 0x00000000 | 38 | #define BM_CTL_DIS 0x00 |
68 | #define BM_CTL_BYTE_ORD_LE 0x00000000 | 39 | #define BM_CTL_BYTE_ORD_LE 0x00 |
69 | #define BM_CTL_BYTE_ORD_BE 0x00000100 | 40 | #define BM_CTL_BYTE_ORD_BE 0x04 |
70 | /* cs5535 specific ac97 codec register defines */ | 41 | /* cs5535 specific ac97 codec register defines */ |
71 | #define CMD_MASK 0xFF00FFFF | 42 | #define CMD_MASK 0xFF00FFFF |
72 | #define CMD_NEW 0x00010000 | 43 | #define CMD_NEW 0x00010000 |
@@ -106,7 +77,6 @@ struct cs5535audio_dma { | |||
106 | struct snd_pcm_substream *substream; | 77 | struct snd_pcm_substream *substream; |
107 | unsigned int buf_addr, buf_bytes; | 78 | unsigned int buf_addr, buf_bytes; |
108 | unsigned int period_bytes, periods; | 79 | unsigned int period_bytes, periods; |
109 | int suspended; | ||
110 | u32 saved_prd; | 80 | u32 saved_prd; |
111 | }; | 81 | }; |
112 | 82 | ||
diff --git a/sound/pci/cs5535audio/cs5535audio_pcm.c b/sound/pci/cs5535audio/cs5535audio_pcm.c index 5450a9e8f133..21df0634af32 100644 --- a/sound/pci/cs5535audio/cs5535audio_pcm.c +++ b/sound/pci/cs5535audio/cs5535audio_pcm.c | |||
@@ -43,7 +43,6 @@ static struct snd_pcm_hardware snd_cs5535audio_playback = | |||
43 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 43 | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
44 | SNDRV_PCM_INFO_MMAP_VALID | | 44 | SNDRV_PCM_INFO_MMAP_VALID | |
45 | SNDRV_PCM_INFO_PAUSE | | 45 | SNDRV_PCM_INFO_PAUSE | |
46 | SNDRV_PCM_INFO_SYNC_START | | ||
47 | SNDRV_PCM_INFO_RESUME | 46 | SNDRV_PCM_INFO_RESUME |
48 | ), | 47 | ), |
49 | .formats = ( | 48 | .formats = ( |
@@ -71,8 +70,7 @@ static struct snd_pcm_hardware snd_cs5535audio_capture = | |||
71 | SNDRV_PCM_INFO_MMAP | | 70 | SNDRV_PCM_INFO_MMAP | |
72 | SNDRV_PCM_INFO_INTERLEAVED | | 71 | SNDRV_PCM_INFO_INTERLEAVED | |
73 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 72 | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
74 | SNDRV_PCM_INFO_MMAP_VALID | | 73 | SNDRV_PCM_INFO_MMAP_VALID |
75 | SNDRV_PCM_INFO_SYNC_START | ||
76 | ), | 74 | ), |
77 | .formats = ( | 75 | .formats = ( |
78 | SNDRV_PCM_FMTBIT_S16_LE | 76 | SNDRV_PCM_FMTBIT_S16_LE |
@@ -102,7 +100,6 @@ static int snd_cs5535audio_playback_open(struct snd_pcm_substream *substream) | |||
102 | runtime->hw = snd_cs5535audio_playback; | 100 | runtime->hw = snd_cs5535audio_playback; |
103 | cs5535au->playback_substream = substream; | 101 | cs5535au->playback_substream = substream; |
104 | runtime->private_data = &(cs5535au->dmas[CS5535AUDIO_DMA_PLAYBACK]); | 102 | runtime->private_data = &(cs5535au->dmas[CS5535AUDIO_DMA_PLAYBACK]); |
105 | snd_pcm_set_sync(substream); | ||
106 | if ((err = snd_pcm_hw_constraint_integer(runtime, | 103 | if ((err = snd_pcm_hw_constraint_integer(runtime, |
107 | SNDRV_PCM_HW_PARAM_PERIODS)) < 0) | 104 | SNDRV_PCM_HW_PARAM_PERIODS)) < 0) |
108 | return err; | 105 | return err; |
@@ -164,6 +161,7 @@ static int cs5535audio_build_dma_packets(struct cs5535audio *cs5535au, | |||
164 | jmpprd_addr = cpu_to_le32(lastdesc->addr + | 161 | jmpprd_addr = cpu_to_le32(lastdesc->addr + |
165 | (sizeof(struct cs5535audio_dma_desc)*periods)); | 162 | (sizeof(struct cs5535audio_dma_desc)*periods)); |
166 | 163 | ||
164 | dma->substream = substream; | ||
167 | dma->period_bytes = period_bytes; | 165 | dma->period_bytes = period_bytes; |
168 | dma->periods = periods; | 166 | dma->periods = periods; |
169 | spin_lock_irq(&cs5535au->reg_lock); | 167 | spin_lock_irq(&cs5535au->reg_lock); |
@@ -241,6 +239,7 @@ static void cs5535audio_clear_dma_packets(struct cs5535audio *cs5535au, | |||
241 | { | 239 | { |
242 | snd_dma_free_pages(&dma->desc_buf); | 240 | snd_dma_free_pages(&dma->desc_buf); |
243 | dma->desc_buf.area = NULL; | 241 | dma->desc_buf.area = NULL; |
242 | dma->substream = NULL; | ||
244 | } | 243 | } |
245 | 244 | ||
246 | static int snd_cs5535audio_hw_params(struct snd_pcm_substream *substream, | 245 | static int snd_cs5535audio_hw_params(struct snd_pcm_substream *substream, |
@@ -298,14 +297,12 @@ static int snd_cs5535audio_trigger(struct snd_pcm_substream *substream, int cmd) | |||
298 | break; | 297 | break; |
299 | case SNDRV_PCM_TRIGGER_RESUME: | 298 | case SNDRV_PCM_TRIGGER_RESUME: |
300 | dma->ops->enable_dma(cs5535au); | 299 | dma->ops->enable_dma(cs5535au); |
301 | dma->suspended = 0; | ||
302 | break; | 300 | break; |
303 | case SNDRV_PCM_TRIGGER_STOP: | 301 | case SNDRV_PCM_TRIGGER_STOP: |
304 | dma->ops->disable_dma(cs5535au); | 302 | dma->ops->disable_dma(cs5535au); |
305 | break; | 303 | break; |
306 | case SNDRV_PCM_TRIGGER_SUSPEND: | 304 | case SNDRV_PCM_TRIGGER_SUSPEND: |
307 | dma->ops->disable_dma(cs5535au); | 305 | dma->ops->disable_dma(cs5535au); |
308 | dma->suspended = 1; | ||
309 | break; | 306 | break; |
310 | default: | 307 | default: |
311 | snd_printk(KERN_ERR "unhandled trigger\n"); | 308 | snd_printk(KERN_ERR "unhandled trigger\n"); |
@@ -348,7 +345,6 @@ static int snd_cs5535audio_capture_open(struct snd_pcm_substream *substream) | |||
348 | runtime->hw = snd_cs5535audio_capture; | 345 | runtime->hw = snd_cs5535audio_capture; |
349 | cs5535au->capture_substream = substream; | 346 | cs5535au->capture_substream = substream; |
350 | runtime->private_data = &(cs5535au->dmas[CS5535AUDIO_DMA_CAPTURE]); | 347 | runtime->private_data = &(cs5535au->dmas[CS5535AUDIO_DMA_CAPTURE]); |
351 | snd_pcm_set_sync(substream); | ||
352 | if ((err = snd_pcm_hw_constraint_integer(runtime, | 348 | if ((err = snd_pcm_hw_constraint_integer(runtime, |
353 | SNDRV_PCM_HW_PARAM_PERIODS)) < 0) | 349 | SNDRV_PCM_HW_PARAM_PERIODS)) < 0) |
354 | return err; | 350 | return err; |
diff --git a/sound/pci/cs5535audio/cs5535audio_pm.c b/sound/pci/cs5535audio/cs5535audio_pm.c index 3e4d198a4502..838708f6d45e 100644 --- a/sound/pci/cs5535audio/cs5535audio_pm.c +++ b/sound/pci/cs5535audio/cs5535audio_pm.c | |||
@@ -64,18 +64,21 @@ int snd_cs5535audio_suspend(struct pci_dev *pci, pm_message_t state) | |||
64 | int i; | 64 | int i; |
65 | 65 | ||
66 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | 66 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
67 | snd_pcm_suspend_all(cs5535au->pcm); | ||
68 | snd_ac97_suspend(cs5535au->ac97); | ||
67 | for (i = 0; i < NUM_CS5535AUDIO_DMAS; i++) { | 69 | for (i = 0; i < NUM_CS5535AUDIO_DMAS; i++) { |
68 | struct cs5535audio_dma *dma = &cs5535au->dmas[i]; | 70 | struct cs5535audio_dma *dma = &cs5535au->dmas[i]; |
69 | if (dma && dma->substream && !dma->suspended) | 71 | if (dma && dma->substream) |
70 | dma->saved_prd = dma->ops->read_prd(cs5535au); | 72 | dma->saved_prd = dma->ops->read_prd(cs5535au); |
71 | } | 73 | } |
72 | snd_pcm_suspend_all(cs5535au->pcm); | ||
73 | snd_ac97_suspend(cs5535au->ac97); | ||
74 | /* save important regs, then disable aclink in hw */ | 74 | /* save important regs, then disable aclink in hw */ |
75 | snd_cs5535audio_stop_hardware(cs5535au); | 75 | snd_cs5535audio_stop_hardware(cs5535au); |
76 | 76 | ||
77 | if (pci_save_state(pci)) { | ||
78 | printk(KERN_ERR "cs5535audio: pci_save_state failed!\n"); | ||
79 | return -EIO; | ||
80 | } | ||
77 | pci_disable_device(pci); | 81 | pci_disable_device(pci); |
78 | pci_save_state(pci); | ||
79 | pci_set_power_state(pci, pci_choose_state(pci, state)); | 82 | pci_set_power_state(pci, pci_choose_state(pci, state)); |
80 | return 0; | 83 | return 0; |
81 | } | 84 | } |
@@ -89,7 +92,12 @@ int snd_cs5535audio_resume(struct pci_dev *pci) | |||
89 | int i; | 92 | int i; |
90 | 93 | ||
91 | pci_set_power_state(pci, PCI_D0); | 94 | pci_set_power_state(pci, PCI_D0); |
92 | pci_restore_state(pci); | 95 | if (pci_restore_state(pci) < 0) { |
96 | printk(KERN_ERR "cs5535audio: pci_restore_state failed, " | ||
97 | "disabling device\n"); | ||
98 | snd_card_disconnect(card); | ||
99 | return -EIO; | ||
100 | } | ||
93 | if (pci_enable_device(pci) < 0) { | 101 | if (pci_enable_device(pci) < 0) { |
94 | printk(KERN_ERR "cs5535audio: pci_enable_device failed, " | 102 | printk(KERN_ERR "cs5535audio: pci_enable_device failed, " |
95 | "disabling device\n"); | 103 | "disabling device\n"); |
@@ -112,17 +120,17 @@ int snd_cs5535audio_resume(struct pci_dev *pci) | |||
112 | if (!timeout) | 120 | if (!timeout) |
113 | snd_printk(KERN_ERR "Failure getting AC Link ready\n"); | 121 | snd_printk(KERN_ERR "Failure getting AC Link ready\n"); |
114 | 122 | ||
115 | /* we depend on ac97 to perform the codec power up */ | ||
116 | snd_ac97_resume(cs5535au->ac97); | ||
117 | /* set up rate regs, dma. actual initiation is done in trig */ | 123 | /* set up rate regs, dma. actual initiation is done in trig */ |
118 | for (i = 0; i < NUM_CS5535AUDIO_DMAS; i++) { | 124 | for (i = 0; i < NUM_CS5535AUDIO_DMAS; i++) { |
119 | struct cs5535audio_dma *dma = &cs5535au->dmas[i]; | 125 | struct cs5535audio_dma *dma = &cs5535au->dmas[i]; |
120 | if (dma && dma->substream && dma->suspended) { | 126 | if (dma && dma->substream) { |
121 | dma->substream->ops->prepare(dma->substream); | 127 | dma->substream->ops->prepare(dma->substream); |
122 | dma->ops->setup_prd(cs5535au, dma->saved_prd); | 128 | dma->ops->setup_prd(cs5535au, dma->saved_prd); |
123 | } | 129 | } |
124 | } | 130 | } |
125 | 131 | ||
132 | /* we depend on ac97 to perform the codec power up */ | ||
133 | snd_ac97_resume(cs5535au->ac97); | ||
126 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 134 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
127 | 135 | ||
128 | return 0; | 136 | return 0; |
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c index f27b6a733b96..499ee1a5319d 100644 --- a/sound/pci/echoaudio/echoaudio.c +++ b/sound/pci/echoaudio/echoaudio.c | |||
@@ -1595,15 +1595,7 @@ static struct snd_kcontrol_new snd_echo_clock_source_switch __devinitdata = { | |||
1595 | #ifdef ECHOCARD_HAS_PHANTOM_POWER | 1595 | #ifdef ECHOCARD_HAS_PHANTOM_POWER |
1596 | 1596 | ||
1597 | /******************* Phantom power switch *******************/ | 1597 | /******************* Phantom power switch *******************/ |
1598 | static int snd_echo_phantom_power_info(struct snd_kcontrol *kcontrol, | 1598 | #define snd_echo_phantom_power_info snd_ctl_boolean_mono_info |
1599 | struct snd_ctl_elem_info *uinfo) | ||
1600 | { | ||
1601 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1602 | uinfo->count = 1; | ||
1603 | uinfo->value.integer.min = 0; | ||
1604 | uinfo->value.integer.max = 1; | ||
1605 | return 0; | ||
1606 | } | ||
1607 | 1599 | ||
1608 | static int snd_echo_phantom_power_get(struct snd_kcontrol *kcontrol, | 1600 | static int snd_echo_phantom_power_get(struct snd_kcontrol *kcontrol, |
1609 | struct snd_ctl_elem_value *ucontrol) | 1601 | struct snd_ctl_elem_value *ucontrol) |
@@ -1646,15 +1638,7 @@ static struct snd_kcontrol_new snd_echo_phantom_power_switch __devinitdata = { | |||
1646 | #ifdef ECHOCARD_HAS_DIGITAL_IN_AUTOMUTE | 1638 | #ifdef ECHOCARD_HAS_DIGITAL_IN_AUTOMUTE |
1647 | 1639 | ||
1648 | /******************* Digital input automute switch *******************/ | 1640 | /******************* Digital input automute switch *******************/ |
1649 | static int snd_echo_automute_info(struct snd_kcontrol *kcontrol, | 1641 | #define snd_echo_automute_info snd_ctl_boolean_mono_info |
1650 | struct snd_ctl_elem_info *uinfo) | ||
1651 | { | ||
1652 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1653 | uinfo->count = 1; | ||
1654 | uinfo->value.integer.min = 0; | ||
1655 | uinfo->value.integer.max = 1; | ||
1656 | return 0; | ||
1657 | } | ||
1658 | 1642 | ||
1659 | static int snd_echo_automute_get(struct snd_kcontrol *kcontrol, | 1643 | static int snd_echo_automute_get(struct snd_kcontrol *kcontrol, |
1660 | struct snd_ctl_elem_value *ucontrol) | 1644 | struct snd_ctl_elem_value *ucontrol) |
@@ -1695,18 +1679,7 @@ static struct snd_kcontrol_new snd_echo_automute_switch __devinitdata = { | |||
1695 | 1679 | ||
1696 | 1680 | ||
1697 | /******************* VU-meters switch *******************/ | 1681 | /******************* VU-meters switch *******************/ |
1698 | static int snd_echo_vumeters_switch_info(struct snd_kcontrol *kcontrol, | 1682 | #define snd_echo_vumeters_switch_info snd_ctl_boolean_mono_info |
1699 | struct snd_ctl_elem_info *uinfo) | ||
1700 | { | ||
1701 | struct echoaudio *chip; | ||
1702 | |||
1703 | chip = snd_kcontrol_chip(kcontrol); | ||
1704 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1705 | uinfo->count = 1; | ||
1706 | uinfo->value.integer.min = 0; | ||
1707 | uinfo->value.integer.max = 1; | ||
1708 | return 0; | ||
1709 | } | ||
1710 | 1683 | ||
1711 | static int snd_echo_vumeters_switch_put(struct snd_kcontrol *kcontrol, | 1684 | static int snd_echo_vumeters_switch_put(struct snd_kcontrol *kcontrol, |
1712 | struct snd_ctl_elem_value *ucontrol) | 1685 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/pci/echoaudio/echoaudio_dsp.c b/sound/pci/echoaudio/echoaudio_dsp.c index 42afa837d9b4..e6c100770392 100644 --- a/sound/pci/echoaudio/echoaudio_dsp.c +++ b/sound/pci/echoaudio/echoaudio_dsp.c | |||
@@ -43,11 +43,11 @@ static int wait_handshake(struct echoaudio *chip) | |||
43 | { | 43 | { |
44 | int i; | 44 | int i; |
45 | 45 | ||
46 | /* Wait up to 10ms for the handshake from the DSP */ | 46 | /* Wait up to 20ms for the handshake from the DSP */ |
47 | for (i = 0; i < HANDSHAKE_TIMEOUT; i++) { | 47 | for (i = 0; i < HANDSHAKE_TIMEOUT; i++) { |
48 | /* Look for the handshake value */ | 48 | /* Look for the handshake value */ |
49 | barrier(); | ||
49 | if (chip->comm_page->handshake) { | 50 | if (chip->comm_page->handshake) { |
50 | /*if (i) DE_ACT(("Handshake time: %d\n", i));*/ | ||
51 | return 0; | 51 | return 0; |
52 | } | 52 | } |
53 | udelay(1); | 53 | udelay(1); |
diff --git a/sound/pci/echoaudio/echoaudio_dsp.h b/sound/pci/echoaudio/echoaudio_dsp.h index e55ee00991ac..e352f3ae292c 100644 --- a/sound/pci/echoaudio/echoaudio_dsp.h +++ b/sound/pci/echoaudio/echoaudio_dsp.h | |||
@@ -642,18 +642,18 @@ struct comm_page { /* Base Length*/ | |||
642 | u32 flags; /* See Appendix A below 0x004 4 */ | 642 | u32 flags; /* See Appendix A below 0x004 4 */ |
643 | u32 unused; /* Unused entry 0x008 4 */ | 643 | u32 unused; /* Unused entry 0x008 4 */ |
644 | u32 sample_rate; /* Card sample rate in Hz 0x00c 4 */ | 644 | u32 sample_rate; /* Card sample rate in Hz 0x00c 4 */ |
645 | volatile u32 handshake; /* DSP command handshake 0x010 4 */ | 645 | u32 handshake; /* DSP command handshake 0x010 4 */ |
646 | u32 cmd_start; /* Chs. to start mask 0x014 4 */ | 646 | u32 cmd_start; /* Chs. to start mask 0x014 4 */ |
647 | u32 cmd_stop; /* Chs. to stop mask 0x018 4 */ | 647 | u32 cmd_stop; /* Chs. to stop mask 0x018 4 */ |
648 | u32 cmd_reset; /* Chs. to reset mask 0x01c 4 */ | 648 | u32 cmd_reset; /* Chs. to reset mask 0x01c 4 */ |
649 | u16 audio_format[DSP_MAXPIPES]; /* Chs. audio format 0x020 32*2 */ | 649 | u16 audio_format[DSP_MAXPIPES]; /* Chs. audio format 0x020 32*2 */ |
650 | struct sg_entry sglist_addr[DSP_MAXPIPES]; | 650 | struct sg_entry sglist_addr[DSP_MAXPIPES]; |
651 | /* Chs. Physical sglist addrs 0x060 32*8 */ | 651 | /* Chs. Physical sglist addrs 0x060 32*8 */ |
652 | volatile u32 position[DSP_MAXPIPES]; | 652 | u32 position[DSP_MAXPIPES]; |
653 | /* Positions for ea. ch. 0x160 32*4 */ | 653 | /* Positions for ea. ch. 0x160 32*4 */ |
654 | volatile s8 vu_meter[DSP_MAXPIPES]; | 654 | s8 vu_meter[DSP_MAXPIPES]; |
655 | /* VU meters 0x1e0 32*1 */ | 655 | /* VU meters 0x1e0 32*1 */ |
656 | volatile s8 peak_meter[DSP_MAXPIPES]; | 656 | s8 peak_meter[DSP_MAXPIPES]; |
657 | /* Peak meters 0x200 32*1 */ | 657 | /* Peak meters 0x200 32*1 */ |
658 | s8 line_out_level[DSP_MAXAUDIOOUTPUTS]; | 658 | s8 line_out_level[DSP_MAXAUDIOOUTPUTS]; |
659 | /* Output gain 0x220 16*1 */ | 659 | /* Output gain 0x220 16*1 */ |
@@ -665,7 +665,7 @@ struct comm_page { /* Base Length*/ | |||
665 | /* Gina/Darla play filters - obsolete 0x3c0 168*4 */ | 665 | /* Gina/Darla play filters - obsolete 0x3c0 168*4 */ |
666 | u32 rec_coeff[MAX_REC_TAPS]; | 666 | u32 rec_coeff[MAX_REC_TAPS]; |
667 | /* Gina/Darla record filters - obsolete 0x660 192*4 */ | 667 | /* Gina/Darla record filters - obsolete 0x660 192*4 */ |
668 | volatile u16 midi_input[MIDI_IN_BUFFER_SIZE]; | 668 | u16 midi_input[MIDI_IN_BUFFER_SIZE]; |
669 | /* MIDI input data transfer buffer 0x960 256*2 */ | 669 | /* MIDI input data transfer buffer 0x960 256*2 */ |
670 | u8 gd_clock_state; /* Chg Gina/Darla clock state 0xb60 1 */ | 670 | u8 gd_clock_state; /* Chg Gina/Darla clock state 0xb60 1 */ |
671 | u8 gd_spdif_status; /* Chg. Gina/Darla S/PDIF state 0xb61 1 */ | 671 | u8 gd_spdif_status; /* Chg. Gina/Darla S/PDIF state 0xb61 1 */ |
@@ -674,11 +674,10 @@ struct comm_page { /* Base Length*/ | |||
674 | u32 nominal_level_mask; /* -10 level enable mask 0xb64 4 */ | 674 | u32 nominal_level_mask; /* -10 level enable mask 0xb64 4 */ |
675 | u16 input_clock; /* Chg. Input clock state 0xb68 2 */ | 675 | u16 input_clock; /* Chg. Input clock state 0xb68 2 */ |
676 | u16 output_clock; /* Chg. Output clock state 0xb6a 2 */ | 676 | u16 output_clock; /* Chg. Output clock state 0xb6a 2 */ |
677 | volatile u32 status_clocks; | 677 | u32 status_clocks; /* Current Input clock state 0xb6c 4 */ |
678 | /* Current Input clock state 0xb6c 4 */ | ||
679 | u32 ext_box_status; /* External box status 0xb70 4 */ | 678 | u32 ext_box_status; /* External box status 0xb70 4 */ |
680 | u32 cmd_add_buffer; /* Pipes to add (obsolete) 0xb74 4 */ | 679 | u32 cmd_add_buffer; /* Pipes to add (obsolete) 0xb74 4 */ |
681 | volatile u32 midi_out_free_count; | 680 | u32 midi_out_free_count; |
682 | /* # of bytes free in MIDI output FIFO 0xb78 4 */ | 681 | /* # of bytes free in MIDI output FIFO 0xb78 4 */ |
683 | u32 unused2; /* Cyclic pipes 0xb7c 4 */ | 682 | u32 unused2; /* Cyclic pipes 0xb7c 4 */ |
684 | u32 control_register; | 683 | u32 control_register; |
diff --git a/sound/pci/emu10k1/Makefile b/sound/pci/emu10k1/Makefile index e521c38cef45..cf2d5636d8be 100644 --- a/sound/pci/emu10k1/Makefile +++ b/sound/pci/emu10k1/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-emu10k1-objs := emu10k1.o emu10k1_main.o \ | 6 | snd-emu10k1-objs := emu10k1.o emu10k1_main.o \ |
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c index 55caf341933a..9680caff90c8 100644 --- a/sound/pci/emu10k1/emu10k1.c +++ b/sound/pci/emu10k1/emu10k1.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * The driver for the EMU10K1 (SB Live!) based soundcards | 2 | * The driver for the EMU10K1 (SB Live!) based soundcards |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk> | 5 | * Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk> |
6 | * Added support for Audigy 2 Value. | 6 | * Added support for Audigy 2 Value. |
@@ -32,7 +32,7 @@ | |||
32 | #include <sound/emu10k1.h> | 32 | #include <sound/emu10k1.h> |
33 | #include <sound/initval.h> | 33 | #include <sound/initval.h> |
34 | 34 | ||
35 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 35 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
36 | MODULE_DESCRIPTION("EMU10K1"); | 36 | MODULE_DESCRIPTION("EMU10K1"); |
37 | MODULE_LICENSE("GPL"); | 37 | MODULE_LICENSE("GPL"); |
38 | MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB Live!/PCI512/E-mu APS}," | 38 | MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB Live!/PCI512/E-mu APS}," |
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index 404ae1be0a4b..97c41d72a255 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Creative Labs, Inc. | 3 | * Creative Labs, Inc. |
4 | * Routines for control of EMU10K1 chips | 4 | * Routines for control of EMU10K1 chips |
5 | * | 5 | * |
@@ -31,6 +31,8 @@ | |||
31 | * | 31 | * |
32 | */ | 32 | */ |
33 | 33 | ||
34 | #include <linux/sched.h> | ||
35 | #include <linux/kthread.h> | ||
34 | #include <sound/driver.h> | 36 | #include <sound/driver.h> |
35 | #include <linux/delay.h> | 37 | #include <linux/delay.h> |
36 | #include <linux/init.h> | 38 | #include <linux/init.h> |
@@ -702,6 +704,65 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 * emu, const char * file | |||
702 | return 0; | 704 | return 0; |
703 | } | 705 | } |
704 | 706 | ||
707 | int emu1010_firmware_thread(void *data) { | ||
708 | struct snd_emu10k1 * emu = data; | ||
709 | int tmp,tmp2; | ||
710 | int reg; | ||
711 | int err; | ||
712 | |||
713 | for (;;) { | ||
714 | /* Delay to allow Audio Dock to settle */ | ||
715 | msleep(1000); | ||
716 | if (kthread_should_stop()) | ||
717 | break; | ||
718 | snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp ); /* IRQ Status */ | ||
719 | snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ® ); /* OPTIONS: Which cards are attached to the EMU */ | ||
720 | if (reg & EMU_HANA_OPTION_DOCK_OFFLINE) { | ||
721 | /* Audio Dock attached */ | ||
722 | /* Return to Audio Dock programming mode */ | ||
723 | snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware\n"); | ||
724 | snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK ); | ||
725 | if (emu->card_capabilities->emu1010 == 1) { | ||
726 | if ((err = snd_emu1010_load_firmware(emu, DOCK_FILENAME)) != 0) { | ||
727 | return err; | ||
728 | } | ||
729 | } else if (emu->card_capabilities->emu1010 == 2) { | ||
730 | if ((err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME)) != 0) { | ||
731 | return err; | ||
732 | } | ||
733 | } else if (emu->card_capabilities->emu1010 == 3) { | ||
734 | if ((err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME)) != 0) { | ||
735 | return err; | ||
736 | } | ||
737 | } | ||
738 | |||
739 | snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0 ); | ||
740 | snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, ® ); | ||
741 | snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_IRQ_STATUS=0x%x\n",reg); | ||
742 | /* ID, should read & 0x7f = 0x55 when FPGA programmed. */ | ||
743 | snd_emu1010_fpga_read(emu, EMU_HANA_ID, ® ); | ||
744 | snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_ID=0x%x\n",reg); | ||
745 | if ((reg & 0x1f) != 0x15) { | ||
746 | /* FPGA failed to be programmed */ | ||
747 | snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware file failed, reg=0x%x\n", reg); | ||
748 | return 0; | ||
749 | return -ENODEV; | ||
750 | } | ||
751 | snd_printk(KERN_INFO "emu1010: Audio Dock Firmware loaded\n"); | ||
752 | snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp ); | ||
753 | snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2 ); | ||
754 | snd_printk("Audio Dock ver:%d.%d\n",tmp ,tmp2); | ||
755 | /* Sync clocking between 1010 and Dock */ | ||
756 | /* Allow DLL to settle */ | ||
757 | msleep(10); | ||
758 | /* Unmute all. Default is muted after a firmware load */ | ||
759 | snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE ); | ||
760 | break; | ||
761 | } | ||
762 | } | ||
763 | return 0; | ||
764 | } | ||
765 | |||
705 | /* | 766 | /* |
706 | * EMU-1010 - details found out from this driver, official MS Win drivers, | 767 | * EMU-1010 - details found out from this driver, official MS Win drivers, |
707 | * testing the card: | 768 | * testing the card: |
@@ -817,8 +878,16 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) | |||
817 | snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ® ); | 878 | snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ® ); |
818 | snd_printk(KERN_INFO "emu1010: Card options=0x%x\n",reg); | 879 | snd_printk(KERN_INFO "emu1010: Card options=0x%x\n",reg); |
819 | snd_emu1010_fpga_read(emu, EMU_HANA_OPTICAL_TYPE, &tmp ); | 880 | snd_emu1010_fpga_read(emu, EMU_HANA_OPTICAL_TYPE, &tmp ); |
820 | /* ADAT input. */ | 881 | /* Optical -> ADAT I/O */ |
821 | snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, 0x01 ); | 882 | /* 0 : SPDIF |
883 | * 1 : ADAT | ||
884 | */ | ||
885 | emu->emu1010.optical_in = 1; /* IN_ADAT */ | ||
886 | emu->emu1010.optical_out = 1; /* IN_ADAT */ | ||
887 | tmp = 0; | ||
888 | tmp = (emu->emu1010.optical_in ? EMU_HANA_OPTICAL_IN_ADAT : 0) | | ||
889 | (emu->emu1010.optical_out ? EMU_HANA_OPTICAL_OUT_ADAT : 0); | ||
890 | snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, tmp ); | ||
822 | snd_emu1010_fpga_read(emu, EMU_HANA_ADC_PADS, &tmp ); | 891 | snd_emu1010_fpga_read(emu, EMU_HANA_ADC_PADS, &tmp ); |
823 | /* Set no attenuation on Audio Dock pads. */ | 892 | /* Set no attenuation on Audio Dock pads. */ |
824 | snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, 0x00 ); | 893 | snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, 0x00 ); |
@@ -1004,49 +1073,12 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) | |||
1004 | snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp ); | 1073 | snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp ); |
1005 | snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10 ); /* SPDIF Format spdif (or 0x11 for aes/ebu) */ | 1074 | snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10 ); /* SPDIF Format spdif (or 0x11 for aes/ebu) */ |
1006 | 1075 | ||
1007 | /* Delay to allow Audio Dock to settle */ | 1076 | /* Start Micro/Audio Dock firmware loader thread */ |
1008 | msleep(100); | 1077 | emu->emu1010.firmware_thread = kthread_create(&emu1010_firmware_thread, |
1009 | snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp ); /* IRQ Status */ | 1078 | emu, |
1010 | snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ® ); /* OPTIONS: Which cards are attached to the EMU */ | 1079 | "emu1010_firmware"); |
1011 | /* FIXME: The loading of this should be able to happen any time, | 1080 | wake_up_process(emu->emu1010.firmware_thread); |
1012 | * as the user can plug/unplug it at any time | ||
1013 | */ | ||
1014 | if (reg & (EMU_HANA_OPTION_DOCK_ONLINE | EMU_HANA_OPTION_DOCK_OFFLINE) ) { | ||
1015 | /* Audio Dock attached */ | ||
1016 | /* Return to Audio Dock programming mode */ | ||
1017 | snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware\n"); | ||
1018 | snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK ); | ||
1019 | if (emu->card_capabilities->emu1010 == 1) { | ||
1020 | if ((err = snd_emu1010_load_firmware(emu, DOCK_FILENAME)) != 0) { | ||
1021 | return err; | ||
1022 | } | ||
1023 | } else if (emu->card_capabilities->emu1010 == 2) { | ||
1024 | if ((err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME)) != 0) { | ||
1025 | return err; | ||
1026 | } | ||
1027 | } else if (emu->card_capabilities->emu1010 == 3) { | ||
1028 | if ((err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME)) != 0) { | ||
1029 | return err; | ||
1030 | } | ||
1031 | } | ||
1032 | 1081 | ||
1033 | snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0 ); | ||
1034 | snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, ® ); | ||
1035 | snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_IRQ_STATUS=0x%x\n",reg); | ||
1036 | /* ID, should read & 0x7f = 0x55 when FPGA programmed. */ | ||
1037 | snd_emu1010_fpga_read(emu, EMU_HANA_ID, ® ); | ||
1038 | snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_ID=0x%x\n",reg); | ||
1039 | if ((reg & 0x3f) != 0x15) { | ||
1040 | /* FPGA failed to be programmed */ | ||
1041 | snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware file failed, reg=0x%x\n", reg); | ||
1042 | return 0; | ||
1043 | return -ENODEV; | ||
1044 | } | ||
1045 | snd_printk(KERN_INFO "emu1010: Audio Dock Firmware loaded\n"); | ||
1046 | snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp ); | ||
1047 | snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2 ); | ||
1048 | snd_printk("Audio Dock ver:%d.%d\n",tmp ,tmp2); | ||
1049 | } | ||
1050 | #if 0 | 1082 | #if 0 |
1051 | snd_emu1010_fpga_link_dst_src_write(emu, | 1083 | snd_emu1010_fpga_link_dst_src_write(emu, |
1052 | EMU_DST_HAMOA_DAC_LEFT1, EMU_SRC_ALICE_EMU32B + 2); /* ALICE2 bus 0xa2 */ | 1084 | EMU_DST_HAMOA_DAC_LEFT1, EMU_SRC_ALICE_EMU32B + 2); /* ALICE2 bus 0xa2 */ |
@@ -1132,7 +1164,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) | |||
1132 | emu->emu1010.output_source[23] = 28; | 1164 | emu->emu1010.output_source[23] = 28; |
1133 | 1165 | ||
1134 | /* TEMP: Select SPDIF in/out */ | 1166 | /* TEMP: Select SPDIF in/out */ |
1135 | snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, 0x0); /* Output spdif */ | 1167 | //snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, 0x0); /* Output spdif */ |
1136 | 1168 | ||
1137 | /* TEMP: Select 48kHz SPDIF out */ | 1169 | /* TEMP: Select 48kHz SPDIF out */ |
1138 | snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x0); /* Mute all */ | 1170 | snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x0); /* Mute all */ |
@@ -1173,6 +1205,7 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu) | |||
1173 | if (emu->card_capabilities->emu1010) { | 1205 | if (emu->card_capabilities->emu1010) { |
1174 | /* Disable 48Volt power to Audio Dock */ | 1206 | /* Disable 48Volt power to Audio Dock */ |
1175 | snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0 ); | 1207 | snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0 ); |
1208 | kthread_stop(emu->emu1010.firmware_thread); | ||
1176 | } | 1209 | } |
1177 | if (emu->memhdr) | 1210 | if (emu->memhdr) |
1178 | snd_util_memhdr_free(emu->memhdr); | 1211 | snd_util_memhdr_free(emu->memhdr); |
@@ -1722,8 +1755,9 @@ int __devinit snd_emu10k1_create(struct snd_card *card, | |||
1722 | goto error; | 1755 | goto error; |
1723 | } | 1756 | } |
1724 | 1757 | ||
1725 | emu->page_ptr_table = (void **)vmalloc(emu->max_cache_pages * sizeof(void*)); | 1758 | emu->page_ptr_table = vmalloc(emu->max_cache_pages * sizeof(void *)); |
1726 | emu->page_addr_table = (unsigned long*)vmalloc(emu->max_cache_pages * sizeof(unsigned long)); | 1759 | emu->page_addr_table = vmalloc(emu->max_cache_pages * |
1760 | sizeof(unsigned long)); | ||
1727 | if (emu->page_ptr_table == NULL || emu->page_addr_table == NULL) { | 1761 | if (emu->page_ptr_table == NULL || emu->page_addr_table == NULL) { |
1728 | err = -ENOMEM; | 1762 | err = -ENOMEM; |
1729 | goto error; | 1763 | goto error; |
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c index e4af7a9b808c..1ec7ebaff9e9 100644 --- a/sound/pci/emu10k1/emu10k1x.c +++ b/sound/pci/emu10k1/emu10k1x.c | |||
@@ -1062,14 +1062,7 @@ static int __devinit snd_emu10k1x_proc_init(struct emu10k1x * emu) | |||
1062 | return 0; | 1062 | return 0; |
1063 | } | 1063 | } |
1064 | 1064 | ||
1065 | static int snd_emu10k1x_shared_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1065 | #define snd_emu10k1x_shared_spdif_info snd_ctl_boolean_mono_info |
1066 | { | ||
1067 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1068 | uinfo->count = 1; | ||
1069 | uinfo->value.integer.min = 0; | ||
1070 | uinfo->value.integer.max = 1; | ||
1071 | return 0; | ||
1072 | } | ||
1073 | 1066 | ||
1074 | static int snd_emu10k1x_shared_spdif_get(struct snd_kcontrol *kcontrol, | 1067 | static int snd_emu10k1x_shared_spdif_get(struct snd_kcontrol *kcontrol, |
1075 | struct snd_ctl_elem_value *ucontrol) | 1068 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c index 7206c0fa06f2..9bf1cd592199 100644 --- a/sound/pci/emu10k1/emufx.c +++ b/sound/pci/emu10k1/emufx.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Creative Labs, Inc. | 3 | * Creative Labs, Inc. |
4 | * Routines for effect processor FX8010 | 4 | * Routines for effect processor FX8010 |
5 | * | 5 | * |
@@ -642,10 +642,8 @@ snd_emu10k1_look_for_ctl(struct snd_emu10k1 *emu, struct snd_ctl_elem_id *id) | |||
642 | { | 642 | { |
643 | struct snd_emu10k1_fx8010_ctl *ctl; | 643 | struct snd_emu10k1_fx8010_ctl *ctl; |
644 | struct snd_kcontrol *kcontrol; | 644 | struct snd_kcontrol *kcontrol; |
645 | struct list_head *list; | 645 | |
646 | 646 | list_for_each_entry(ctl, &emu->fx8010.gpr_ctl, list) { | |
647 | list_for_each(list, &emu->fx8010.gpr_ctl) { | ||
648 | ctl = emu10k1_gpr_ctl(list); | ||
649 | kcontrol = ctl->kcontrol; | 647 | kcontrol = ctl->kcontrol; |
650 | if (kcontrol->id.iface == id->iface && | 648 | if (kcontrol->id.iface == id->iface && |
651 | !strcmp(kcontrol->id.name, id->name) && | 649 | !strcmp(kcontrol->id.name, id->name) && |
@@ -895,14 +893,12 @@ static int snd_emu10k1_list_controls(struct snd_emu10k1 *emu, | |||
895 | struct snd_emu10k1_fx8010_control_gpr *gctl; | 893 | struct snd_emu10k1_fx8010_control_gpr *gctl; |
896 | struct snd_emu10k1_fx8010_ctl *ctl; | 894 | struct snd_emu10k1_fx8010_ctl *ctl; |
897 | struct snd_ctl_elem_id *id; | 895 | struct snd_ctl_elem_id *id; |
898 | struct list_head *list; | ||
899 | 896 | ||
900 | gctl = kmalloc(sizeof(*gctl), GFP_KERNEL); | 897 | gctl = kmalloc(sizeof(*gctl), GFP_KERNEL); |
901 | if (! gctl) | 898 | if (! gctl) |
902 | return -ENOMEM; | 899 | return -ENOMEM; |
903 | 900 | ||
904 | list_for_each(list, &emu->fx8010.gpr_ctl) { | 901 | list_for_each_entry(ctl, &emu->fx8010.gpr_ctl, list) { |
905 | ctl = emu10k1_gpr_ctl(list); | ||
906 | total++; | 902 | total++; |
907 | if (icode->gpr_list_controls && | 903 | if (icode->gpr_list_controls && |
908 | i < icode->gpr_list_control_count) { | 904 | i < icode->gpr_list_control_count) { |
@@ -1207,7 +1203,7 @@ static int __devinit _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu) | |||
1207 | A_OP(icode, &ptr, iMAC0, A_GPR(playback+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_FRONT)); | 1203 | A_OP(icode, &ptr, iMAC0, A_GPR(playback+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_FRONT)); |
1208 | snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Front Playback Volume", gpr, 100); | 1204 | snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Front Playback Volume", gpr, 100); |
1209 | gpr += 2; | 1205 | gpr += 2; |
1210 | 1206 | ||
1211 | /* PCM Surround Playback (independent from stereo mix) */ | 1207 | /* PCM Surround Playback (independent from stereo mix) */ |
1212 | A_OP(icode, &ptr, iMAC0, A_GPR(playback+2), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_REAR)); | 1208 | A_OP(icode, &ptr, iMAC0, A_GPR(playback+2), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_REAR)); |
1213 | A_OP(icode, &ptr, iMAC0, A_GPR(playback+3), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_REAR)); | 1209 | A_OP(icode, &ptr, iMAC0, A_GPR(playback+3), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_REAR)); |
@@ -1267,8 +1263,16 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) | |||
1267 | 1263 | ||
1268 | /* emu1212 DSP 0 and DSP 1 Capture */ | 1264 | /* emu1212 DSP 0 and DSP 1 Capture */ |
1269 | if (emu->card_capabilities->emu1010) { | 1265 | if (emu->card_capabilities->emu1010) { |
1270 | A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_GPR(capture+0), A_GPR(gpr), A_P16VIN(0x0)); | 1266 | if (emu->card_capabilities->ca0108_chip) { |
1271 | A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr+1), A_P16VIN(0x1)); | 1267 | /* Note:JCD:No longer bit shift lower 16bits to upper 16bits of 32bit value. */ |
1268 | A_OP(icode, &ptr, iMACINT0, A_GPR(tmp), A_C_00000000, A3_EMU32IN(0x0), A_C_00000001); | ||
1269 | A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_GPR(capture+0), A_GPR(gpr), A_GPR(tmp)); | ||
1270 | A_OP(icode, &ptr, iMACINT0, A_GPR(tmp), A_C_00000000, A3_EMU32IN(0x1), A_C_00000001); | ||
1271 | A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr), A_GPR(tmp)); | ||
1272 | } else { | ||
1273 | A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_GPR(capture+0), A_GPR(gpr), A_P16VIN(0x0)); | ||
1274 | A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr+1), A_P16VIN(0x1)); | ||
1275 | } | ||
1272 | snd_emu10k1_init_stereo_control(&controls[nctl++], "EMU Capture Volume", gpr, 0); | 1276 | snd_emu10k1_init_stereo_control(&controls[nctl++], "EMU Capture Volume", gpr, 0); |
1273 | gpr += 2; | 1277 | gpr += 2; |
1274 | } | 1278 | } |
@@ -1516,7 +1520,11 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) | |||
1516 | /* EMU1010 Outputs from PCM Front, Rear, Center, LFE, Side */ | 1520 | /* EMU1010 Outputs from PCM Front, Rear, Center, LFE, Side */ |
1517 | snd_printk("EMU outputs on\n"); | 1521 | snd_printk("EMU outputs on\n"); |
1518 | for (z = 0; z < 8; z++) { | 1522 | for (z = 0; z < 8; z++) { |
1519 | A_OP(icode, &ptr, iACC3, A_EMU32OUTL(z), A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), A_C_00000000, A_C_00000000); | 1523 | if (emu->card_capabilities->ca0108_chip) { |
1524 | A_OP(icode, &ptr, iACC3, A3_EMU32OUT(z), A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), A_C_00000000, A_C_00000000); | ||
1525 | } else { | ||
1526 | A_OP(icode, &ptr, iACC3, A_EMU32OUTL(z), A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), A_C_00000000, A_C_00000000); | ||
1527 | } | ||
1520 | } | 1528 | } |
1521 | } | 1529 | } |
1522 | 1530 | ||
@@ -1557,106 +1565,116 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) | |||
1557 | #endif | 1565 | #endif |
1558 | 1566 | ||
1559 | if (emu->card_capabilities->emu1010) { | 1567 | if (emu->card_capabilities->emu1010) { |
1560 | snd_printk("EMU inputs on\n"); | 1568 | if (emu->card_capabilities->ca0108_chip) { |
1561 | /* Capture 16 (originally 8) channels of S32_LE sound */ | 1569 | snd_printk("EMU2 inputs on\n"); |
1562 | 1570 | for (z = 0; z < 0x10; z++) { | |
1563 | /* printk("emufx.c: gpr=0x%x, tmp=0x%x\n",gpr, tmp); */ | 1571 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, |
1564 | /* For the EMU1010: How to get 32bit values from the DSP. High 16bits into L, low 16bits into R. */ | 1572 | bit_shifter16, |
1565 | /* A_P16VIN(0) is delayed by one sample, | 1573 | A3_EMU32IN(z), |
1566 | * so all other A_P16VIN channels will need to also be delayed | 1574 | A_FXBUS2(z*2) ); |
1567 | */ | 1575 | } |
1568 | /* Left ADC in. 1 of 2 */ | 1576 | } else { |
1569 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_P16VIN(0x0), A_FXBUS2(0) ); | 1577 | snd_printk("EMU inputs on\n"); |
1570 | /* Right ADC in 1 of 2 */ | 1578 | /* Capture 16 (originally 8) channels of S32_LE sound */ |
1571 | gpr_map[gpr++] = 0x00000000; | 1579 | |
1572 | /* Delaying by one sample: instead of copying the input | 1580 | /* printk("emufx.c: gpr=0x%x, tmp=0x%x\n",gpr, tmp); */ |
1573 | * value A_P16VIN to output A_FXBUS2 as in the first channel, | 1581 | /* For the EMU1010: How to get 32bit values from the DSP. High 16bits into L, low 16bits into R. */ |
1574 | * we use an auxiliary register, delaying the value by one | 1582 | /* A_P16VIN(0) is delayed by one sample, |
1575 | * sample | 1583 | * so all other A_P16VIN channels will need to also be delayed |
1576 | */ | 1584 | */ |
1577 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(2) ); | 1585 | /* Left ADC in. 1 of 2 */ |
1578 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x1), A_C_00000000, A_C_00000000); | 1586 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_P16VIN(0x0), A_FXBUS2(0) ); |
1579 | gpr_map[gpr++] = 0x00000000; | 1587 | /* Right ADC in 1 of 2 */ |
1580 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(4) ); | 1588 | gpr_map[gpr++] = 0x00000000; |
1581 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x2), A_C_00000000, A_C_00000000); | 1589 | /* Delaying by one sample: instead of copying the input |
1582 | gpr_map[gpr++] = 0x00000000; | 1590 | * value A_P16VIN to output A_FXBUS2 as in the first channel, |
1583 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(6) ); | 1591 | * we use an auxiliary register, delaying the value by one |
1584 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x3), A_C_00000000, A_C_00000000); | 1592 | * sample |
1585 | /* For 96kHz mode */ | 1593 | */ |
1586 | /* Left ADC in. 2 of 2 */ | 1594 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(2) ); |
1587 | gpr_map[gpr++] = 0x00000000; | 1595 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x1), A_C_00000000, A_C_00000000); |
1588 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0x8) ); | 1596 | gpr_map[gpr++] = 0x00000000; |
1589 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x4), A_C_00000000, A_C_00000000); | 1597 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(4) ); |
1590 | /* Right ADC in 2 of 2 */ | 1598 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x2), A_C_00000000, A_C_00000000); |
1591 | gpr_map[gpr++] = 0x00000000; | 1599 | gpr_map[gpr++] = 0x00000000; |
1592 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xa) ); | 1600 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(6) ); |
1593 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x5), A_C_00000000, A_C_00000000); | 1601 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x3), A_C_00000000, A_C_00000000); |
1594 | gpr_map[gpr++] = 0x00000000; | 1602 | /* For 96kHz mode */ |
1595 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xc) ); | 1603 | /* Left ADC in. 2 of 2 */ |
1596 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x6), A_C_00000000, A_C_00000000); | 1604 | gpr_map[gpr++] = 0x00000000; |
1597 | gpr_map[gpr++] = 0x00000000; | 1605 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0x8) ); |
1598 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xe) ); | 1606 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x4), A_C_00000000, A_C_00000000); |
1599 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x7), A_C_00000000, A_C_00000000); | 1607 | /* Right ADC in 2 of 2 */ |
1600 | /* Pavel Hofman - we still have voices, A_FXBUS2s, and | 1608 | gpr_map[gpr++] = 0x00000000; |
1601 | * A_P16VINs available - | 1609 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xa) ); |
1602 | * let's add 8 more capture channels - total of 16 | 1610 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x5), A_C_00000000, A_C_00000000); |
1603 | */ | 1611 | gpr_map[gpr++] = 0x00000000; |
1604 | gpr_map[gpr++] = 0x00000000; | 1612 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xc) ); |
1605 | snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, | 1613 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x6), A_C_00000000, A_C_00000000); |
1606 | bit_shifter16, | 1614 | gpr_map[gpr++] = 0x00000000; |
1607 | A_GPR(gpr - 1), | 1615 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xe) ); |
1608 | A_FXBUS2(0x10)); | 1616 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x7), A_C_00000000, A_C_00000000); |
1609 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x8), | 1617 | /* Pavel Hofman - we still have voices, A_FXBUS2s, and |
1610 | A_C_00000000, A_C_00000000); | 1618 | * A_P16VINs available - |
1611 | gpr_map[gpr++] = 0x00000000; | 1619 | * let's add 8 more capture channels - total of 16 |
1612 | snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, | 1620 | */ |
1613 | bit_shifter16, | 1621 | gpr_map[gpr++] = 0x00000000; |
1614 | A_GPR(gpr - 1), | 1622 | snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, |
1615 | A_FXBUS2(0x12)); | 1623 | bit_shifter16, |
1616 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x9), | 1624 | A_GPR(gpr - 1), |
1617 | A_C_00000000, A_C_00000000); | 1625 | A_FXBUS2(0x10)); |
1618 | gpr_map[gpr++] = 0x00000000; | 1626 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x8), |
1619 | snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, | 1627 | A_C_00000000, A_C_00000000); |
1620 | bit_shifter16, | 1628 | gpr_map[gpr++] = 0x00000000; |
1621 | A_GPR(gpr - 1), | 1629 | snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, |
1622 | A_FXBUS2(0x14)); | 1630 | bit_shifter16, |
1623 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xa), | 1631 | A_GPR(gpr - 1), |
1624 | A_C_00000000, A_C_00000000); | 1632 | A_FXBUS2(0x12)); |
1625 | gpr_map[gpr++] = 0x00000000; | 1633 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x9), |
1626 | snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, | 1634 | A_C_00000000, A_C_00000000); |
1627 | bit_shifter16, | 1635 | gpr_map[gpr++] = 0x00000000; |
1628 | A_GPR(gpr - 1), | 1636 | snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, |
1629 | A_FXBUS2(0x16)); | 1637 | bit_shifter16, |
1630 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xb), | 1638 | A_GPR(gpr - 1), |
1631 | A_C_00000000, A_C_00000000); | 1639 | A_FXBUS2(0x14)); |
1632 | gpr_map[gpr++] = 0x00000000; | 1640 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xa), |
1633 | snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, | 1641 | A_C_00000000, A_C_00000000); |
1634 | bit_shifter16, | 1642 | gpr_map[gpr++] = 0x00000000; |
1635 | A_GPR(gpr - 1), | 1643 | snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, |
1636 | A_FXBUS2(0x18)); | 1644 | bit_shifter16, |
1637 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xc), | 1645 | A_GPR(gpr - 1), |
1638 | A_C_00000000, A_C_00000000); | 1646 | A_FXBUS2(0x16)); |
1639 | gpr_map[gpr++] = 0x00000000; | 1647 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xb), |
1640 | snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, | 1648 | A_C_00000000, A_C_00000000); |
1641 | bit_shifter16, | 1649 | gpr_map[gpr++] = 0x00000000; |
1642 | A_GPR(gpr - 1), | 1650 | snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, |
1643 | A_FXBUS2(0x1a)); | 1651 | bit_shifter16, |
1644 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xd), | 1652 | A_GPR(gpr - 1), |
1645 | A_C_00000000, A_C_00000000); | 1653 | A_FXBUS2(0x18)); |
1646 | gpr_map[gpr++] = 0x00000000; | 1654 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xc), |
1647 | snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, | 1655 | A_C_00000000, A_C_00000000); |
1648 | bit_shifter16, | 1656 | gpr_map[gpr++] = 0x00000000; |
1649 | A_GPR(gpr - 1), | 1657 | snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, |
1650 | A_FXBUS2(0x1c)); | 1658 | bit_shifter16, |
1651 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xe), | 1659 | A_GPR(gpr - 1), |
1652 | A_C_00000000, A_C_00000000); | 1660 | A_FXBUS2(0x1a)); |
1653 | gpr_map[gpr++] = 0x00000000; | 1661 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xd), |
1654 | snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, | 1662 | A_C_00000000, A_C_00000000); |
1655 | bit_shifter16, | 1663 | gpr_map[gpr++] = 0x00000000; |
1656 | A_GPR(gpr - 1), | 1664 | snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, |
1657 | A_FXBUS2(0x1e)); | 1665 | bit_shifter16, |
1658 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xf), | 1666 | A_GPR(gpr - 1), |
1659 | A_C_00000000, A_C_00000000); | 1667 | A_FXBUS2(0x1c)); |
1668 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xe), | ||
1669 | A_C_00000000, A_C_00000000); | ||
1670 | gpr_map[gpr++] = 0x00000000; | ||
1671 | snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, | ||
1672 | bit_shifter16, | ||
1673 | A_GPR(gpr - 1), | ||
1674 | A_FXBUS2(0x1e)); | ||
1675 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xf), | ||
1676 | A_C_00000000, A_C_00000000); | ||
1677 | } | ||
1660 | 1678 | ||
1661 | #if 0 | 1679 | #if 0 |
1662 | for (z = 4; z < 8; z++) { | 1680 | for (z = 4; z < 8; z++) { |
@@ -2418,14 +2436,13 @@ static void copy_string(char *dst, char *src, char *null, int idx) | |||
2418 | strcpy(dst, src); | 2436 | strcpy(dst, src); |
2419 | } | 2437 | } |
2420 | 2438 | ||
2421 | static int snd_emu10k1_fx8010_info(struct snd_emu10k1 *emu, | 2439 | static void snd_emu10k1_fx8010_info(struct snd_emu10k1 *emu, |
2422 | struct snd_emu10k1_fx8010_info *info) | 2440 | struct snd_emu10k1_fx8010_info *info) |
2423 | { | 2441 | { |
2424 | char **fxbus, **extin, **extout; | 2442 | char **fxbus, **extin, **extout; |
2425 | unsigned short fxbus_mask, extin_mask, extout_mask; | 2443 | unsigned short fxbus_mask, extin_mask, extout_mask; |
2426 | int res; | 2444 | int res; |
2427 | 2445 | ||
2428 | memset(info, 0, sizeof(info)); | ||
2429 | info->internal_tram_size = emu->fx8010.itram_size; | 2446 | info->internal_tram_size = emu->fx8010.itram_size; |
2430 | info->external_tram_size = emu->fx8010.etram_pages.bytes / 2; | 2447 | info->external_tram_size = emu->fx8010.etram_pages.bytes / 2; |
2431 | fxbus = fxbuses; | 2448 | fxbus = fxbuses; |
@@ -2442,7 +2459,6 @@ static int snd_emu10k1_fx8010_info(struct snd_emu10k1 *emu, | |||
2442 | for (res = 16; res < 32; res++, extout++) | 2459 | for (res = 16; res < 32; res++, extout++) |
2443 | copy_string(info->extout_names[res], extout_mask & (1 << res) ? *extout : NULL, "Unused", res); | 2460 | copy_string(info->extout_names[res], extout_mask & (1 << res) ? *extout : NULL, "Unused", res); |
2444 | info->gpr_controls = emu->fx8010.gpr_count; | 2461 | info->gpr_controls = emu->fx8010.gpr_count; |
2445 | return 0; | ||
2446 | } | 2462 | } |
2447 | 2463 | ||
2448 | static int snd_emu10k1_fx8010_ioctl(struct snd_hwdep * hw, struct file *file, unsigned int cmd, unsigned long arg) | 2464 | static int snd_emu10k1_fx8010_ioctl(struct snd_hwdep * hw, struct file *file, unsigned int cmd, unsigned long arg) |
@@ -2463,10 +2479,7 @@ static int snd_emu10k1_fx8010_ioctl(struct snd_hwdep * hw, struct file *file, un | |||
2463 | info = kmalloc(sizeof(*info), GFP_KERNEL); | 2479 | info = kmalloc(sizeof(*info), GFP_KERNEL); |
2464 | if (!info) | 2480 | if (!info) |
2465 | return -ENOMEM; | 2481 | return -ENOMEM; |
2466 | if ((res = snd_emu10k1_fx8010_info(emu, info)) < 0) { | 2482 | snd_emu10k1_fx8010_info(emu, info); |
2467 | kfree(info); | ||
2468 | return res; | ||
2469 | } | ||
2470 | if (copy_to_user(argp, info, sizeof(*info))) { | 2483 | if (copy_to_user(argp, info, sizeof(*info))) { |
2471 | kfree(info); | 2484 | kfree(info); |
2472 | return -EFAULT; | 2485 | return -EFAULT; |
diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c index 7b2c1dcc5337..54a2034d8edd 100644 --- a/sound/pci/emu10k1/emumixer.c +++ b/sound/pci/emu10k1/emumixer.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz>, | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz>, |
3 | * Takashi Iwai <tiwai@suse.de> | 3 | * Takashi Iwai <tiwai@suse.de> |
4 | * Creative Labs, Inc. | 4 | * Creative Labs, Inc. |
5 | * Routines for control of EMU10K1 chips / mixer routines | 5 | * Routines for control of EMU10K1 chips / mixer routines |
@@ -400,15 +400,7 @@ static struct snd_kcontrol_new snd_emu1010_input_enum_ctls[] __devinitdata = { | |||
400 | 400 | ||
401 | 401 | ||
402 | 402 | ||
403 | 403 | #define snd_emu1010_adc_pads_info snd_ctl_boolean_mono_info | |
404 | static int snd_emu1010_adc_pads_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | ||
405 | { | ||
406 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
407 | uinfo->count = 1; | ||
408 | uinfo->value.integer.min = 0; | ||
409 | uinfo->value.integer.max = 1; | ||
410 | return 0; | ||
411 | } | ||
412 | 404 | ||
413 | static int snd_emu1010_adc_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 405 | static int snd_emu1010_adc_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
414 | { | 406 | { |
@@ -456,14 +448,7 @@ static struct snd_kcontrol_new snd_emu1010_adc_pads[] __devinitdata = { | |||
456 | EMU1010_ADC_PADS("ADC1 14dB PAD 0202 Capture Switch", EMU_HANA_0202_ADC_PAD1), | 448 | EMU1010_ADC_PADS("ADC1 14dB PAD 0202 Capture Switch", EMU_HANA_0202_ADC_PAD1), |
457 | }; | 449 | }; |
458 | 450 | ||
459 | static int snd_emu1010_dac_pads_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 451 | #define snd_emu1010_dac_pads_info snd_ctl_boolean_mono_info |
460 | { | ||
461 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
462 | uinfo->count = 1; | ||
463 | uinfo->value.integer.min = 0; | ||
464 | uinfo->value.integer.max = 1; | ||
465 | return 0; | ||
466 | } | ||
467 | 452 | ||
468 | static int snd_emu1010_dac_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 453 | static int snd_emu1010_dac_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
469 | { | 454 | { |
@@ -516,17 +501,19 @@ static struct snd_kcontrol_new snd_emu1010_dac_pads[] __devinitdata = { | |||
516 | static int snd_emu1010_internal_clock_info(struct snd_kcontrol *kcontrol, | 501 | static int snd_emu1010_internal_clock_info(struct snd_kcontrol *kcontrol, |
517 | struct snd_ctl_elem_info *uinfo) | 502 | struct snd_ctl_elem_info *uinfo) |
518 | { | 503 | { |
519 | static char *texts[2] = { | 504 | static char *texts[4] = { |
520 | "44100", "48000" | 505 | "44100", "48000", "SPDIF", "ADAT" |
521 | }; | 506 | }; |
522 | 507 | ||
523 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 508 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
524 | uinfo->count = 1; | 509 | uinfo->count = 1; |
525 | uinfo->value.enumerated.items = 2; | 510 | uinfo->value.enumerated.items = 4; |
526 | if (uinfo->value.enumerated.item > 1) | 511 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) |
527 | uinfo->value.enumerated.item = 1; | 512 | uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; |
528 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | 513 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); |
529 | return 0; | 514 | return 0; |
515 | |||
516 | |||
530 | } | 517 | } |
531 | 518 | ||
532 | static int snd_emu1010_internal_clock_get(struct snd_kcontrol *kcontrol, | 519 | static int snd_emu1010_internal_clock_get(struct snd_kcontrol *kcontrol, |
@@ -584,6 +571,44 @@ static int snd_emu1010_internal_clock_put(struct snd_kcontrol *kcontrol, | |||
584 | /* Unmute all */ | 571 | /* Unmute all */ |
585 | snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE ); | 572 | snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE ); |
586 | break; | 573 | break; |
574 | |||
575 | case 2: /* Take clock from S/PDIF IN */ | ||
576 | /* Mute all */ | ||
577 | snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE ); | ||
578 | /* Default fallback clock 48kHz */ | ||
579 | snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_48K ); | ||
580 | /* Word Clock source, sync to S/PDIF input */ | ||
581 | snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, | ||
582 | EMU_HANA_WCLOCK_HANA_SPDIF_IN | EMU_HANA_WCLOCK_1X ); | ||
583 | /* Set LEDs on Audio Dock */ | ||
584 | snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, | ||
585 | EMU_HANA_DOCK_LEDS_2_EXT | EMU_HANA_DOCK_LEDS_2_LOCK ); | ||
586 | /* FIXME: We should set EMU_HANA_DOCK_LEDS_2_LOCK only when clock signal is present and valid */ | ||
587 | /* Allow DLL to settle */ | ||
588 | msleep(10); | ||
589 | /* Unmute all */ | ||
590 | snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE ); | ||
591 | break; | ||
592 | |||
593 | case 3: | ||
594 | /* Take clock from ADAT IN */ | ||
595 | /* Mute all */ | ||
596 | snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE ); | ||
597 | /* Default fallback clock 48kHz */ | ||
598 | snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_48K ); | ||
599 | /* Word Clock source, sync to ADAT input */ | ||
600 | snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, | ||
601 | EMU_HANA_WCLOCK_HANA_ADAT_IN | EMU_HANA_WCLOCK_1X ); | ||
602 | /* Set LEDs on Audio Dock */ | ||
603 | snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, EMU_HANA_DOCK_LEDS_2_EXT | EMU_HANA_DOCK_LEDS_2_LOCK ); | ||
604 | /* FIXME: We should set EMU_HANA_DOCK_LEDS_2_LOCK only when clock signal is present and valid */ | ||
605 | /* Allow DLL to settle */ | ||
606 | msleep(10); | ||
607 | /* Unmute all */ | ||
608 | snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE ); | ||
609 | |||
610 | |||
611 | break; | ||
587 | } | 612 | } |
588 | } | 613 | } |
589 | return change; | 614 | return change; |
@@ -871,7 +896,7 @@ static struct snd_kcontrol_new snd_emu10k1_spdif_mask_control = | |||
871 | .access = SNDRV_CTL_ELEM_ACCESS_READ, | 896 | .access = SNDRV_CTL_ELEM_ACCESS_READ, |
872 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | 897 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
873 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK), | 898 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK), |
874 | .count = 4, | 899 | .count = 3, |
875 | .info = snd_emu10k1_spdif_info, | 900 | .info = snd_emu10k1_spdif_info, |
876 | .get = snd_emu10k1_spdif_get_mask | 901 | .get = snd_emu10k1_spdif_get_mask |
877 | }; | 902 | }; |
@@ -880,7 +905,7 @@ static struct snd_kcontrol_new snd_emu10k1_spdif_control = | |||
880 | { | 905 | { |
881 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | 906 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
882 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), | 907 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), |
883 | .count = 4, | 908 | .count = 3, |
884 | .info = snd_emu10k1_spdif_info, | 909 | .info = snd_emu10k1_spdif_info, |
885 | .get = snd_emu10k1_spdif_get, | 910 | .get = snd_emu10k1_spdif_get, |
886 | .put = snd_emu10k1_spdif_put | 911 | .put = snd_emu10k1_spdif_put |
@@ -1326,14 +1351,7 @@ static struct snd_kcontrol_new snd_emu10k1_efx_attn_control = | |||
1326 | .put = snd_emu10k1_efx_attn_put | 1351 | .put = snd_emu10k1_efx_attn_put |
1327 | }; | 1352 | }; |
1328 | 1353 | ||
1329 | static int snd_emu10k1_shared_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1354 | #define snd_emu10k1_shared_spdif_info snd_ctl_boolean_mono_info |
1330 | { | ||
1331 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1332 | uinfo->count = 1; | ||
1333 | uinfo->value.integer.min = 0; | ||
1334 | uinfo->value.integer.max = 1; | ||
1335 | return 0; | ||
1336 | } | ||
1337 | 1355 | ||
1338 | static int snd_emu10k1_shared_spdif_get(struct snd_kcontrol *kcontrol, | 1356 | static int snd_emu10k1_shared_spdif_get(struct snd_kcontrol *kcontrol, |
1339 | struct snd_ctl_elem_value *ucontrol) | 1357 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/pci/emu10k1/emumpu401.c b/sound/pci/emu10k1/emumpu401.c index 950c6bcd6b7d..04c7cf703531 100644 --- a/sound/pci/emu10k1/emumpu401.c +++ b/sound/pci/emu10k1/emumpu401.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Routines for control of EMU10K1 MPU-401 in UART mode | 3 | * Routines for control of EMU10K1 MPU-401 in UART mode |
4 | * | 4 | * |
5 | * | 5 | * |
diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c index eda5cb373ded..5ce5befc701b 100644 --- a/sound/pci/emu10k1/emupcm.c +++ b/sound/pci/emu10k1/emupcm.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Creative Labs, Inc. | 3 | * Creative Labs, Inc. |
4 | * Routines for control of EMU10K1 chips / PCM routines | 4 | * Routines for control of EMU10K1 chips / PCM routines |
5 | * Multichannel PCM support Copyright (c) Lee Revell <rlrevell@joe-job.com> | 5 | * Multichannel PCM support Copyright (c) Lee Revell <rlrevell@joe-job.com> |
diff --git a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c index 2c1585991bc8..c3fb10e81c9e 100644 --- a/sound/pci/emu10k1/emuproc.c +++ b/sound/pci/emu10k1/emuproc.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Creative Labs, Inc. | 3 | * Creative Labs, Inc. |
4 | * Routines for control of EMU10K1 chips / proc interface routines | 4 | * Routines for control of EMU10K1 chips / proc interface routines |
5 | * | 5 | * |
@@ -240,8 +240,42 @@ static void snd_emu10k1_proc_spdif_read(struct snd_info_entry *entry, | |||
240 | struct snd_info_buffer *buffer) | 240 | struct snd_info_buffer *buffer) |
241 | { | 241 | { |
242 | struct snd_emu10k1 *emu = entry->private_data; | 242 | struct snd_emu10k1 *emu = entry->private_data; |
243 | snd_emu10k1_proc_spdif_status(emu, buffer, "CD-ROM S/PDIF In", CDCS, CDSRCS); | 243 | u32 value; |
244 | snd_emu10k1_proc_spdif_status(emu, buffer, "Optical or Coax S/PDIF In", GPSCS, GPSRCS); | 244 | u32 value2; |
245 | unsigned long flags; | ||
246 | u32 rate; | ||
247 | |||
248 | if (emu->card_capabilities->emu1010) { | ||
249 | spin_lock_irqsave(&emu->emu_lock, flags); | ||
250 | snd_emu1010_fpga_read(emu, 0x38, &value); | ||
251 | spin_unlock_irqrestore(&emu->emu_lock, flags); | ||
252 | if ((value & 0x1) == 0) { | ||
253 | spin_lock_irqsave(&emu->emu_lock, flags); | ||
254 | snd_emu1010_fpga_read(emu, 0x2a, &value); | ||
255 | snd_emu1010_fpga_read(emu, 0x2b, &value2); | ||
256 | spin_unlock_irqrestore(&emu->emu_lock, flags); | ||
257 | rate = 0x1770000 / (((value << 5) | value2)+1); | ||
258 | snd_iprintf(buffer, "ADAT Locked : %u\n", rate); | ||
259 | } else { | ||
260 | snd_iprintf(buffer, "ADAT Unlocked\n"); | ||
261 | } | ||
262 | spin_lock_irqsave(&emu->emu_lock, flags); | ||
263 | snd_emu1010_fpga_read(emu, 0x20, &value); | ||
264 | spin_unlock_irqrestore(&emu->emu_lock, flags); | ||
265 | if ((value & 0x4) == 0) { | ||
266 | spin_lock_irqsave(&emu->emu_lock, flags); | ||
267 | snd_emu1010_fpga_read(emu, 0x28, &value); | ||
268 | snd_emu1010_fpga_read(emu, 0x29, &value2); | ||
269 | spin_unlock_irqrestore(&emu->emu_lock, flags); | ||
270 | rate = 0x1770000 / (((value << 5) | value2)+1); | ||
271 | snd_iprintf(buffer, "SPDIF Locked : %d\n", rate); | ||
272 | } else { | ||
273 | snd_iprintf(buffer, "SPDIF Unlocked\n"); | ||
274 | } | ||
275 | } else { | ||
276 | snd_emu10k1_proc_spdif_status(emu, buffer, "CD-ROM S/PDIF In", CDCS, CDSRCS); | ||
277 | snd_emu10k1_proc_spdif_status(emu, buffer, "Optical or Coax S/PDIF In", GPSCS, GPSRCS); | ||
278 | } | ||
245 | #if 0 | 279 | #if 0 |
246 | val = snd_emu10k1_ptr_read(emu, ZVSRCS, 0); | 280 | val = snd_emu10k1_ptr_read(emu, ZVSRCS, 0); |
247 | snd_iprintf(buffer, "\nZoomed Video\n"); | 281 | snd_iprintf(buffer, "\nZoomed Video\n"); |
@@ -379,20 +413,16 @@ static void snd_emu_proc_emu1010_reg_read(struct snd_info_entry *entry, | |||
379 | struct snd_info_buffer *buffer) | 413 | struct snd_info_buffer *buffer) |
380 | { | 414 | { |
381 | struct snd_emu10k1 *emu = entry->private_data; | 415 | struct snd_emu10k1 *emu = entry->private_data; |
382 | unsigned long value; | 416 | int value; |
383 | unsigned long flags; | 417 | unsigned long flags; |
384 | unsigned long regs; | ||
385 | int i; | 418 | int i; |
386 | snd_iprintf(buffer, "EMU1010 Registers:\n\n"); | 419 | snd_iprintf(buffer, "EMU1010 Registers:\n\n"); |
387 | 420 | ||
388 | for(i = 0; i < 0x30; i+=1) { | 421 | for(i = 0; i < 0x40; i+=1) { |
389 | spin_lock_irqsave(&emu->emu_lock, flags); | 422 | spin_lock_irqsave(&emu->emu_lock, flags); |
390 | regs=i+0x40; /* 0x40 upwards are registers. */ | 423 | snd_emu1010_fpga_read(emu, i, &value); |
391 | outl(regs, emu->port + A_IOCFG); | ||
392 | outl(regs | 0x80, emu->port + A_IOCFG); /* High bit clocks the value into the fpga. */ | ||
393 | value = inl(emu->port + A_IOCFG); | ||
394 | spin_unlock_irqrestore(&emu->emu_lock, flags); | 424 | spin_unlock_irqrestore(&emu->emu_lock, flags); |
395 | snd_iprintf(buffer, "%02X: %08lX, %02lX\n", i, value, (value >> 8) & 0x7f); | 425 | snd_iprintf(buffer, "%02X: %08X, %02X\n", i, value, (value >> 8) & 0x7f); |
396 | } | 426 | } |
397 | } | 427 | } |
398 | 428 | ||
@@ -555,9 +585,9 @@ int __devinit snd_emu10k1_proc_init(struct snd_emu10k1 * emu) | |||
555 | { | 585 | { |
556 | struct snd_info_entry *entry; | 586 | struct snd_info_entry *entry; |
557 | #ifdef CONFIG_SND_DEBUG | 587 | #ifdef CONFIG_SND_DEBUG |
558 | if ((emu->card_capabilities->emu1010) && | 588 | if (emu->card_capabilities->emu1010) { |
559 | snd_card_proc_new(emu->card, "emu1010_regs", &entry)) { | 589 | if (! snd_card_proc_new(emu->card, "emu1010_regs", &entry)) |
560 | snd_info_set_text_ops(entry, emu, snd_emu_proc_emu1010_reg_read); | 590 | snd_info_set_text_ops(entry, emu, snd_emu_proc_emu1010_reg_read); |
561 | } | 591 | } |
562 | if (! snd_card_proc_new(emu->card, "io_regs", &entry)) { | 592 | if (! snd_card_proc_new(emu->card, "io_regs", &entry)) { |
563 | snd_info_set_text_ops(entry, emu, snd_emu_proc_io_reg_read); | 593 | snd_info_set_text_ops(entry, emu, snd_emu_proc_io_reg_read); |
diff --git a/sound/pci/emu10k1/io.c b/sound/pci/emu10k1/io.c index 116e1c8d9361..6702c15fefa3 100644 --- a/sound/pci/emu10k1/io.c +++ b/sound/pci/emu10k1/io.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Creative Labs, Inc. | 3 | * Creative Labs, Inc. |
4 | * Routines for control of EMU10K1 chips | 4 | * Routines for control of EMU10K1 chips |
5 | * | 5 | * |
@@ -226,9 +226,9 @@ int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu, | |||
226 | return 0; | 226 | return 0; |
227 | } | 227 | } |
228 | 228 | ||
229 | int snd_emu1010_fpga_write(struct snd_emu10k1 * emu, int reg, int value) | 229 | int snd_emu1010_fpga_write(struct snd_emu10k1 * emu, u32 reg, u32 value) |
230 | { | 230 | { |
231 | if (reg < 0 || reg > 0x3f) | 231 | if (reg > 0x3f) |
232 | return 1; | 232 | return 1; |
233 | reg += 0x40; /* 0x40 upwards are registers. */ | 233 | reg += 0x40; /* 0x40 upwards are registers. */ |
234 | if (value < 0 || value > 0x3f) /* 0 to 0x3f are values */ | 234 | if (value < 0 || value > 0x3f) /* 0 to 0x3f are values */ |
@@ -244,9 +244,9 @@ int snd_emu1010_fpga_write(struct snd_emu10k1 * emu, int reg, int value) | |||
244 | return 0; | 244 | return 0; |
245 | } | 245 | } |
246 | 246 | ||
247 | int snd_emu1010_fpga_read(struct snd_emu10k1 * emu, int reg, int *value) | 247 | int snd_emu1010_fpga_read(struct snd_emu10k1 * emu, u32 reg, u32 *value) |
248 | { | 248 | { |
249 | if (reg < 0 || reg > 0x3f) | 249 | if (reg > 0x3f) |
250 | return 1; | 250 | return 1; |
251 | reg += 0x40; /* 0x40 upwards are registers. */ | 251 | reg += 0x40; /* 0x40 upwards are registers. */ |
252 | outl(reg, emu->port + A_IOCFG); | 252 | outl(reg, emu->port + A_IOCFG); |
@@ -261,7 +261,7 @@ int snd_emu1010_fpga_read(struct snd_emu10k1 * emu, int reg, int *value) | |||
261 | /* Each Destination has one and only one Source, | 261 | /* Each Destination has one and only one Source, |
262 | * but one Source can feed any number of Destinations simultaneously. | 262 | * but one Source can feed any number of Destinations simultaneously. |
263 | */ | 263 | */ |
264 | int snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 * emu, int dst, int src) | 264 | int snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 * emu, u32 dst, u32 src) |
265 | { | 265 | { |
266 | snd_emu1010_fpga_write(emu, 0x00, ((dst >> 8) & 0x3f) ); | 266 | snd_emu1010_fpga_write(emu, 0x00, ((dst >> 8) & 0x3f) ); |
267 | snd_emu1010_fpga_write(emu, 0x01, (dst & 0x3f) ); | 267 | snd_emu1010_fpga_write(emu, 0x01, (dst & 0x3f) ); |
diff --git a/sound/pci/emu10k1/irq.c b/sound/pci/emu10k1/irq.c index 4f18f7e8bcfb..3c114b45e0b2 100644 --- a/sound/pci/emu10k1/irq.c +++ b/sound/pci/emu10k1/irq.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Creative Labs, Inc. | 3 | * Creative Labs, Inc. |
4 | * Routines for IRQ control of EMU10K1 chips | 4 | * Routines for IRQ control of EMU10K1 chips |
5 | * | 5 | * |
diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c index 4fcaefe5a3c5..48097c6bb15c 100644 --- a/sound/pci/emu10k1/memory.c +++ b/sound/pci/emu10k1/memory.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Copyright (c) by Takashi Iwai <tiwai@suse.de> | 3 | * Copyright (c) by Takashi Iwai <tiwai@suse.de> |
4 | * | 4 | * |
5 | * EMU10K1 memory page allocation (PTB area) | 5 | * EMU10K1 memory page allocation (PTB area) |
diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c index 7ee19c63c2c8..d619a3842cdd 100644 --- a/sound/pci/emu10k1/p16v.c +++ b/sound/pci/emu10k1/p16v.c | |||
@@ -124,11 +124,12 @@ | |||
124 | 124 | ||
125 | /* hardware definition */ | 125 | /* hardware definition */ |
126 | static struct snd_pcm_hardware snd_p16v_playback_hw = { | 126 | static struct snd_pcm_hardware snd_p16v_playback_hw = { |
127 | .info = (SNDRV_PCM_INFO_MMAP | | 127 | .info = SNDRV_PCM_INFO_MMAP | |
128 | SNDRV_PCM_INFO_INTERLEAVED | | 128 | SNDRV_PCM_INFO_INTERLEAVED | |
129 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 129 | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
130 | SNDRV_PCM_INFO_RESUME | | 130 | SNDRV_PCM_INFO_RESUME | |
131 | SNDRV_PCM_INFO_MMAP_VALID), | 131 | SNDRV_PCM_INFO_MMAP_VALID | |
132 | SNDRV_PCM_INFO_SYNC_START, | ||
132 | .formats = SNDRV_PCM_FMTBIT_S32_LE, /* Only supports 24-bit samples padded to 32 bits. */ | 133 | .formats = SNDRV_PCM_FMTBIT_S32_LE, /* Only supports 24-bit samples padded to 32 bits. */ |
133 | .rates = SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100, | 134 | .rates = SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100, |
134 | .rate_min = 44100, | 135 | .rate_min = 44100, |
@@ -207,6 +208,11 @@ static int snd_p16v_pcm_open_playback_channel(struct snd_pcm_substream *substrea | |||
207 | if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) | 208 | if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) |
208 | return err; | 209 | return err; |
209 | 210 | ||
211 | runtime->sync.id32[0] = substream->pcm->card->number; | ||
212 | runtime->sync.id32[1] = 'P'; | ||
213 | runtime->sync.id32[2] = 16; | ||
214 | runtime->sync.id32[3] = 'V'; | ||
215 | |||
210 | return 0; | 216 | return 0; |
211 | } | 217 | } |
212 | /* open_capture callback */ | 218 | /* open_capture callback */ |
@@ -448,6 +454,9 @@ static int snd_p16v_pcm_trigger_playback(struct snd_pcm_substream *substream, | |||
448 | break; | 454 | break; |
449 | } | 455 | } |
450 | snd_pcm_group_for_each_entry(s, substream) { | 456 | snd_pcm_group_for_each_entry(s, substream) { |
457 | if (snd_pcm_substream_chip(s) != emu || | ||
458 | s->stream != SNDRV_PCM_STREAM_PLAYBACK) | ||
459 | continue; | ||
451 | runtime = s->runtime; | 460 | runtime = s->runtime; |
452 | epcm = runtime->private_data; | 461 | epcm = runtime->private_data; |
453 | channel = substream->pcm->device-emu->p16v_device_offset; | 462 | channel = substream->pcm->device-emu->p16v_device_offset; |
diff --git a/sound/pci/emu10k1/voice.c b/sound/pci/emu10k1/voice.c index 1db50fe61475..04fa8492abb0 100644 --- a/sound/pci/emu10k1/voice.c +++ b/sound/pci/emu10k1/voice.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Creative Labs, Inc. | 3 | * Creative Labs, Inc. |
4 | * Lee Revell <rlrevell@joe-job.com> | 4 | * Lee Revell <rlrevell@joe-job.com> |
5 | * Routines for control of EMU10K1 chips - voice manager | 5 | * Routines for control of EMU10K1 chips - voice manager |
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index 21cb4268a59b..b958f869cb13 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for Ensoniq ES1370/ES1371 AudioPCI soundcard | 2 | * Driver for Ensoniq ES1370/ES1371 AudioPCI soundcard |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz>, | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz>, |
4 | * Thomas Sailer <sailer@ife.ee.ethz.ch> | 4 | * Thomas Sailer <sailer@ife.ee.ethz.ch> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -61,7 +61,7 @@ | |||
61 | #endif | 61 | #endif |
62 | 62 | ||
63 | 63 | ||
64 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Thomas Sailer <sailer@ife.ee.ethz.ch>"); | 64 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Thomas Sailer <sailer@ife.ee.ethz.ch>"); |
65 | MODULE_LICENSE("GPL"); | 65 | MODULE_LICENSE("GPL"); |
66 | #ifdef CHIP1370 | 66 | #ifdef CHIP1370 |
67 | MODULE_DESCRIPTION("Ensoniq AudioPCI ES1370"); | 67 | MODULE_DESCRIPTION("Ensoniq AudioPCI ES1370"); |
@@ -1419,15 +1419,7 @@ static int snd_ens1373_spdif_stream_put(struct snd_kcontrol *kcontrol, | |||
1419 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_es1371_spdif_info, \ | 1419 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_es1371_spdif_info, \ |
1420 | .get = snd_es1371_spdif_get, .put = snd_es1371_spdif_put } | 1420 | .get = snd_es1371_spdif_get, .put = snd_es1371_spdif_put } |
1421 | 1421 | ||
1422 | static int snd_es1371_spdif_info(struct snd_kcontrol *kcontrol, | 1422 | #define snd_es1371_spdif_info snd_ctl_boolean_mono_info |
1423 | struct snd_ctl_elem_info *uinfo) | ||
1424 | { | ||
1425 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1426 | uinfo->count = 1; | ||
1427 | uinfo->value.integer.min = 0; | ||
1428 | uinfo->value.integer.max = 1; | ||
1429 | return 0; | ||
1430 | } | ||
1431 | 1423 | ||
1432 | static int snd_es1371_spdif_get(struct snd_kcontrol *kcontrol, | 1424 | static int snd_es1371_spdif_get(struct snd_kcontrol *kcontrol, |
1433 | struct snd_ctl_elem_value *ucontrol) | 1425 | struct snd_ctl_elem_value *ucontrol) |
@@ -1489,15 +1481,7 @@ static struct snd_kcontrol_new snd_es1371_mixer_spdif[] __devinitdata = { | |||
1489 | }; | 1481 | }; |
1490 | 1482 | ||
1491 | 1483 | ||
1492 | static int snd_es1373_rear_info(struct snd_kcontrol *kcontrol, | 1484 | #define snd_es1373_rear_info snd_ctl_boolean_mono_info |
1493 | struct snd_ctl_elem_info *uinfo) | ||
1494 | { | ||
1495 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1496 | uinfo->count = 1; | ||
1497 | uinfo->value.integer.min = 0; | ||
1498 | uinfo->value.integer.max = 1; | ||
1499 | return 0; | ||
1500 | } | ||
1501 | 1485 | ||
1502 | static int snd_es1373_rear_get(struct snd_kcontrol *kcontrol, | 1486 | static int snd_es1373_rear_get(struct snd_kcontrol *kcontrol, |
1503 | struct snd_ctl_elem_value *ucontrol) | 1487 | struct snd_ctl_elem_value *ucontrol) |
@@ -1542,15 +1526,7 @@ static struct snd_kcontrol_new snd_ens1373_rear __devinitdata = | |||
1542 | .put = snd_es1373_rear_put, | 1526 | .put = snd_es1373_rear_put, |
1543 | }; | 1527 | }; |
1544 | 1528 | ||
1545 | static int snd_es1373_line_info(struct snd_kcontrol *kcontrol, | 1529 | #define snd_es1373_line_info snd_ctl_boolean_mono_info |
1546 | struct snd_ctl_elem_info *uinfo) | ||
1547 | { | ||
1548 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1549 | uinfo->count = 1; | ||
1550 | uinfo->value.integer.min = 0; | ||
1551 | uinfo->value.integer.max = 1; | ||
1552 | return 0; | ||
1553 | } | ||
1554 | 1530 | ||
1555 | static int snd_es1373_line_get(struct snd_kcontrol *kcontrol, | 1531 | static int snd_es1373_line_get(struct snd_kcontrol *kcontrol, |
1556 | struct snd_ctl_elem_value *ucontrol) | 1532 | struct snd_ctl_elem_value *ucontrol) |
@@ -1707,15 +1683,7 @@ static int __devinit snd_ensoniq_1371_mixer(struct ensoniq *ensoniq, | |||
1707 | .get = snd_ensoniq_control_get, .put = snd_ensoniq_control_put, \ | 1683 | .get = snd_ensoniq_control_get, .put = snd_ensoniq_control_put, \ |
1708 | .private_value = mask } | 1684 | .private_value = mask } |
1709 | 1685 | ||
1710 | static int snd_ensoniq_control_info(struct snd_kcontrol *kcontrol, | 1686 | #define snd_ensoniq_control_info snd_ctl_boolean_mono_info |
1711 | struct snd_ctl_elem_info *uinfo) | ||
1712 | { | ||
1713 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1714 | uinfo->count = 1; | ||
1715 | uinfo->value.integer.min = 0; | ||
1716 | uinfo->value.integer.max = 1; | ||
1717 | return 0; | ||
1718 | } | ||
1719 | 1687 | ||
1720 | static int snd_ensoniq_control_get(struct snd_kcontrol *kcontrol, | 1688 | static int snd_ensoniq_control_get(struct snd_kcontrol *kcontrol, |
1721 | struct snd_ctl_elem_value *ucontrol) | 1689 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index fec29a108945..fb25abe68a02 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for ESS Solo-1 (ES1938, ES1946, ES1969) soundcard | 2 | * Driver for ESS Solo-1 (ES1938, ES1946, ES1969) soundcard |
3 | * Copyright (c) by Jaromir Koutek <miri@punknet.cz>, | 3 | * Copyright (c) by Jaromir Koutek <miri@punknet.cz>, |
4 | * Jaroslav Kysela <perex@suse.cz>, | 4 | * Jaroslav Kysela <perex@perex.cz>, |
5 | * Thomas Sailer <sailer@ife.ee.ethz.ch>, | 5 | * Thomas Sailer <sailer@ife.ee.ethz.ch>, |
6 | * Abramo Bagnara <abramo@alsa-project.org>, | 6 | * Abramo Bagnara <abramo@alsa-project.org>, |
7 | * Markus Gruber <gruber@eikon.tum.de> | 7 | * Markus Gruber <gruber@eikon.tum.de> |
@@ -1066,15 +1066,7 @@ static int snd_es1938_put_mux(struct snd_kcontrol *kcontrol, | |||
1066 | return snd_es1938_mixer_bits(chip, 0x1c, 0x07, val) != val; | 1066 | return snd_es1938_mixer_bits(chip, 0x1c, 0x07, val) != val; |
1067 | } | 1067 | } |
1068 | 1068 | ||
1069 | static int snd_es1938_info_spatializer_enable(struct snd_kcontrol *kcontrol, | 1069 | #define snd_es1938_info_spatializer_enable snd_ctl_boolean_mono_info |
1070 | struct snd_ctl_elem_info *uinfo) | ||
1071 | { | ||
1072 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1073 | uinfo->count = 1; | ||
1074 | uinfo->value.integer.min = 0; | ||
1075 | uinfo->value.integer.max = 1; | ||
1076 | return 0; | ||
1077 | } | ||
1078 | 1070 | ||
1079 | static int snd_es1938_get_spatializer_enable(struct snd_kcontrol *kcontrol, | 1071 | static int snd_es1938_get_spatializer_enable(struct snd_kcontrol *kcontrol, |
1080 | struct snd_ctl_elem_value *ucontrol) | 1072 | struct snd_ctl_elem_value *ucontrol) |
@@ -1120,15 +1112,7 @@ static int snd_es1938_get_hw_volume(struct snd_kcontrol *kcontrol, | |||
1120 | return 0; | 1112 | return 0; |
1121 | } | 1113 | } |
1122 | 1114 | ||
1123 | static int snd_es1938_info_hw_switch(struct snd_kcontrol *kcontrol, | 1115 | #define snd_es1938_info_hw_switch snd_ctl_boolean_stereo_info |
1124 | struct snd_ctl_elem_info *uinfo) | ||
1125 | { | ||
1126 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1127 | uinfo->count = 2; | ||
1128 | uinfo->value.integer.min = 0; | ||
1129 | uinfo->value.integer.max = 1; | ||
1130 | return 0; | ||
1131 | } | ||
1132 | 1116 | ||
1133 | static int snd_es1938_get_hw_switch(struct snd_kcontrol *kcontrol, | 1117 | static int snd_es1938_get_hw_switch(struct snd_kcontrol *kcontrol, |
1134 | struct snd_ctl_elem_value *ucontrol) | 1118 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index 2faf009076bb..d69b11d1f993 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c | |||
@@ -843,10 +843,9 @@ static void snd_es1968_bob_dec(struct es1968 *chip) | |||
843 | snd_es1968_bob_stop(chip); | 843 | snd_es1968_bob_stop(chip); |
844 | else if (chip->bob_freq > ESM_BOB_FREQ) { | 844 | else if (chip->bob_freq > ESM_BOB_FREQ) { |
845 | /* check reduction of timer frequency */ | 845 | /* check reduction of timer frequency */ |
846 | struct list_head *p; | ||
847 | int max_freq = ESM_BOB_FREQ; | 846 | int max_freq = ESM_BOB_FREQ; |
848 | list_for_each(p, &chip->substream_list) { | 847 | struct esschan *es; |
849 | struct esschan *es = list_entry(p, struct esschan, list); | 848 | list_for_each_entry(es, &chip->substream_list, list) { |
850 | if (max_freq < es->bob_freq) | 849 | if (max_freq < es->bob_freq) |
851 | max_freq = es->bob_freq; | 850 | max_freq = es->bob_freq; |
852 | } | 851 | } |
@@ -1316,12 +1315,11 @@ static struct snd_pcm_hardware snd_es1968_capture = { | |||
1316 | 1315 | ||
1317 | static int calc_available_memory_size(struct es1968 *chip) | 1316 | static int calc_available_memory_size(struct es1968 *chip) |
1318 | { | 1317 | { |
1319 | struct list_head *p; | ||
1320 | int max_size = 0; | 1318 | int max_size = 0; |
1321 | 1319 | struct esm_memory *buf; | |
1320 | |||
1322 | mutex_lock(&chip->memory_mutex); | 1321 | mutex_lock(&chip->memory_mutex); |
1323 | list_for_each(p, &chip->buf_list) { | 1322 | list_for_each_entry(buf, &chip->buf_list, list) { |
1324 | struct esm_memory *buf = list_entry(p, struct esm_memory, list); | ||
1325 | if (buf->empty && buf->buf.bytes > max_size) | 1323 | if (buf->empty && buf->buf.bytes > max_size) |
1326 | max_size = buf->buf.bytes; | 1324 | max_size = buf->buf.bytes; |
1327 | } | 1325 | } |
@@ -1335,12 +1333,10 @@ static int calc_available_memory_size(struct es1968 *chip) | |||
1335 | static struct esm_memory *snd_es1968_new_memory(struct es1968 *chip, int size) | 1333 | static struct esm_memory *snd_es1968_new_memory(struct es1968 *chip, int size) |
1336 | { | 1334 | { |
1337 | struct esm_memory *buf; | 1335 | struct esm_memory *buf; |
1338 | struct list_head *p; | 1336 | |
1339 | |||
1340 | size = ALIGN(size, ESM_MEM_ALIGN); | 1337 | size = ALIGN(size, ESM_MEM_ALIGN); |
1341 | mutex_lock(&chip->memory_mutex); | 1338 | mutex_lock(&chip->memory_mutex); |
1342 | list_for_each(p, &chip->buf_list) { | 1339 | list_for_each_entry(buf, &chip->buf_list, list) { |
1343 | buf = list_entry(p, struct esm_memory, list); | ||
1344 | if (buf->empty && buf->buf.bytes >= size) | 1340 | if (buf->empty && buf->buf.bytes >= size) |
1345 | goto __found; | 1341 | goto __found; |
1346 | } | 1342 | } |
@@ -1938,10 +1934,9 @@ static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id) | |||
1938 | } | 1934 | } |
1939 | 1935 | ||
1940 | if (event & ESM_SOUND_IRQ) { | 1936 | if (event & ESM_SOUND_IRQ) { |
1941 | struct list_head *p; | 1937 | struct esschan *es; |
1942 | spin_lock(&chip->substream_lock); | 1938 | spin_lock(&chip->substream_lock); |
1943 | list_for_each(p, &chip->substream_list) { | 1939 | list_for_each_entry(es, &chip->substream_list, list) { |
1944 | struct esschan *es = list_entry(p, struct esschan, list); | ||
1945 | if (es->running) | 1940 | if (es->running) |
1946 | snd_es1968_update_pcm(chip, es); | 1941 | snd_es1968_update_pcm(chip, es); |
1947 | } | 1942 | } |
@@ -2345,7 +2340,7 @@ static int es1968_resume(struct pci_dev *pci) | |||
2345 | { | 2340 | { |
2346 | struct snd_card *card = pci_get_drvdata(pci); | 2341 | struct snd_card *card = pci_get_drvdata(pci); |
2347 | struct es1968 *chip = card->private_data; | 2342 | struct es1968 *chip = card->private_data; |
2348 | struct list_head *p; | 2343 | struct esschan *es; |
2349 | 2344 | ||
2350 | if (! chip->do_pm) | 2345 | if (! chip->do_pm) |
2351 | return 0; | 2346 | return 0; |
@@ -2374,8 +2369,7 @@ static int es1968_resume(struct pci_dev *pci) | |||
2374 | /* restore ac97 state */ | 2369 | /* restore ac97 state */ |
2375 | snd_ac97_resume(chip->ac97); | 2370 | snd_ac97_resume(chip->ac97); |
2376 | 2371 | ||
2377 | list_for_each(p, &chip->substream_list) { | 2372 | list_for_each_entry(es, &chip->substream_list, list) { |
2378 | struct esschan *es = list_entry(p, struct esschan, list); | ||
2379 | switch (es->mode) { | 2373 | switch (es->mode) { |
2380 | case ESM_MODE_PLAY: | 2374 | case ESM_MODE_PLAY: |
2381 | snd_es1968_playback_setup(chip, es, es->substream->runtime); | 2375 | snd_es1968_playback_setup(chip, es, es->substream->runtime); |
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index 11015178e207..9939109f05a2 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * The driver for the ForteMedia FM801 based soundcards | 2 | * The driver for the ForteMedia FM801 based soundcards |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * Support FM only card by Andy Shevchenko <andy@smile.org.ua> | 5 | * Support FM only card by Andy Shevchenko <andy@smile.org.ua> |
6 | * | 6 | * |
@@ -42,7 +42,7 @@ | |||
42 | #define TEA575X_RADIO 1 | 42 | #define TEA575X_RADIO 1 |
43 | #endif | 43 | #endif |
44 | 44 | ||
45 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 45 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
46 | MODULE_DESCRIPTION("ForteMedia FM801"); | 46 | MODULE_DESCRIPTION("ForteMedia FM801"); |
47 | MODULE_LICENSE("GPL"); | 47 | MODULE_LICENSE("GPL"); |
48 | MODULE_SUPPORTED_DEVICE("{{ForteMedia,FM801}," | 48 | MODULE_SUPPORTED_DEVICE("{{ForteMedia,FM801}," |
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile index b2484bbdcc1d..ab0c726d648e 100644 --- a/sound/pci/hda/Makefile +++ b/sound/pci/hda/Makefile | |||
@@ -1,19 +1,18 @@ | |||
1 | snd-hda-intel-objs := hda_intel.o | 1 | snd-hda-intel-y := hda_intel.o |
2 | # since snd-hda-intel is the only driver using hda-codec, | 2 | # since snd-hda-intel is the only driver using hda-codec, |
3 | # merge it into a single module although it was originally | 3 | # merge it into a single module although it was originally |
4 | # designed to be individual modules | 4 | # designed to be individual modules |
5 | snd-hda-intel-objs += hda_codec.o \ | 5 | snd-hda-intel-y += hda_codec.o |
6 | hda_generic.o \ | 6 | snd-hda-intel-$(CONFIG_PROC_FS) += hda_proc.o |
7 | patch_realtek.o \ | 7 | snd-hda-intel-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o |
8 | patch_cmedia.o \ | 8 | snd-hda-intel-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o |
9 | patch_analog.o \ | 9 | snd-hda-intel-$(CONFIG_SND_HDA_CODEC_REALTEK) += patch_realtek.o |
10 | patch_sigmatel.o \ | 10 | snd-hda-intel-$(CONFIG_SND_HDA_CODEC_CMEDIA) += patch_cmedia.o |
11 | patch_si3054.o \ | 11 | snd-hda-intel-$(CONFIG_SND_HDA_CODEC_ANALOG) += patch_analog.o |
12 | patch_atihdmi.o \ | 12 | snd-hda-intel-$(CONFIG_SND_HDA_CODEC_SIGMATEL) += patch_sigmatel.o |
13 | patch_conexant.o \ | 13 | snd-hda-intel-$(CONFIG_SND_HDA_CODEC_SI3054) += patch_si3054.o |
14 | patch_via.o | 14 | snd-hda-intel-$(CONFIG_SND_HDA_CODEC_ATIHDMI) += patch_atihdmi.o |
15 | ifdef CONFIG_PROC_FS | 15 | snd-hda-intel-$(CONFIG_SND_HDA_CODEC_CONEXANT) += patch_conexant.o |
16 | snd-hda-intel-objs += hda_proc.o | 16 | snd-hda-intel-$(CONFIG_SND_HDA_CODEC_VIA) += patch_via.o |
17 | endif | ||
18 | 17 | ||
19 | obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-intel.o | 18 | obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-intel.o |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index f87f8f088956..187533e477c6 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -31,7 +31,15 @@ | |||
31 | #include <sound/tlv.h> | 31 | #include <sound/tlv.h> |
32 | #include <sound/initval.h> | 32 | #include <sound/initval.h> |
33 | #include "hda_local.h" | 33 | #include "hda_local.h" |
34 | 34 | #include <sound/hda_hwdep.h> | |
35 | |||
36 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
37 | /* define this option here to hide as static */ | ||
38 | static int power_save = CONFIG_SND_HDA_POWER_SAVE_DEFAULT; | ||
39 | module_param(power_save, int, 0644); | ||
40 | MODULE_PARM_DESC(power_save, "Automatic power-saving timeout " | ||
41 | "(in second, 0 = disable)."); | ||
42 | #endif | ||
35 | 43 | ||
36 | /* | 44 | /* |
37 | * vendor / preset table | 45 | * vendor / preset table |
@@ -59,6 +67,13 @@ static struct hda_vendor_id hda_vendor_ids[] = { | |||
59 | #include "hda_patch.h" | 67 | #include "hda_patch.h" |
60 | 68 | ||
61 | 69 | ||
70 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
71 | static void hda_power_work(struct work_struct *work); | ||
72 | static void hda_keep_power_on(struct hda_codec *codec); | ||
73 | #else | ||
74 | static inline void hda_keep_power_on(struct hda_codec *codec) {} | ||
75 | #endif | ||
76 | |||
62 | /** | 77 | /** |
63 | * snd_hda_codec_read - send a command and get the response | 78 | * snd_hda_codec_read - send a command and get the response |
64 | * @codec: the HDA codec | 79 | * @codec: the HDA codec |
@@ -76,12 +91,14 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, | |||
76 | unsigned int verb, unsigned int parm) | 91 | unsigned int verb, unsigned int parm) |
77 | { | 92 | { |
78 | unsigned int res; | 93 | unsigned int res; |
94 | snd_hda_power_up(codec); | ||
79 | mutex_lock(&codec->bus->cmd_mutex); | 95 | mutex_lock(&codec->bus->cmd_mutex); |
80 | if (!codec->bus->ops.command(codec, nid, direct, verb, parm)) | 96 | if (!codec->bus->ops.command(codec, nid, direct, verb, parm)) |
81 | res = codec->bus->ops.get_response(codec); | 97 | res = codec->bus->ops.get_response(codec); |
82 | else | 98 | else |
83 | res = (unsigned int)-1; | 99 | res = (unsigned int)-1; |
84 | mutex_unlock(&codec->bus->cmd_mutex); | 100 | mutex_unlock(&codec->bus->cmd_mutex); |
101 | snd_hda_power_down(codec); | ||
85 | return res; | 102 | return res; |
86 | } | 103 | } |
87 | 104 | ||
@@ -101,9 +118,11 @@ int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct, | |||
101 | unsigned int verb, unsigned int parm) | 118 | unsigned int verb, unsigned int parm) |
102 | { | 119 | { |
103 | int err; | 120 | int err; |
121 | snd_hda_power_up(codec); | ||
104 | mutex_lock(&codec->bus->cmd_mutex); | 122 | mutex_lock(&codec->bus->cmd_mutex); |
105 | err = codec->bus->ops.command(codec, nid, direct, verb, parm); | 123 | err = codec->bus->ops.command(codec, nid, direct, verb, parm); |
106 | mutex_unlock(&codec->bus->cmd_mutex); | 124 | mutex_unlock(&codec->bus->cmd_mutex); |
125 | snd_hda_power_down(codec); | ||
107 | return err; | 126 | return err; |
108 | } | 127 | } |
109 | 128 | ||
@@ -136,6 +155,8 @@ int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid, | |||
136 | unsigned int parm; | 155 | unsigned int parm; |
137 | 156 | ||
138 | parm = snd_hda_param_read(codec, nid, AC_PAR_NODE_COUNT); | 157 | parm = snd_hda_param_read(codec, nid, AC_PAR_NODE_COUNT); |
158 | if (parm == -1) | ||
159 | return 0; | ||
139 | *start_id = (parm >> 16) & 0x7fff; | 160 | *start_id = (parm >> 16) & 0x7fff; |
140 | return (int)(parm & 0x7fff); | 161 | return (int)(parm & 0x7fff); |
141 | } | 162 | } |
@@ -387,6 +408,13 @@ int __devinit snd_hda_bus_new(struct snd_card *card, | |||
387 | return 0; | 408 | return 0; |
388 | } | 409 | } |
389 | 410 | ||
411 | #ifdef CONFIG_SND_HDA_GENERIC | ||
412 | #define is_generic_config(codec) \ | ||
413 | (codec->bus->modelname && !strcmp(codec->bus->modelname, "generic")) | ||
414 | #else | ||
415 | #define is_generic_config(codec) 0 | ||
416 | #endif | ||
417 | |||
390 | /* | 418 | /* |
391 | * find a matching codec preset | 419 | * find a matching codec preset |
392 | */ | 420 | */ |
@@ -395,7 +423,7 @@ find_codec_preset(struct hda_codec *codec) | |||
395 | { | 423 | { |
396 | const struct hda_codec_preset **tbl, *preset; | 424 | const struct hda_codec_preset **tbl, *preset; |
397 | 425 | ||
398 | if (codec->bus->modelname && !strcmp(codec->bus->modelname, "generic")) | 426 | if (is_generic_config(codec)) |
399 | return NULL; /* use the generic parser */ | 427 | return NULL; /* use the generic parser */ |
400 | 428 | ||
401 | for (tbl = hda_preset_tables; *tbl; tbl++) { | 429 | for (tbl = hda_preset_tables; *tbl; tbl++) { |
@@ -486,6 +514,10 @@ static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node) | |||
486 | } | 514 | } |
487 | 515 | ||
488 | 516 | ||
517 | static void init_hda_cache(struct hda_cache_rec *cache, | ||
518 | unsigned int record_size); | ||
519 | static void free_hda_cache(struct hda_cache_rec *cache); | ||
520 | |||
489 | /* | 521 | /* |
490 | * codec destructor | 522 | * codec destructor |
491 | */ | 523 | */ |
@@ -493,17 +525,20 @@ static void snd_hda_codec_free(struct hda_codec *codec) | |||
493 | { | 525 | { |
494 | if (!codec) | 526 | if (!codec) |
495 | return; | 527 | return; |
528 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
529 | cancel_delayed_work(&codec->power_work); | ||
530 | flush_scheduled_work(); | ||
531 | #endif | ||
496 | list_del(&codec->list); | 532 | list_del(&codec->list); |
497 | codec->bus->caddr_tbl[codec->addr] = NULL; | 533 | codec->bus->caddr_tbl[codec->addr] = NULL; |
498 | if (codec->patch_ops.free) | 534 | if (codec->patch_ops.free) |
499 | codec->patch_ops.free(codec); | 535 | codec->patch_ops.free(codec); |
500 | kfree(codec->amp_info); | 536 | free_hda_cache(&codec->amp_cache); |
537 | free_hda_cache(&codec->cmd_cache); | ||
501 | kfree(codec->wcaps); | 538 | kfree(codec->wcaps); |
502 | kfree(codec); | 539 | kfree(codec); |
503 | } | 540 | } |
504 | 541 | ||
505 | static void init_amp_hash(struct hda_codec *codec); | ||
506 | |||
507 | /** | 542 | /** |
508 | * snd_hda_codec_new - create a HDA codec | 543 | * snd_hda_codec_new - create a HDA codec |
509 | * @bus: the bus to assign | 544 | * @bus: the bus to assign |
@@ -537,7 +572,17 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, | |||
537 | codec->bus = bus; | 572 | codec->bus = bus; |
538 | codec->addr = codec_addr; | 573 | codec->addr = codec_addr; |
539 | mutex_init(&codec->spdif_mutex); | 574 | mutex_init(&codec->spdif_mutex); |
540 | init_amp_hash(codec); | 575 | init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); |
576 | init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); | ||
577 | |||
578 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
579 | INIT_DELAYED_WORK(&codec->power_work, hda_power_work); | ||
580 | /* snd_hda_codec_new() marks the codec as power-up, and leave it as is. | ||
581 | * the caller has to power down appropriatley after initialization | ||
582 | * phase. | ||
583 | */ | ||
584 | hda_keep_power_on(codec); | ||
585 | #endif | ||
541 | 586 | ||
542 | list_add_tail(&codec->list, &bus->codec_list); | 587 | list_add_tail(&codec->list, &bus->codec_list); |
543 | bus->caddr_tbl[codec_addr] = codec; | 588 | bus->caddr_tbl[codec_addr] = codec; |
@@ -581,10 +626,26 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, | |||
581 | snd_hda_get_codec_name(codec, bus->card->mixername, | 626 | snd_hda_get_codec_name(codec, bus->card->mixername, |
582 | sizeof(bus->card->mixername)); | 627 | sizeof(bus->card->mixername)); |
583 | 628 | ||
584 | if (codec->preset && codec->preset->patch) | 629 | #ifdef CONFIG_SND_HDA_GENERIC |
585 | err = codec->preset->patch(codec); | 630 | if (is_generic_config(codec)) { |
586 | else | ||
587 | err = snd_hda_parse_generic_codec(codec); | 631 | err = snd_hda_parse_generic_codec(codec); |
632 | goto patched; | ||
633 | } | ||
634 | #endif | ||
635 | if (codec->preset && codec->preset->patch) { | ||
636 | err = codec->preset->patch(codec); | ||
637 | goto patched; | ||
638 | } | ||
639 | |||
640 | /* call the default parser */ | ||
641 | #ifdef CONFIG_SND_HDA_GENERIC | ||
642 | err = snd_hda_parse_generic_codec(codec); | ||
643 | #else | ||
644 | printk(KERN_ERR "hda-codec: No codec parser is available\n"); | ||
645 | err = -ENODEV; | ||
646 | #endif | ||
647 | |||
648 | patched: | ||
588 | if (err < 0) { | 649 | if (err < 0) { |
589 | snd_hda_codec_free(codec); | 650 | snd_hda_codec_free(codec); |
590 | return err; | 651 | return err; |
@@ -594,6 +655,9 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, | |||
594 | init_unsol_queue(bus); | 655 | init_unsol_queue(bus); |
595 | 656 | ||
596 | snd_hda_codec_proc_new(codec); | 657 | snd_hda_codec_proc_new(codec); |
658 | #ifdef CONFIG_SND_HDA_HWDEP | ||
659 | snd_hda_create_hwdep(codec); | ||
660 | #endif | ||
597 | 661 | ||
598 | sprintf(component, "HDA:%08x", codec->vendor_id); | 662 | sprintf(component, "HDA:%08x", codec->vendor_id); |
599 | snd_component_add(codec->bus->card, component); | 663 | snd_component_add(codec->bus->card, component); |
@@ -637,59 +701,72 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, | |||
637 | #define INFO_AMP_VOL(ch) (1 << (1 + (ch))) | 701 | #define INFO_AMP_VOL(ch) (1 << (1 + (ch))) |
638 | 702 | ||
639 | /* initialize the hash table */ | 703 | /* initialize the hash table */ |
640 | static void __devinit init_amp_hash(struct hda_codec *codec) | 704 | static void __devinit init_hda_cache(struct hda_cache_rec *cache, |
705 | unsigned int record_size) | ||
706 | { | ||
707 | memset(cache, 0, sizeof(*cache)); | ||
708 | memset(cache->hash, 0xff, sizeof(cache->hash)); | ||
709 | cache->record_size = record_size; | ||
710 | } | ||
711 | |||
712 | static void free_hda_cache(struct hda_cache_rec *cache) | ||
641 | { | 713 | { |
642 | memset(codec->amp_hash, 0xff, sizeof(codec->amp_hash)); | 714 | kfree(cache->buffer); |
643 | codec->num_amp_entries = 0; | ||
644 | codec->amp_info_size = 0; | ||
645 | codec->amp_info = NULL; | ||
646 | } | 715 | } |
647 | 716 | ||
648 | /* query the hash. allocate an entry if not found. */ | 717 | /* query the hash. allocate an entry if not found. */ |
649 | static struct hda_amp_info *get_alloc_amp_hash(struct hda_codec *codec, u32 key) | 718 | static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache, |
719 | u32 key) | ||
650 | { | 720 | { |
651 | u16 idx = key % (u16)ARRAY_SIZE(codec->amp_hash); | 721 | u16 idx = key % (u16)ARRAY_SIZE(cache->hash); |
652 | u16 cur = codec->amp_hash[idx]; | 722 | u16 cur = cache->hash[idx]; |
653 | struct hda_amp_info *info; | 723 | struct hda_cache_head *info; |
654 | 724 | ||
655 | while (cur != 0xffff) { | 725 | while (cur != 0xffff) { |
656 | info = &codec->amp_info[cur]; | 726 | info = (struct hda_cache_head *)(cache->buffer + |
727 | cur * cache->record_size); | ||
657 | if (info->key == key) | 728 | if (info->key == key) |
658 | return info; | 729 | return info; |
659 | cur = info->next; | 730 | cur = info->next; |
660 | } | 731 | } |
661 | 732 | ||
662 | /* add a new hash entry */ | 733 | /* add a new hash entry */ |
663 | if (codec->num_amp_entries >= codec->amp_info_size) { | 734 | if (cache->num_entries >= cache->size) { |
664 | /* reallocate the array */ | 735 | /* reallocate the array */ |
665 | int new_size = codec->amp_info_size + 64; | 736 | unsigned int new_size = cache->size + 64; |
666 | struct hda_amp_info *new_info; | 737 | void *new_buffer; |
667 | new_info = kcalloc(new_size, sizeof(struct hda_amp_info), | 738 | new_buffer = kcalloc(new_size, cache->record_size, GFP_KERNEL); |
668 | GFP_KERNEL); | 739 | if (!new_buffer) { |
669 | if (!new_info) { | ||
670 | snd_printk(KERN_ERR "hda_codec: " | 740 | snd_printk(KERN_ERR "hda_codec: " |
671 | "can't malloc amp_info\n"); | 741 | "can't malloc amp_info\n"); |
672 | return NULL; | 742 | return NULL; |
673 | } | 743 | } |
674 | if (codec->amp_info) { | 744 | if (cache->buffer) { |
675 | memcpy(new_info, codec->amp_info, | 745 | memcpy(new_buffer, cache->buffer, |
676 | codec->amp_info_size * | 746 | cache->size * cache->record_size); |
677 | sizeof(struct hda_amp_info)); | 747 | kfree(cache->buffer); |
678 | kfree(codec->amp_info); | ||
679 | } | 748 | } |
680 | codec->amp_info_size = new_size; | 749 | cache->size = new_size; |
681 | codec->amp_info = new_info; | 750 | cache->buffer = new_buffer; |
682 | } | 751 | } |
683 | cur = codec->num_amp_entries++; | 752 | cur = cache->num_entries++; |
684 | info = &codec->amp_info[cur]; | 753 | info = (struct hda_cache_head *)(cache->buffer + |
754 | cur * cache->record_size); | ||
685 | info->key = key; | 755 | info->key = key; |
686 | info->status = 0; /* not initialized yet */ | 756 | info->val = 0; |
687 | info->next = codec->amp_hash[idx]; | 757 | info->next = cache->hash[idx]; |
688 | codec->amp_hash[idx] = cur; | 758 | cache->hash[idx] = cur; |
689 | 759 | ||
690 | return info; | 760 | return info; |
691 | } | 761 | } |
692 | 762 | ||
763 | /* query and allocate an amp hash entry */ | ||
764 | static inline struct hda_amp_info * | ||
765 | get_alloc_amp_hash(struct hda_codec *codec, u32 key) | ||
766 | { | ||
767 | return (struct hda_amp_info *)get_alloc_hash(&codec->amp_cache, key); | ||
768 | } | ||
769 | |||
693 | /* | 770 | /* |
694 | * query AMP capabilities for the given widget and direction | 771 | * query AMP capabilities for the given widget and direction |
695 | */ | 772 | */ |
@@ -700,7 +777,7 @@ static u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction) | |||
700 | info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, 0)); | 777 | info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, 0)); |
701 | if (!info) | 778 | if (!info) |
702 | return 0; | 779 | return 0; |
703 | if (!(info->status & INFO_AMP_CAPS)) { | 780 | if (!(info->head.val & INFO_AMP_CAPS)) { |
704 | if (!(get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD)) | 781 | if (!(get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD)) |
705 | nid = codec->afg; | 782 | nid = codec->afg; |
706 | info->amp_caps = snd_hda_param_read(codec, nid, | 783 | info->amp_caps = snd_hda_param_read(codec, nid, |
@@ -708,7 +785,7 @@ static u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction) | |||
708 | AC_PAR_AMP_OUT_CAP : | 785 | AC_PAR_AMP_OUT_CAP : |
709 | AC_PAR_AMP_IN_CAP); | 786 | AC_PAR_AMP_IN_CAP); |
710 | if (info->amp_caps) | 787 | if (info->amp_caps) |
711 | info->status |= INFO_AMP_CAPS; | 788 | info->head.val |= INFO_AMP_CAPS; |
712 | } | 789 | } |
713 | return info->amp_caps; | 790 | return info->amp_caps; |
714 | } | 791 | } |
@@ -722,7 +799,7 @@ int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, | |||
722 | if (!info) | 799 | if (!info) |
723 | return -EINVAL; | 800 | return -EINVAL; |
724 | info->amp_caps = caps; | 801 | info->amp_caps = caps; |
725 | info->status |= INFO_AMP_CAPS; | 802 | info->head.val |= INFO_AMP_CAPS; |
726 | return 0; | 803 | return 0; |
727 | } | 804 | } |
728 | 805 | ||
@@ -736,7 +813,7 @@ static unsigned int get_vol_mute(struct hda_codec *codec, | |||
736 | { | 813 | { |
737 | u32 val, parm; | 814 | u32 val, parm; |
738 | 815 | ||
739 | if (info->status & INFO_AMP_VOL(ch)) | 816 | if (info->head.val & INFO_AMP_VOL(ch)) |
740 | return info->vol[ch]; | 817 | return info->vol[ch]; |
741 | 818 | ||
742 | parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT; | 819 | parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT; |
@@ -745,7 +822,7 @@ static unsigned int get_vol_mute(struct hda_codec *codec, | |||
745 | val = snd_hda_codec_read(codec, nid, 0, | 822 | val = snd_hda_codec_read(codec, nid, 0, |
746 | AC_VERB_GET_AMP_GAIN_MUTE, parm); | 823 | AC_VERB_GET_AMP_GAIN_MUTE, parm); |
747 | info->vol[ch] = val & 0xff; | 824 | info->vol[ch] = val & 0xff; |
748 | info->status |= INFO_AMP_VOL(ch); | 825 | info->head.val |= INFO_AMP_VOL(ch); |
749 | return info->vol[ch]; | 826 | return info->vol[ch]; |
750 | } | 827 | } |
751 | 828 | ||
@@ -792,12 +869,50 @@ int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch, | |||
792 | return 0; | 869 | return 0; |
793 | val &= mask; | 870 | val &= mask; |
794 | val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask; | 871 | val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask; |
795 | if (info->vol[ch] == val && !codec->in_resume) | 872 | if (info->vol[ch] == val) |
796 | return 0; | 873 | return 0; |
797 | put_vol_mute(codec, info, nid, ch, direction, idx, val); | 874 | put_vol_mute(codec, info, nid, ch, direction, idx, val); |
798 | return 1; | 875 | return 1; |
799 | } | 876 | } |
800 | 877 | ||
878 | /* | ||
879 | * update the AMP stereo with the same mask and value | ||
880 | */ | ||
881 | int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid, | ||
882 | int direction, int idx, int mask, int val) | ||
883 | { | ||
884 | int ch, ret = 0; | ||
885 | for (ch = 0; ch < 2; ch++) | ||
886 | ret |= snd_hda_codec_amp_update(codec, nid, ch, direction, | ||
887 | idx, mask, val); | ||
888 | return ret; | ||
889 | } | ||
890 | |||
891 | #ifdef SND_HDA_NEEDS_RESUME | ||
892 | /* resume the all amp commands from the cache */ | ||
893 | void snd_hda_codec_resume_amp(struct hda_codec *codec) | ||
894 | { | ||
895 | struct hda_amp_info *buffer = codec->amp_cache.buffer; | ||
896 | int i; | ||
897 | |||
898 | for (i = 0; i < codec->amp_cache.size; i++, buffer++) { | ||
899 | u32 key = buffer->head.key; | ||
900 | hda_nid_t nid; | ||
901 | unsigned int idx, dir, ch; | ||
902 | if (!key) | ||
903 | continue; | ||
904 | nid = key & 0xff; | ||
905 | idx = (key >> 16) & 0xff; | ||
906 | dir = (key >> 24) & 0xff; | ||
907 | for (ch = 0; ch < 2; ch++) { | ||
908 | if (!(buffer->head.val & INFO_AMP_VOL(ch))) | ||
909 | continue; | ||
910 | put_vol_mute(codec, buffer, nid, ch, dir, idx, | ||
911 | buffer->vol[ch]); | ||
912 | } | ||
913 | } | ||
914 | } | ||
915 | #endif /* SND_HDA_NEEDS_RESUME */ | ||
801 | 916 | ||
802 | /* | 917 | /* |
803 | * AMP control callbacks | 918 | * AMP control callbacks |
@@ -844,9 +959,11 @@ int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, | |||
844 | long *valp = ucontrol->value.integer.value; | 959 | long *valp = ucontrol->value.integer.value; |
845 | 960 | ||
846 | if (chs & 1) | 961 | if (chs & 1) |
847 | *valp++ = snd_hda_codec_amp_read(codec, nid, 0, dir, idx) & 0x7f; | 962 | *valp++ = snd_hda_codec_amp_read(codec, nid, 0, dir, idx) |
963 | & HDA_AMP_VOLMASK; | ||
848 | if (chs & 2) | 964 | if (chs & 2) |
849 | *valp = snd_hda_codec_amp_read(codec, nid, 1, dir, idx) & 0x7f; | 965 | *valp = snd_hda_codec_amp_read(codec, nid, 1, dir, idx) |
966 | & HDA_AMP_VOLMASK; | ||
850 | return 0; | 967 | return 0; |
851 | } | 968 | } |
852 | 969 | ||
@@ -861,6 +978,7 @@ int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, | |||
861 | long *valp = ucontrol->value.integer.value; | 978 | long *valp = ucontrol->value.integer.value; |
862 | int change = 0; | 979 | int change = 0; |
863 | 980 | ||
981 | snd_hda_power_up(codec); | ||
864 | if (chs & 1) { | 982 | if (chs & 1) { |
865 | change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx, | 983 | change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx, |
866 | 0x7f, *valp); | 984 | 0x7f, *valp); |
@@ -869,6 +987,7 @@ int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, | |||
869 | if (chs & 2) | 987 | if (chs & 2) |
870 | change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx, | 988 | change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx, |
871 | 0x7f, *valp); | 989 | 0x7f, *valp); |
990 | snd_hda_power_down(codec); | ||
872 | return change; | 991 | return change; |
873 | } | 992 | } |
874 | 993 | ||
@@ -923,10 +1042,10 @@ int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol, | |||
923 | 1042 | ||
924 | if (chs & 1) | 1043 | if (chs & 1) |
925 | *valp++ = (snd_hda_codec_amp_read(codec, nid, 0, dir, idx) & | 1044 | *valp++ = (snd_hda_codec_amp_read(codec, nid, 0, dir, idx) & |
926 | 0x80) ? 0 : 1; | 1045 | HDA_AMP_MUTE) ? 0 : 1; |
927 | if (chs & 2) | 1046 | if (chs & 2) |
928 | *valp = (snd_hda_codec_amp_read(codec, nid, 1, dir, idx) & | 1047 | *valp = (snd_hda_codec_amp_read(codec, nid, 1, dir, idx) & |
929 | 0x80) ? 0 : 1; | 1048 | HDA_AMP_MUTE) ? 0 : 1; |
930 | return 0; | 1049 | return 0; |
931 | } | 1050 | } |
932 | 1051 | ||
@@ -941,15 +1060,22 @@ int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, | |||
941 | long *valp = ucontrol->value.integer.value; | 1060 | long *valp = ucontrol->value.integer.value; |
942 | int change = 0; | 1061 | int change = 0; |
943 | 1062 | ||
1063 | snd_hda_power_up(codec); | ||
944 | if (chs & 1) { | 1064 | if (chs & 1) { |
945 | change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx, | 1065 | change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx, |
946 | 0x80, *valp ? 0 : 0x80); | 1066 | HDA_AMP_MUTE, |
1067 | *valp ? 0 : HDA_AMP_MUTE); | ||
947 | valp++; | 1068 | valp++; |
948 | } | 1069 | } |
949 | if (chs & 2) | 1070 | if (chs & 2) |
950 | change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx, | 1071 | change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx, |
951 | 0x80, *valp ? 0 : 0x80); | 1072 | HDA_AMP_MUTE, |
952 | 1073 | *valp ? 0 : HDA_AMP_MUTE); | |
1074 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1075 | if (codec->patch_ops.check_power_status) | ||
1076 | codec->patch_ops.check_power_status(codec, nid); | ||
1077 | #endif | ||
1078 | snd_hda_power_down(codec); | ||
953 | return change; | 1079 | return change; |
954 | } | 1080 | } |
955 | 1081 | ||
@@ -1002,6 +1128,93 @@ int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol, | |||
1002 | } | 1128 | } |
1003 | 1129 | ||
1004 | /* | 1130 | /* |
1131 | * generic bound volume/swtich controls | ||
1132 | */ | ||
1133 | int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol, | ||
1134 | struct snd_ctl_elem_info *uinfo) | ||
1135 | { | ||
1136 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1137 | struct hda_bind_ctls *c; | ||
1138 | int err; | ||
1139 | |||
1140 | c = (struct hda_bind_ctls *)kcontrol->private_value; | ||
1141 | mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */ | ||
1142 | kcontrol->private_value = *c->values; | ||
1143 | err = c->ops->info(kcontrol, uinfo); | ||
1144 | kcontrol->private_value = (long)c; | ||
1145 | mutex_unlock(&codec->spdif_mutex); | ||
1146 | return err; | ||
1147 | } | ||
1148 | |||
1149 | int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol, | ||
1150 | struct snd_ctl_elem_value *ucontrol) | ||
1151 | { | ||
1152 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1153 | struct hda_bind_ctls *c; | ||
1154 | int err; | ||
1155 | |||
1156 | c = (struct hda_bind_ctls *)kcontrol->private_value; | ||
1157 | mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */ | ||
1158 | kcontrol->private_value = *c->values; | ||
1159 | err = c->ops->get(kcontrol, ucontrol); | ||
1160 | kcontrol->private_value = (long)c; | ||
1161 | mutex_unlock(&codec->spdif_mutex); | ||
1162 | return err; | ||
1163 | } | ||
1164 | |||
1165 | int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol, | ||
1166 | struct snd_ctl_elem_value *ucontrol) | ||
1167 | { | ||
1168 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1169 | struct hda_bind_ctls *c; | ||
1170 | unsigned long *vals; | ||
1171 | int err = 0, change = 0; | ||
1172 | |||
1173 | c = (struct hda_bind_ctls *)kcontrol->private_value; | ||
1174 | mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */ | ||
1175 | for (vals = c->values; *vals; vals++) { | ||
1176 | kcontrol->private_value = *vals; | ||
1177 | err = c->ops->put(kcontrol, ucontrol); | ||
1178 | if (err < 0) | ||
1179 | break; | ||
1180 | change |= err; | ||
1181 | } | ||
1182 | kcontrol->private_value = (long)c; | ||
1183 | mutex_unlock(&codec->spdif_mutex); | ||
1184 | return err < 0 ? err : change; | ||
1185 | } | ||
1186 | |||
1187 | int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag, | ||
1188 | unsigned int size, unsigned int __user *tlv) | ||
1189 | { | ||
1190 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1191 | struct hda_bind_ctls *c; | ||
1192 | int err; | ||
1193 | |||
1194 | c = (struct hda_bind_ctls *)kcontrol->private_value; | ||
1195 | mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */ | ||
1196 | kcontrol->private_value = *c->values; | ||
1197 | err = c->ops->tlv(kcontrol, op_flag, size, tlv); | ||
1198 | kcontrol->private_value = (long)c; | ||
1199 | mutex_unlock(&codec->spdif_mutex); | ||
1200 | return err; | ||
1201 | } | ||
1202 | |||
1203 | struct hda_ctl_ops snd_hda_bind_vol = { | ||
1204 | .info = snd_hda_mixer_amp_volume_info, | ||
1205 | .get = snd_hda_mixer_amp_volume_get, | ||
1206 | .put = snd_hda_mixer_amp_volume_put, | ||
1207 | .tlv = snd_hda_mixer_amp_tlv | ||
1208 | }; | ||
1209 | |||
1210 | struct hda_ctl_ops snd_hda_bind_sw = { | ||
1211 | .info = snd_hda_mixer_amp_switch_info, | ||
1212 | .get = snd_hda_mixer_amp_switch_get, | ||
1213 | .put = snd_hda_mixer_amp_switch_put, | ||
1214 | .tlv = snd_hda_mixer_amp_tlv | ||
1215 | }; | ||
1216 | |||
1217 | /* | ||
1005 | * SPDIF out controls | 1218 | * SPDIF out controls |
1006 | */ | 1219 | */ |
1007 | 1220 | ||
@@ -1118,26 +1331,20 @@ static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol, | |||
1118 | change = codec->spdif_ctls != val; | 1331 | change = codec->spdif_ctls != val; |
1119 | codec->spdif_ctls = val; | 1332 | codec->spdif_ctls = val; |
1120 | 1333 | ||
1121 | if (change || codec->in_resume) { | 1334 | if (change) { |
1122 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, | 1335 | snd_hda_codec_write_cache(codec, nid, 0, |
1123 | val & 0xff); | 1336 | AC_VERB_SET_DIGI_CONVERT_1, |
1124 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_2, | 1337 | val & 0xff); |
1125 | val >> 8); | 1338 | snd_hda_codec_write_cache(codec, nid, 0, |
1339 | AC_VERB_SET_DIGI_CONVERT_2, | ||
1340 | val >> 8); | ||
1126 | } | 1341 | } |
1127 | 1342 | ||
1128 | mutex_unlock(&codec->spdif_mutex); | 1343 | mutex_unlock(&codec->spdif_mutex); |
1129 | return change; | 1344 | return change; |
1130 | } | 1345 | } |
1131 | 1346 | ||
1132 | static int snd_hda_spdif_out_switch_info(struct snd_kcontrol *kcontrol, | 1347 | #define snd_hda_spdif_out_switch_info snd_ctl_boolean_mono_info |
1133 | struct snd_ctl_elem_info *uinfo) | ||
1134 | { | ||
1135 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1136 | uinfo->count = 1; | ||
1137 | uinfo->value.integer.min = 0; | ||
1138 | uinfo->value.integer.max = 1; | ||
1139 | return 0; | ||
1140 | } | ||
1141 | 1348 | ||
1142 | static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol, | 1349 | static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol, |
1143 | struct snd_ctl_elem_value *ucontrol) | 1350 | struct snd_ctl_elem_value *ucontrol) |
@@ -1161,17 +1368,16 @@ static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol, | |||
1161 | if (ucontrol->value.integer.value[0]) | 1368 | if (ucontrol->value.integer.value[0]) |
1162 | val |= AC_DIG1_ENABLE; | 1369 | val |= AC_DIG1_ENABLE; |
1163 | change = codec->spdif_ctls != val; | 1370 | change = codec->spdif_ctls != val; |
1164 | if (change || codec->in_resume) { | 1371 | if (change) { |
1165 | codec->spdif_ctls = val; | 1372 | codec->spdif_ctls = val; |
1166 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, | 1373 | snd_hda_codec_write_cache(codec, nid, 0, |
1167 | val & 0xff); | 1374 | AC_VERB_SET_DIGI_CONVERT_1, |
1375 | val & 0xff); | ||
1168 | /* unmute amp switch (if any) */ | 1376 | /* unmute amp switch (if any) */ |
1169 | if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) && | 1377 | if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) && |
1170 | (val & AC_DIG1_ENABLE)) | 1378 | (val & AC_DIG1_ENABLE)) |
1171 | snd_hda_codec_write(codec, nid, 0, | 1379 | snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, |
1172 | AC_VERB_SET_AMP_GAIN_MUTE, | 1380 | HDA_AMP_MUTE, 0); |
1173 | AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | | ||
1174 | AC_AMP_SET_OUTPUT); | ||
1175 | } | 1381 | } |
1176 | mutex_unlock(&codec->spdif_mutex); | 1382 | mutex_unlock(&codec->spdif_mutex); |
1177 | return change; | 1383 | return change; |
@@ -1219,8 +1425,7 @@ static struct snd_kcontrol_new dig_mixes[] = { | |||
1219 | * | 1425 | * |
1220 | * Returns 0 if successful, or a negative error code. | 1426 | * Returns 0 if successful, or a negative error code. |
1221 | */ | 1427 | */ |
1222 | int __devinit snd_hda_create_spdif_out_ctls(struct hda_codec *codec, | 1428 | int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid) |
1223 | hda_nid_t nid) | ||
1224 | { | 1429 | { |
1225 | int err; | 1430 | int err; |
1226 | struct snd_kcontrol *kctl; | 1431 | struct snd_kcontrol *kctl; |
@@ -1264,10 +1469,10 @@ static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol, | |||
1264 | 1469 | ||
1265 | mutex_lock(&codec->spdif_mutex); | 1470 | mutex_lock(&codec->spdif_mutex); |
1266 | change = codec->spdif_in_enable != val; | 1471 | change = codec->spdif_in_enable != val; |
1267 | if (change || codec->in_resume) { | 1472 | if (change) { |
1268 | codec->spdif_in_enable = val; | 1473 | codec->spdif_in_enable = val; |
1269 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, | 1474 | snd_hda_codec_write_cache(codec, nid, 0, |
1270 | val); | 1475 | AC_VERB_SET_DIGI_CONVERT_1, val); |
1271 | } | 1476 | } |
1272 | mutex_unlock(&codec->spdif_mutex); | 1477 | mutex_unlock(&codec->spdif_mutex); |
1273 | return change; | 1478 | return change; |
@@ -1318,8 +1523,7 @@ static struct snd_kcontrol_new dig_in_ctls[] = { | |||
1318 | * | 1523 | * |
1319 | * Returns 0 if successful, or a negative error code. | 1524 | * Returns 0 if successful, or a negative error code. |
1320 | */ | 1525 | */ |
1321 | int __devinit snd_hda_create_spdif_in_ctls(struct hda_codec *codec, | 1526 | int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid) |
1322 | hda_nid_t nid) | ||
1323 | { | 1527 | { |
1324 | int err; | 1528 | int err; |
1325 | struct snd_kcontrol *kctl; | 1529 | struct snd_kcontrol *kctl; |
@@ -1338,6 +1542,79 @@ int __devinit snd_hda_create_spdif_in_ctls(struct hda_codec *codec, | |||
1338 | return 0; | 1542 | return 0; |
1339 | } | 1543 | } |
1340 | 1544 | ||
1545 | #ifdef SND_HDA_NEEDS_RESUME | ||
1546 | /* | ||
1547 | * command cache | ||
1548 | */ | ||
1549 | |||
1550 | /* build a 32bit cache key with the widget id and the command parameter */ | ||
1551 | #define build_cmd_cache_key(nid, verb) ((verb << 8) | nid) | ||
1552 | #define get_cmd_cache_nid(key) ((key) & 0xff) | ||
1553 | #define get_cmd_cache_cmd(key) (((key) >> 8) & 0xffff) | ||
1554 | |||
1555 | /** | ||
1556 | * snd_hda_codec_write_cache - send a single command with caching | ||
1557 | * @codec: the HDA codec | ||
1558 | * @nid: NID to send the command | ||
1559 | * @direct: direct flag | ||
1560 | * @verb: the verb to send | ||
1561 | * @parm: the parameter for the verb | ||
1562 | * | ||
1563 | * Send a single command without waiting for response. | ||
1564 | * | ||
1565 | * Returns 0 if successful, or a negative error code. | ||
1566 | */ | ||
1567 | int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, | ||
1568 | int direct, unsigned int verb, unsigned int parm) | ||
1569 | { | ||
1570 | int err; | ||
1571 | snd_hda_power_up(codec); | ||
1572 | mutex_lock(&codec->bus->cmd_mutex); | ||
1573 | err = codec->bus->ops.command(codec, nid, direct, verb, parm); | ||
1574 | if (!err) { | ||
1575 | struct hda_cache_head *c; | ||
1576 | u32 key = build_cmd_cache_key(nid, verb); | ||
1577 | c = get_alloc_hash(&codec->cmd_cache, key); | ||
1578 | if (c) | ||
1579 | c->val = parm; | ||
1580 | } | ||
1581 | mutex_unlock(&codec->bus->cmd_mutex); | ||
1582 | snd_hda_power_down(codec); | ||
1583 | return err; | ||
1584 | } | ||
1585 | |||
1586 | /* resume the all commands from the cache */ | ||
1587 | void snd_hda_codec_resume_cache(struct hda_codec *codec) | ||
1588 | { | ||
1589 | struct hda_cache_head *buffer = codec->cmd_cache.buffer; | ||
1590 | int i; | ||
1591 | |||
1592 | for (i = 0; i < codec->cmd_cache.size; i++, buffer++) { | ||
1593 | u32 key = buffer->key; | ||
1594 | if (!key) | ||
1595 | continue; | ||
1596 | snd_hda_codec_write(codec, get_cmd_cache_nid(key), 0, | ||
1597 | get_cmd_cache_cmd(key), buffer->val); | ||
1598 | } | ||
1599 | } | ||
1600 | |||
1601 | /** | ||
1602 | * snd_hda_sequence_write_cache - sequence writes with caching | ||
1603 | * @codec: the HDA codec | ||
1604 | * @seq: VERB array to send | ||
1605 | * | ||
1606 | * Send the commands sequentially from the given array. | ||
1607 | * Thte commands are recorded on cache for power-save and resume. | ||
1608 | * The array must be terminated with NID=0. | ||
1609 | */ | ||
1610 | void snd_hda_sequence_write_cache(struct hda_codec *codec, | ||
1611 | const struct hda_verb *seq) | ||
1612 | { | ||
1613 | for (; seq->nid; seq++) | ||
1614 | snd_hda_codec_write_cache(codec, seq->nid, 0, seq->verb, | ||
1615 | seq->param); | ||
1616 | } | ||
1617 | #endif /* SND_HDA_NEEDS_RESUME */ | ||
1341 | 1618 | ||
1342 | /* | 1619 | /* |
1343 | * set power state of the codec | 1620 | * set power state of the codec |
@@ -1345,23 +1622,86 @@ int __devinit snd_hda_create_spdif_in_ctls(struct hda_codec *codec, | |||
1345 | static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, | 1622 | static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, |
1346 | unsigned int power_state) | 1623 | unsigned int power_state) |
1347 | { | 1624 | { |
1348 | hda_nid_t nid, nid_start; | 1625 | hda_nid_t nid; |
1349 | int nodes; | 1626 | int i; |
1350 | 1627 | ||
1351 | snd_hda_codec_write(codec, fg, 0, AC_VERB_SET_POWER_STATE, | 1628 | snd_hda_codec_write(codec, fg, 0, AC_VERB_SET_POWER_STATE, |
1352 | power_state); | 1629 | power_state); |
1353 | 1630 | ||
1354 | nodes = snd_hda_get_sub_nodes(codec, fg, &nid_start); | 1631 | nid = codec->start_nid; |
1355 | for (nid = nid_start; nid < nodes + nid_start; nid++) { | 1632 | for (i = 0; i < codec->num_nodes; i++, nid++) { |
1356 | if (get_wcaps(codec, nid) & AC_WCAP_POWER) | 1633 | if (get_wcaps(codec, nid) & AC_WCAP_POWER) { |
1634 | unsigned int pincap; | ||
1635 | /* | ||
1636 | * don't power down the widget if it controls eapd | ||
1637 | * and EAPD_BTLENABLE is set. | ||
1638 | */ | ||
1639 | pincap = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); | ||
1640 | if (pincap & AC_PINCAP_EAPD) { | ||
1641 | int eapd = snd_hda_codec_read(codec, nid, | ||
1642 | 0, AC_VERB_GET_EAPD_BTLENABLE, 0); | ||
1643 | eapd &= 0x02; | ||
1644 | if (power_state == AC_PWRST_D3 && eapd) | ||
1645 | continue; | ||
1646 | } | ||
1357 | snd_hda_codec_write(codec, nid, 0, | 1647 | snd_hda_codec_write(codec, nid, 0, |
1358 | AC_VERB_SET_POWER_STATE, | 1648 | AC_VERB_SET_POWER_STATE, |
1359 | power_state); | 1649 | power_state); |
1650 | } | ||
1360 | } | 1651 | } |
1361 | 1652 | ||
1362 | if (power_state == AC_PWRST_D0) | 1653 | if (power_state == AC_PWRST_D0) { |
1654 | unsigned long end_time; | ||
1655 | int state; | ||
1363 | msleep(10); | 1656 | msleep(10); |
1657 | /* wait until the codec reachs to D0 */ | ||
1658 | end_time = jiffies + msecs_to_jiffies(500); | ||
1659 | do { | ||
1660 | state = snd_hda_codec_read(codec, fg, 0, | ||
1661 | AC_VERB_GET_POWER_STATE, 0); | ||
1662 | if (state == power_state) | ||
1663 | break; | ||
1664 | msleep(1); | ||
1665 | } while (time_after_eq(end_time, jiffies)); | ||
1666 | } | ||
1667 | } | ||
1668 | |||
1669 | #ifdef SND_HDA_NEEDS_RESUME | ||
1670 | /* | ||
1671 | * call suspend and power-down; used both from PM and power-save | ||
1672 | */ | ||
1673 | static void hda_call_codec_suspend(struct hda_codec *codec) | ||
1674 | { | ||
1675 | if (codec->patch_ops.suspend) | ||
1676 | codec->patch_ops.suspend(codec, PMSG_SUSPEND); | ||
1677 | hda_set_power_state(codec, | ||
1678 | codec->afg ? codec->afg : codec->mfg, | ||
1679 | AC_PWRST_D3); | ||
1680 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1681 | cancel_delayed_work(&codec->power_work); | ||
1682 | codec->power_on = 0; | ||
1683 | codec->power_transition = 0; | ||
1684 | #endif | ||
1685 | } | ||
1686 | |||
1687 | /* | ||
1688 | * kick up codec; used both from PM and power-save | ||
1689 | */ | ||
1690 | static void hda_call_codec_resume(struct hda_codec *codec) | ||
1691 | { | ||
1692 | hda_set_power_state(codec, | ||
1693 | codec->afg ? codec->afg : codec->mfg, | ||
1694 | AC_PWRST_D0); | ||
1695 | if (codec->patch_ops.resume) | ||
1696 | codec->patch_ops.resume(codec); | ||
1697 | else { | ||
1698 | if (codec->patch_ops.init) | ||
1699 | codec->patch_ops.init(codec); | ||
1700 | snd_hda_codec_resume_amp(codec); | ||
1701 | snd_hda_codec_resume_cache(codec); | ||
1702 | } | ||
1364 | } | 1703 | } |
1704 | #endif /* SND_HDA_NEEDS_RESUME */ | ||
1365 | 1705 | ||
1366 | 1706 | ||
1367 | /** | 1707 | /** |
@@ -1376,28 +1716,24 @@ int __devinit snd_hda_build_controls(struct hda_bus *bus) | |||
1376 | { | 1716 | { |
1377 | struct hda_codec *codec; | 1717 | struct hda_codec *codec; |
1378 | 1718 | ||
1379 | /* build controls */ | ||
1380 | list_for_each_entry(codec, &bus->codec_list, list) { | 1719 | list_for_each_entry(codec, &bus->codec_list, list) { |
1381 | int err; | 1720 | int err = 0; |
1382 | if (!codec->patch_ops.build_controls) | 1721 | /* fake as if already powered-on */ |
1383 | continue; | 1722 | hda_keep_power_on(codec); |
1384 | err = codec->patch_ops.build_controls(codec); | 1723 | /* then fire up */ |
1385 | if (err < 0) | ||
1386 | return err; | ||
1387 | } | ||
1388 | |||
1389 | /* initialize */ | ||
1390 | list_for_each_entry(codec, &bus->codec_list, list) { | ||
1391 | int err; | ||
1392 | hda_set_power_state(codec, | 1724 | hda_set_power_state(codec, |
1393 | codec->afg ? codec->afg : codec->mfg, | 1725 | codec->afg ? codec->afg : codec->mfg, |
1394 | AC_PWRST_D0); | 1726 | AC_PWRST_D0); |
1395 | if (!codec->patch_ops.init) | 1727 | /* continue to initialize... */ |
1396 | continue; | 1728 | if (codec->patch_ops.init) |
1397 | err = codec->patch_ops.init(codec); | 1729 | err = codec->patch_ops.init(codec); |
1730 | if (!err && codec->patch_ops.build_controls) | ||
1731 | err = codec->patch_ops.build_controls(codec); | ||
1732 | snd_hda_power_down(codec); | ||
1398 | if (err < 0) | 1733 | if (err < 0) |
1399 | return err; | 1734 | return err; |
1400 | } | 1735 | } |
1736 | |||
1401 | return 0; | 1737 | return 0; |
1402 | } | 1738 | } |
1403 | 1739 | ||
@@ -1789,9 +2125,9 @@ int __devinit snd_hda_build_pcms(struct hda_bus *bus) | |||
1789 | * | 2125 | * |
1790 | * If no entries are matching, the function returns a negative value. | 2126 | * If no entries are matching, the function returns a negative value. |
1791 | */ | 2127 | */ |
1792 | int __devinit snd_hda_check_board_config(struct hda_codec *codec, | 2128 | int snd_hda_check_board_config(struct hda_codec *codec, |
1793 | int num_configs, const char **models, | 2129 | int num_configs, const char **models, |
1794 | const struct snd_pci_quirk *tbl) | 2130 | const struct snd_pci_quirk *tbl) |
1795 | { | 2131 | { |
1796 | if (codec->bus->modelname && models) { | 2132 | if (codec->bus->modelname && models) { |
1797 | int i; | 2133 | int i; |
@@ -1841,10 +2177,9 @@ int __devinit snd_hda_check_board_config(struct hda_codec *codec, | |||
1841 | * | 2177 | * |
1842 | * Returns 0 if successful, or a negative error code. | 2178 | * Returns 0 if successful, or a negative error code. |
1843 | */ | 2179 | */ |
1844 | int __devinit snd_hda_add_new_ctls(struct hda_codec *codec, | 2180 | int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew) |
1845 | struct snd_kcontrol_new *knew) | ||
1846 | { | 2181 | { |
1847 | int err; | 2182 | int err; |
1848 | 2183 | ||
1849 | for (; knew->name; knew++) { | 2184 | for (; knew->name; knew++) { |
1850 | struct snd_kcontrol *kctl; | 2185 | struct snd_kcontrol *kctl; |
@@ -1867,6 +2202,93 @@ int __devinit snd_hda_add_new_ctls(struct hda_codec *codec, | |||
1867 | return 0; | 2202 | return 0; |
1868 | } | 2203 | } |
1869 | 2204 | ||
2205 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
2206 | static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, | ||
2207 | unsigned int power_state); | ||
2208 | |||
2209 | static void hda_power_work(struct work_struct *work) | ||
2210 | { | ||
2211 | struct hda_codec *codec = | ||
2212 | container_of(work, struct hda_codec, power_work.work); | ||
2213 | |||
2214 | if (!codec->power_on || codec->power_count) { | ||
2215 | codec->power_transition = 0; | ||
2216 | return; | ||
2217 | } | ||
2218 | |||
2219 | hda_call_codec_suspend(codec); | ||
2220 | if (codec->bus->ops.pm_notify) | ||
2221 | codec->bus->ops.pm_notify(codec); | ||
2222 | } | ||
2223 | |||
2224 | static void hda_keep_power_on(struct hda_codec *codec) | ||
2225 | { | ||
2226 | codec->power_count++; | ||
2227 | codec->power_on = 1; | ||
2228 | } | ||
2229 | |||
2230 | void snd_hda_power_up(struct hda_codec *codec) | ||
2231 | { | ||
2232 | codec->power_count++; | ||
2233 | if (codec->power_on || codec->power_transition) | ||
2234 | return; | ||
2235 | |||
2236 | codec->power_on = 1; | ||
2237 | if (codec->bus->ops.pm_notify) | ||
2238 | codec->bus->ops.pm_notify(codec); | ||
2239 | hda_call_codec_resume(codec); | ||
2240 | cancel_delayed_work(&codec->power_work); | ||
2241 | codec->power_transition = 0; | ||
2242 | } | ||
2243 | |||
2244 | void snd_hda_power_down(struct hda_codec *codec) | ||
2245 | { | ||
2246 | --codec->power_count; | ||
2247 | if (!codec->power_on || codec->power_count || codec->power_transition) | ||
2248 | return; | ||
2249 | if (power_save) { | ||
2250 | codec->power_transition = 1; /* avoid reentrance */ | ||
2251 | schedule_delayed_work(&codec->power_work, | ||
2252 | msecs_to_jiffies(power_save * 1000)); | ||
2253 | } | ||
2254 | } | ||
2255 | |||
2256 | int snd_hda_check_amp_list_power(struct hda_codec *codec, | ||
2257 | struct hda_loopback_check *check, | ||
2258 | hda_nid_t nid) | ||
2259 | { | ||
2260 | struct hda_amp_list *p; | ||
2261 | int ch, v; | ||
2262 | |||
2263 | if (!check->amplist) | ||
2264 | return 0; | ||
2265 | for (p = check->amplist; p->nid; p++) { | ||
2266 | if (p->nid == nid) | ||
2267 | break; | ||
2268 | } | ||
2269 | if (!p->nid) | ||
2270 | return 0; /* nothing changed */ | ||
2271 | |||
2272 | for (p = check->amplist; p->nid; p++) { | ||
2273 | for (ch = 0; ch < 2; ch++) { | ||
2274 | v = snd_hda_codec_amp_read(codec, p->nid, ch, p->dir, | ||
2275 | p->idx); | ||
2276 | if (!(v & HDA_AMP_MUTE) && v > 0) { | ||
2277 | if (!check->power_on) { | ||
2278 | check->power_on = 1; | ||
2279 | snd_hda_power_up(codec); | ||
2280 | } | ||
2281 | return 1; | ||
2282 | } | ||
2283 | } | ||
2284 | } | ||
2285 | if (check->power_on) { | ||
2286 | check->power_on = 0; | ||
2287 | snd_hda_power_down(codec); | ||
2288 | } | ||
2289 | return 0; | ||
2290 | } | ||
2291 | #endif | ||
1870 | 2292 | ||
1871 | /* | 2293 | /* |
1872 | * Channel mode helper | 2294 | * Channel mode helper |
@@ -1913,12 +2335,12 @@ int snd_hda_ch_mode_put(struct hda_codec *codec, | |||
1913 | 2335 | ||
1914 | mode = ucontrol->value.enumerated.item[0]; | 2336 | mode = ucontrol->value.enumerated.item[0]; |
1915 | snd_assert(mode < num_chmodes, return -EINVAL); | 2337 | snd_assert(mode < num_chmodes, return -EINVAL); |
1916 | if (*max_channelsp == chmode[mode].channels && !codec->in_resume) | 2338 | if (*max_channelsp == chmode[mode].channels) |
1917 | return 0; | 2339 | return 0; |
1918 | /* change the current channel setting */ | 2340 | /* change the current channel setting */ |
1919 | *max_channelsp = chmode[mode].channels; | 2341 | *max_channelsp = chmode[mode].channels; |
1920 | if (chmode[mode].sequence) | 2342 | if (chmode[mode].sequence) |
1921 | snd_hda_sequence_write(codec, chmode[mode].sequence); | 2343 | snd_hda_sequence_write_cache(codec, chmode[mode].sequence); |
1922 | return 1; | 2344 | return 1; |
1923 | } | 2345 | } |
1924 | 2346 | ||
@@ -1933,6 +2355,8 @@ int snd_hda_input_mux_info(const struct hda_input_mux *imux, | |||
1933 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 2355 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
1934 | uinfo->count = 1; | 2356 | uinfo->count = 1; |
1935 | uinfo->value.enumerated.items = imux->num_items; | 2357 | uinfo->value.enumerated.items = imux->num_items; |
2358 | if (!imux->num_items) | ||
2359 | return 0; | ||
1936 | index = uinfo->value.enumerated.item; | 2360 | index = uinfo->value.enumerated.item; |
1937 | if (index >= imux->num_items) | 2361 | if (index >= imux->num_items) |
1938 | index = imux->num_items - 1; | 2362 | index = imux->num_items - 1; |
@@ -1948,13 +2372,15 @@ int snd_hda_input_mux_put(struct hda_codec *codec, | |||
1948 | { | 2372 | { |
1949 | unsigned int idx; | 2373 | unsigned int idx; |
1950 | 2374 | ||
2375 | if (!imux->num_items) | ||
2376 | return 0; | ||
1951 | idx = ucontrol->value.enumerated.item[0]; | 2377 | idx = ucontrol->value.enumerated.item[0]; |
1952 | if (idx >= imux->num_items) | 2378 | if (idx >= imux->num_items) |
1953 | idx = imux->num_items - 1; | 2379 | idx = imux->num_items - 1; |
1954 | if (*cur_val == idx && !codec->in_resume) | 2380 | if (*cur_val == idx) |
1955 | return 0; | 2381 | return 0; |
1956 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, | 2382 | snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, |
1957 | imux->items[idx].index); | 2383 | imux->items[idx].index); |
1958 | *cur_val = idx; | 2384 | *cur_val = idx; |
1959 | return 1; | 2385 | return 1; |
1960 | } | 2386 | } |
@@ -2118,7 +2544,7 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, | |||
2118 | * Helper for automatic ping configuration | 2544 | * Helper for automatic ping configuration |
2119 | */ | 2545 | */ |
2120 | 2546 | ||
2121 | static int __devinit is_in_nid_list(hda_nid_t nid, hda_nid_t *list) | 2547 | static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list) |
2122 | { | 2548 | { |
2123 | for (; *list; list++) | 2549 | for (; *list; list++) |
2124 | if (*list == nid) | 2550 | if (*list == nid) |
@@ -2169,9 +2595,9 @@ static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences, | |||
2169 | * The digital input/output pins are assigned to dig_in_pin and dig_out_pin, | 2595 | * The digital input/output pins are assigned to dig_in_pin and dig_out_pin, |
2170 | * respectively. | 2596 | * respectively. |
2171 | */ | 2597 | */ |
2172 | int __devinit snd_hda_parse_pin_def_config(struct hda_codec *codec, | 2598 | int snd_hda_parse_pin_def_config(struct hda_codec *codec, |
2173 | struct auto_pin_cfg *cfg, | 2599 | struct auto_pin_cfg *cfg, |
2174 | hda_nid_t *ignore_nids) | 2600 | hda_nid_t *ignore_nids) |
2175 | { | 2601 | { |
2176 | hda_nid_t nid, nid_start; | 2602 | hda_nid_t nid, nid_start; |
2177 | int nodes; | 2603 | int nodes; |
@@ -2371,13 +2797,12 @@ int snd_hda_suspend(struct hda_bus *bus, pm_message_t state) | |||
2371 | { | 2797 | { |
2372 | struct hda_codec *codec; | 2798 | struct hda_codec *codec; |
2373 | 2799 | ||
2374 | /* FIXME: should handle power widget capabilities */ | ||
2375 | list_for_each_entry(codec, &bus->codec_list, list) { | 2800 | list_for_each_entry(codec, &bus->codec_list, list) { |
2376 | if (codec->patch_ops.suspend) | 2801 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
2377 | codec->patch_ops.suspend(codec, state); | 2802 | if (!codec->power_on) |
2378 | hda_set_power_state(codec, | 2803 | continue; |
2379 | codec->afg ? codec->afg : codec->mfg, | 2804 | #endif |
2380 | AC_PWRST_D3); | 2805 | hda_call_codec_suspend(codec); |
2381 | } | 2806 | } |
2382 | return 0; | 2807 | return 0; |
2383 | } | 2808 | } |
@@ -2388,76 +2813,30 @@ int snd_hda_suspend(struct hda_bus *bus, pm_message_t state) | |||
2388 | * @state: resume state | 2813 | * @state: resume state |
2389 | * | 2814 | * |
2390 | * Returns 0 if successful. | 2815 | * Returns 0 if successful. |
2816 | * | ||
2817 | * This fucntion is defined only when POWER_SAVE isn't set. | ||
2818 | * In the power-save mode, the codec is resumed dynamically. | ||
2391 | */ | 2819 | */ |
2392 | int snd_hda_resume(struct hda_bus *bus) | 2820 | int snd_hda_resume(struct hda_bus *bus) |
2393 | { | 2821 | { |
2394 | struct hda_codec *codec; | 2822 | struct hda_codec *codec; |
2395 | 2823 | ||
2396 | list_for_each_entry(codec, &bus->codec_list, list) { | 2824 | list_for_each_entry(codec, &bus->codec_list, list) { |
2397 | hda_set_power_state(codec, | 2825 | if (snd_hda_codec_needs_resume(codec)) |
2398 | codec->afg ? codec->afg : codec->mfg, | 2826 | hda_call_codec_resume(codec); |
2399 | AC_PWRST_D0); | ||
2400 | if (codec->patch_ops.resume) | ||
2401 | codec->patch_ops.resume(codec); | ||
2402 | } | 2827 | } |
2403 | return 0; | 2828 | return 0; |
2404 | } | 2829 | } |
2405 | 2830 | #ifdef CONFIG_SND_HDA_POWER_SAVE | |
2406 | /** | 2831 | int snd_hda_codecs_inuse(struct hda_bus *bus) |
2407 | * snd_hda_resume_ctls - resume controls in the new control list | ||
2408 | * @codec: the HDA codec | ||
2409 | * @knew: the array of struct snd_kcontrol_new | ||
2410 | * | ||
2411 | * This function resumes the mixer controls in the struct snd_kcontrol_new array, | ||
2412 | * originally for snd_hda_add_new_ctls(). | ||
2413 | * The array must be terminated with an empty entry as terminator. | ||
2414 | */ | ||
2415 | int snd_hda_resume_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew) | ||
2416 | { | 2832 | { |
2417 | struct snd_ctl_elem_value *val; | 2833 | struct hda_codec *codec; |
2418 | 2834 | ||
2419 | val = kmalloc(sizeof(*val), GFP_KERNEL); | 2835 | list_for_each_entry(codec, &bus->codec_list, list) { |
2420 | if (!val) | 2836 | if (snd_hda_codec_needs_resume(codec)) |
2421 | return -ENOMEM; | 2837 | return 1; |
2422 | codec->in_resume = 1; | ||
2423 | for (; knew->name; knew++) { | ||
2424 | int i, count; | ||
2425 | count = knew->count ? knew->count : 1; | ||
2426 | for (i = 0; i < count; i++) { | ||
2427 | memset(val, 0, sizeof(*val)); | ||
2428 | val->id.iface = knew->iface; | ||
2429 | val->id.device = knew->device; | ||
2430 | val->id.subdevice = knew->subdevice; | ||
2431 | strcpy(val->id.name, knew->name); | ||
2432 | val->id.index = knew->index ? knew->index : i; | ||
2433 | /* Assume that get callback reads only from cache, | ||
2434 | * not accessing to the real hardware | ||
2435 | */ | ||
2436 | if (snd_ctl_elem_read(codec->bus->card, val) < 0) | ||
2437 | continue; | ||
2438 | snd_ctl_elem_write(codec->bus->card, NULL, val); | ||
2439 | } | ||
2440 | } | 2838 | } |
2441 | codec->in_resume = 0; | ||
2442 | kfree(val); | ||
2443 | return 0; | 2839 | return 0; |
2444 | } | 2840 | } |
2445 | 2841 | #endif | |
2446 | /** | ||
2447 | * snd_hda_resume_spdif_out - resume the digital out | ||
2448 | * @codec: the HDA codec | ||
2449 | */ | ||
2450 | int snd_hda_resume_spdif_out(struct hda_codec *codec) | ||
2451 | { | ||
2452 | return snd_hda_resume_ctls(codec, dig_mixes); | ||
2453 | } | ||
2454 | |||
2455 | /** | ||
2456 | * snd_hda_resume_spdif_in - resume the digital in | ||
2457 | * @codec: the HDA codec | ||
2458 | */ | ||
2459 | int snd_hda_resume_spdif_in(struct hda_codec *codec) | ||
2460 | { | ||
2461 | return snd_hda_resume_ctls(codec, dig_in_ctls); | ||
2462 | } | ||
2463 | #endif | 2842 | #endif |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 56c26e7ccdf1..2bce925d84ef 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -24,6 +24,11 @@ | |||
24 | #include <sound/info.h> | 24 | #include <sound/info.h> |
25 | #include <sound/control.h> | 25 | #include <sound/control.h> |
26 | #include <sound/pcm.h> | 26 | #include <sound/pcm.h> |
27 | #include <sound/hwdep.h> | ||
28 | |||
29 | #if defined(CONFIG_PM) || defined(CONFIG_SND_HDA_POWER_SAVE) | ||
30 | #define SND_HDA_NEEDS_RESUME /* resume control code is required */ | ||
31 | #endif | ||
27 | 32 | ||
28 | /* | 33 | /* |
29 | * nodes | 34 | * nodes |
@@ -199,7 +204,9 @@ enum { | |||
199 | #define AC_AMPCAP_OFFSET_SHIFT 0 | 204 | #define AC_AMPCAP_OFFSET_SHIFT 0 |
200 | #define AC_AMPCAP_NUM_STEPS (0x7f<<8) /* number of steps */ | 205 | #define AC_AMPCAP_NUM_STEPS (0x7f<<8) /* number of steps */ |
201 | #define AC_AMPCAP_NUM_STEPS_SHIFT 8 | 206 | #define AC_AMPCAP_NUM_STEPS_SHIFT 8 |
202 | #define AC_AMPCAP_STEP_SIZE (0x7f<<16) /* step size 0-32dB in 0.25dB */ | 207 | #define AC_AMPCAP_STEP_SIZE (0x7f<<16) /* step size 0-32dB |
208 | * in 0.25dB | ||
209 | */ | ||
203 | #define AC_AMPCAP_STEP_SIZE_SHIFT 16 | 210 | #define AC_AMPCAP_STEP_SIZE_SHIFT 16 |
204 | #define AC_AMPCAP_MUTE (1<<31) /* mute capable */ | 211 | #define AC_AMPCAP_MUTE (1<<31) /* mute capable */ |
205 | #define AC_AMPCAP_MUTE_SHIFT 31 | 212 | #define AC_AMPCAP_MUTE_SHIFT 31 |
@@ -409,6 +416,10 @@ struct hda_bus_ops { | |||
409 | unsigned int (*get_response)(struct hda_codec *codec); | 416 | unsigned int (*get_response)(struct hda_codec *codec); |
410 | /* free the private data */ | 417 | /* free the private data */ |
411 | void (*private_free)(struct hda_bus *); | 418 | void (*private_free)(struct hda_bus *); |
419 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
420 | /* notify power-up/down from codec to contoller */ | ||
421 | void (*pm_notify)(struct hda_codec *codec); | ||
422 | #endif | ||
412 | }; | 423 | }; |
413 | 424 | ||
414 | /* template to pass to the bus constructor */ | 425 | /* template to pass to the bus constructor */ |
@@ -436,7 +447,8 @@ struct hda_bus { | |||
436 | 447 | ||
437 | /* codec linked list */ | 448 | /* codec linked list */ |
438 | struct list_head codec_list; | 449 | struct list_head codec_list; |
439 | struct hda_codec *caddr_tbl[HDA_MAX_CODEC_ADDRESS + 1]; /* caddr -> codec */ | 450 | /* link caddr -> codec */ |
451 | struct hda_codec *caddr_tbl[HDA_MAX_CODEC_ADDRESS + 1]; | ||
440 | 452 | ||
441 | struct mutex cmd_mutex; | 453 | struct mutex cmd_mutex; |
442 | 454 | ||
@@ -469,19 +481,34 @@ struct hda_codec_ops { | |||
469 | int (*init)(struct hda_codec *codec); | 481 | int (*init)(struct hda_codec *codec); |
470 | void (*free)(struct hda_codec *codec); | 482 | void (*free)(struct hda_codec *codec); |
471 | void (*unsol_event)(struct hda_codec *codec, unsigned int res); | 483 | void (*unsol_event)(struct hda_codec *codec, unsigned int res); |
472 | #ifdef CONFIG_PM | 484 | #ifdef SND_HDA_NEEDS_RESUME |
473 | int (*suspend)(struct hda_codec *codec, pm_message_t state); | 485 | int (*suspend)(struct hda_codec *codec, pm_message_t state); |
474 | int (*resume)(struct hda_codec *codec); | 486 | int (*resume)(struct hda_codec *codec); |
475 | #endif | 487 | #endif |
488 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
489 | int (*check_power_status)(struct hda_codec *codec, hda_nid_t nid); | ||
490 | #endif | ||
476 | }; | 491 | }; |
477 | 492 | ||
478 | /* record for amp information cache */ | 493 | /* record for amp information cache */ |
479 | struct hda_amp_info { | 494 | struct hda_cache_head { |
480 | u32 key; /* hash key */ | 495 | u32 key; /* hash key */ |
496 | u16 val; /* assigned value */ | ||
497 | u16 next; /* next link; -1 = terminal */ | ||
498 | }; | ||
499 | |||
500 | struct hda_amp_info { | ||
501 | struct hda_cache_head head; | ||
481 | u32 amp_caps; /* amp capabilities */ | 502 | u32 amp_caps; /* amp capabilities */ |
482 | u16 vol[2]; /* current volume & mute */ | 503 | u16 vol[2]; /* current volume & mute */ |
483 | u16 status; /* update flag */ | 504 | }; |
484 | u16 next; /* next link */ | 505 | |
506 | struct hda_cache_rec { | ||
507 | u16 hash[64]; /* hash table for index */ | ||
508 | unsigned int num_entries; /* number of assigned entries */ | ||
509 | unsigned int size; /* allocated size */ | ||
510 | unsigned int record_size; /* record size (including header) */ | ||
511 | void *buffer; /* hash table entries */ | ||
485 | }; | 512 | }; |
486 | 513 | ||
487 | /* PCM callbacks */ | 514 | /* PCM callbacks */ |
@@ -499,7 +526,7 @@ struct hda_pcm_ops { | |||
499 | 526 | ||
500 | /* PCM information for each substream */ | 527 | /* PCM information for each substream */ |
501 | struct hda_pcm_stream { | 528 | struct hda_pcm_stream { |
502 | unsigned int substreams; /* number of substreams, 0 = not exist */ | 529 | unsigned int substreams; /* number of substreams, 0 = not exist*/ |
503 | unsigned int channels_min; /* min. number of channels */ | 530 | unsigned int channels_min; /* min. number of channels */ |
504 | unsigned int channels_max; /* max. number of channels */ | 531 | unsigned int channels_max; /* max. number of channels */ |
505 | hda_nid_t nid; /* default NID to query rates/formats/bps, or set up */ | 532 | hda_nid_t nid; /* default NID to query rates/formats/bps, or set up */ |
@@ -536,11 +563,6 @@ struct hda_codec { | |||
536 | /* set by patch */ | 563 | /* set by patch */ |
537 | struct hda_codec_ops patch_ops; | 564 | struct hda_codec_ops patch_ops; |
538 | 565 | ||
539 | /* resume phase - all controls should update even if | ||
540 | * the values are not changed | ||
541 | */ | ||
542 | unsigned int in_resume; | ||
543 | |||
544 | /* PCM to create, set by patch_ops.build_pcms callback */ | 566 | /* PCM to create, set by patch_ops.build_pcms callback */ |
545 | unsigned int num_pcms; | 567 | unsigned int num_pcms; |
546 | struct hda_pcm *pcm_info; | 568 | struct hda_pcm *pcm_info; |
@@ -553,16 +575,22 @@ struct hda_codec { | |||
553 | hda_nid_t start_nid; | 575 | hda_nid_t start_nid; |
554 | u32 *wcaps; | 576 | u32 *wcaps; |
555 | 577 | ||
556 | /* hash for amp access */ | 578 | struct hda_cache_rec amp_cache; /* cache for amp access */ |
557 | u16 amp_hash[32]; | 579 | struct hda_cache_rec cmd_cache; /* cache for other commands */ |
558 | int num_amp_entries; | ||
559 | int amp_info_size; | ||
560 | struct hda_amp_info *amp_info; | ||
561 | 580 | ||
562 | struct mutex spdif_mutex; | 581 | struct mutex spdif_mutex; |
563 | unsigned int spdif_status; /* IEC958 status bits */ | 582 | unsigned int spdif_status; /* IEC958 status bits */ |
564 | unsigned short spdif_ctls; /* SPDIF control bits */ | 583 | unsigned short spdif_ctls; /* SPDIF control bits */ |
565 | unsigned int spdif_in_enable; /* SPDIF input enable? */ | 584 | unsigned int spdif_in_enable; /* SPDIF input enable? */ |
585 | |||
586 | struct snd_hwdep *hwdep; /* assigned hwdep device */ | ||
587 | |||
588 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
589 | unsigned int power_on :1; /* current (global) power-state */ | ||
590 | unsigned int power_transition :1; /* power-state in transition */ | ||
591 | int power_count; /* current (global) power refcount */ | ||
592 | struct delayed_work power_work; /* delayed task for powerdown */ | ||
593 | #endif | ||
566 | }; | 594 | }; |
567 | 595 | ||
568 | /* direction */ | 596 | /* direction */ |
@@ -582,13 +610,17 @@ int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, | |||
582 | /* | 610 | /* |
583 | * low level functions | 611 | * low level functions |
584 | */ | 612 | */ |
585 | unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, int direct, | 613 | unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, |
614 | int direct, | ||
586 | unsigned int verb, unsigned int parm); | 615 | unsigned int verb, unsigned int parm); |
587 | int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct, | 616 | int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct, |
588 | unsigned int verb, unsigned int parm); | 617 | unsigned int verb, unsigned int parm); |
589 | #define snd_hda_param_read(codec, nid, param) snd_hda_codec_read(codec, nid, 0, AC_VERB_PARAMETERS, param) | 618 | #define snd_hda_param_read(codec, nid, param) \ |
590 | int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid, hda_nid_t *start_id); | 619 | snd_hda_codec_read(codec, nid, 0, AC_VERB_PARAMETERS, param) |
591 | int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid, hda_nid_t *conn_list, int max_conns); | 620 | int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid, |
621 | hda_nid_t *start_id); | ||
622 | int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid, | ||
623 | hda_nid_t *conn_list, int max_conns); | ||
592 | 624 | ||
593 | struct hda_verb { | 625 | struct hda_verb { |
594 | hda_nid_t nid; | 626 | hda_nid_t nid; |
@@ -596,11 +628,24 @@ struct hda_verb { | |||
596 | u32 param; | 628 | u32 param; |
597 | }; | 629 | }; |
598 | 630 | ||
599 | void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq); | 631 | void snd_hda_sequence_write(struct hda_codec *codec, |
632 | const struct hda_verb *seq); | ||
600 | 633 | ||
601 | /* unsolicited event */ | 634 | /* unsolicited event */ |
602 | int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex); | 635 | int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex); |
603 | 636 | ||
637 | /* cached write */ | ||
638 | #ifdef SND_HDA_NEEDS_RESUME | ||
639 | int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, | ||
640 | int direct, unsigned int verb, unsigned int parm); | ||
641 | void snd_hda_sequence_write_cache(struct hda_codec *codec, | ||
642 | const struct hda_verb *seq); | ||
643 | void snd_hda_codec_resume_cache(struct hda_codec *codec); | ||
644 | #else | ||
645 | #define snd_hda_codec_write_cache snd_hda_codec_write | ||
646 | #define snd_hda_sequence_write_cache snd_hda_sequence_write | ||
647 | #endif | ||
648 | |||
604 | /* | 649 | /* |
605 | * Mixer | 650 | * Mixer |
606 | */ | 651 | */ |
@@ -610,10 +655,13 @@ int snd_hda_build_controls(struct hda_bus *bus); | |||
610 | * PCM | 655 | * PCM |
611 | */ | 656 | */ |
612 | int snd_hda_build_pcms(struct hda_bus *bus); | 657 | int snd_hda_build_pcms(struct hda_bus *bus); |
613 | void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, u32 stream_tag, | 658 | void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, |
659 | u32 stream_tag, | ||
614 | int channel_id, int format); | 660 | int channel_id, int format); |
615 | unsigned int snd_hda_calc_stream_format(unsigned int rate, unsigned int channels, | 661 | unsigned int snd_hda_calc_stream_format(unsigned int rate, |
616 | unsigned int format, unsigned int maxbps); | 662 | unsigned int channels, |
663 | unsigned int format, | ||
664 | unsigned int maxbps); | ||
617 | int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, | 665 | int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, |
618 | u32 *ratesp, u64 *formatsp, unsigned int *bpsp); | 666 | u32 *ratesp, u64 *formatsp, unsigned int *bpsp); |
619 | int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid, | 667 | int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid, |
@@ -632,4 +680,19 @@ int snd_hda_suspend(struct hda_bus *bus, pm_message_t state); | |||
632 | int snd_hda_resume(struct hda_bus *bus); | 680 | int snd_hda_resume(struct hda_bus *bus); |
633 | #endif | 681 | #endif |
634 | 682 | ||
683 | /* | ||
684 | * power saving | ||
685 | */ | ||
686 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
687 | void snd_hda_power_up(struct hda_codec *codec); | ||
688 | void snd_hda_power_down(struct hda_codec *codec); | ||
689 | #define snd_hda_codec_needs_resume(codec) codec->power_count | ||
690 | int snd_hda_codecs_inuse(struct hda_bus *bus); | ||
691 | #else | ||
692 | static inline void snd_hda_power_up(struct hda_codec *codec) {} | ||
693 | static inline void snd_hda_power_down(struct hda_codec *codec) {} | ||
694 | #define snd_hda_codec_needs_resume(codec) 1 | ||
695 | #define snd_hda_codecs_inuse(bus) 1 | ||
696 | #endif | ||
697 | |||
635 | #endif /* __SOUND_HDA_CODEC_H */ | 698 | #endif /* __SOUND_HDA_CODEC_H */ |
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 000287f7da43..c957eb58de5c 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c | |||
@@ -70,6 +70,13 @@ struct hda_gspec { | |||
70 | struct hda_pcm pcm_rec; /* PCM information */ | 70 | struct hda_pcm pcm_rec; /* PCM information */ |
71 | 71 | ||
72 | struct list_head nid_list; /* list of widgets */ | 72 | struct list_head nid_list; /* list of widgets */ |
73 | |||
74 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
75 | #define MAX_LOOPBACK_AMPS 7 | ||
76 | struct hda_loopback_check loopback; | ||
77 | int num_loopbacks; | ||
78 | struct hda_amp_list loopback_list[MAX_LOOPBACK_AMPS + 1]; | ||
79 | #endif | ||
73 | }; | 80 | }; |
74 | 81 | ||
75 | /* | 82 | /* |
@@ -88,13 +95,12 @@ struct hda_gspec { | |||
88 | static void snd_hda_generic_free(struct hda_codec *codec) | 95 | static void snd_hda_generic_free(struct hda_codec *codec) |
89 | { | 96 | { |
90 | struct hda_gspec *spec = codec->spec; | 97 | struct hda_gspec *spec = codec->spec; |
91 | struct list_head *p, *n; | 98 | struct hda_gnode *node, *n; |
92 | 99 | ||
93 | if (! spec) | 100 | if (! spec) |
94 | return; | 101 | return; |
95 | /* free all widgets */ | 102 | /* free all widgets */ |
96 | list_for_each_safe(p, n, &spec->nid_list) { | 103 | list_for_each_entry_safe(node, n, &spec->nid_list, list) { |
97 | struct hda_gnode *node = list_entry(p, struct hda_gnode, list); | ||
98 | if (node->conn_list != node->slist) | 104 | if (node->conn_list != node->slist) |
99 | kfree(node->conn_list); | 105 | kfree(node->conn_list); |
100 | kfree(node); | 106 | kfree(node); |
@@ -196,11 +202,9 @@ static int build_afg_tree(struct hda_codec *codec) | |||
196 | /* FIXME: should avoid the braindead linear search */ | 202 | /* FIXME: should avoid the braindead linear search */ |
197 | static struct hda_gnode *hda_get_node(struct hda_gspec *spec, hda_nid_t nid) | 203 | static struct hda_gnode *hda_get_node(struct hda_gspec *spec, hda_nid_t nid) |
198 | { | 204 | { |
199 | struct list_head *p; | ||
200 | struct hda_gnode *node; | 205 | struct hda_gnode *node; |
201 | 206 | ||
202 | list_for_each(p, &spec->nid_list) { | 207 | list_for_each_entry(node, &spec->nid_list, list) { |
203 | node = list_entry(p, struct hda_gnode, list); | ||
204 | if (node->nid == nid) | 208 | if (node->nid == nid) |
205 | return node; | 209 | return node; |
206 | } | 210 | } |
@@ -218,9 +222,8 @@ static int unmute_output(struct hda_codec *codec, struct hda_gnode *node) | |||
218 | ofs = (node->amp_out_caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT; | 222 | ofs = (node->amp_out_caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT; |
219 | if (val >= ofs) | 223 | if (val >= ofs) |
220 | val -= ofs; | 224 | val -= ofs; |
221 | val |= AC_AMP_SET_LEFT | AC_AMP_SET_RIGHT; | 225 | snd_hda_codec_amp_stereo(codec, node->nid, HDA_OUTPUT, 0, 0xff, val); |
222 | val |= AC_AMP_SET_OUTPUT; | 226 | return 0; |
223 | return snd_hda_codec_write(codec, node->nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, val); | ||
224 | } | 227 | } |
225 | 228 | ||
226 | /* | 229 | /* |
@@ -234,11 +237,8 @@ static int unmute_input(struct hda_codec *codec, struct hda_gnode *node, unsigne | |||
234 | ofs = (node->amp_in_caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT; | 237 | ofs = (node->amp_in_caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT; |
235 | if (val >= ofs) | 238 | if (val >= ofs) |
236 | val -= ofs; | 239 | val -= ofs; |
237 | val |= AC_AMP_SET_LEFT | AC_AMP_SET_RIGHT; | 240 | snd_hda_codec_amp_stereo(codec, node->nid, HDA_INPUT, index, 0xff, val); |
238 | val |= AC_AMP_SET_INPUT; | 241 | return 0; |
239 | // awk added - fixed to allow unmuting of indexed amps | ||
240 | val |= index << AC_AMP_SET_INDEX_SHIFT; | ||
241 | return snd_hda_codec_write(codec, node->nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, val); | ||
242 | } | 242 | } |
243 | 243 | ||
244 | /* | 244 | /* |
@@ -248,7 +248,8 @@ static int select_input_connection(struct hda_codec *codec, struct hda_gnode *no | |||
248 | unsigned int index) | 248 | unsigned int index) |
249 | { | 249 | { |
250 | snd_printdd("CONNECT: NID=0x%x IDX=0x%x\n", node->nid, index); | 250 | snd_printdd("CONNECT: NID=0x%x IDX=0x%x\n", node->nid, index); |
251 | return snd_hda_codec_write(codec, node->nid, 0, AC_VERB_SET_CONNECT_SEL, index); | 251 | return snd_hda_codec_write_cache(codec, node->nid, 0, |
252 | AC_VERB_SET_CONNECT_SEL, index); | ||
252 | } | 253 | } |
253 | 254 | ||
254 | /* | 255 | /* |
@@ -256,11 +257,9 @@ static int select_input_connection(struct hda_codec *codec, struct hda_gnode *no | |||
256 | */ | 257 | */ |
257 | static void clear_check_flags(struct hda_gspec *spec) | 258 | static void clear_check_flags(struct hda_gspec *spec) |
258 | { | 259 | { |
259 | struct list_head *p; | ||
260 | struct hda_gnode *node; | 260 | struct hda_gnode *node; |
261 | 261 | ||
262 | list_for_each(p, &spec->nid_list) { | 262 | list_for_each_entry(node, &spec->nid_list, list) { |
263 | node = list_entry(p, struct hda_gnode, list); | ||
264 | node->checked = 0; | 263 | node->checked = 0; |
265 | } | 264 | } |
266 | } | 265 | } |
@@ -343,12 +342,10 @@ static struct hda_gnode *parse_output_jack(struct hda_codec *codec, | |||
343 | struct hda_gspec *spec, | 342 | struct hda_gspec *spec, |
344 | int jack_type) | 343 | int jack_type) |
345 | { | 344 | { |
346 | struct list_head *p; | ||
347 | struct hda_gnode *node; | 345 | struct hda_gnode *node; |
348 | int err; | 346 | int err; |
349 | 347 | ||
350 | list_for_each(p, &spec->nid_list) { | 348 | list_for_each_entry(node, &spec->nid_list, list) { |
351 | node = list_entry(p, struct hda_gnode, list); | ||
352 | if (node->type != AC_WID_PIN) | 349 | if (node->type != AC_WID_PIN) |
353 | continue; | 350 | continue; |
354 | /* output capable? */ | 351 | /* output capable? */ |
@@ -379,7 +376,7 @@ static struct hda_gnode *parse_output_jack(struct hda_codec *codec, | |||
379 | /* unmute the PIN output */ | 376 | /* unmute the PIN output */ |
380 | unmute_output(codec, node); | 377 | unmute_output(codec, node); |
381 | /* set PIN-Out enable */ | 378 | /* set PIN-Out enable */ |
382 | snd_hda_codec_write(codec, node->nid, 0, | 379 | snd_hda_codec_write_cache(codec, node->nid, 0, |
383 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 380 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
384 | AC_PINCTL_OUT_EN | | 381 | AC_PINCTL_OUT_EN | |
385 | ((node->pin_caps & AC_PINCAP_HP_DRV) ? | 382 | ((node->pin_caps & AC_PINCAP_HP_DRV) ? |
@@ -570,7 +567,8 @@ static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec, | |||
570 | /* unmute the PIN external input */ | 567 | /* unmute the PIN external input */ |
571 | unmute_input(codec, node, 0); /* index = 0? */ | 568 | unmute_input(codec, node, 0); /* index = 0? */ |
572 | /* set PIN-In enable */ | 569 | /* set PIN-In enable */ |
573 | snd_hda_codec_write(codec, node->nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pinctl); | 570 | snd_hda_codec_write_cache(codec, node->nid, 0, |
571 | AC_VERB_SET_PIN_WIDGET_CONTROL, pinctl); | ||
574 | 572 | ||
575 | return 1; /* found */ | 573 | return 1; /* found */ |
576 | } | 574 | } |
@@ -659,7 +657,6 @@ static int parse_input_path(struct hda_codec *codec, struct hda_gnode *adc_node) | |||
659 | static int parse_input(struct hda_codec *codec) | 657 | static int parse_input(struct hda_codec *codec) |
660 | { | 658 | { |
661 | struct hda_gspec *spec = codec->spec; | 659 | struct hda_gspec *spec = codec->spec; |
662 | struct list_head *p; | ||
663 | struct hda_gnode *node; | 660 | struct hda_gnode *node; |
664 | int err; | 661 | int err; |
665 | 662 | ||
@@ -668,8 +665,7 @@ static int parse_input(struct hda_codec *codec) | |||
668 | * If it reaches to certain input PINs, we take it as the | 665 | * If it reaches to certain input PINs, we take it as the |
669 | * input path. | 666 | * input path. |
670 | */ | 667 | */ |
671 | list_for_each(p, &spec->nid_list) { | 668 | list_for_each_entry(node, &spec->nid_list, list) { |
672 | node = list_entry(p, struct hda_gnode, list); | ||
673 | if (node->wid_caps & AC_WCAP_DIGITAL) | 669 | if (node->wid_caps & AC_WCAP_DIGITAL) |
674 | continue; /* skip SPDIF */ | 670 | continue; /* skip SPDIF */ |
675 | if (node->type == AC_WID_AUD_IN) { | 671 | if (node->type == AC_WID_AUD_IN) { |
@@ -684,11 +680,33 @@ static int parse_input(struct hda_codec *codec) | |||
684 | return 0; | 680 | return 0; |
685 | } | 681 | } |
686 | 682 | ||
683 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
684 | static void add_input_loopback(struct hda_codec *codec, hda_nid_t nid, | ||
685 | int dir, int idx) | ||
686 | { | ||
687 | struct hda_gspec *spec = codec->spec; | ||
688 | struct hda_amp_list *p; | ||
689 | |||
690 | if (spec->num_loopbacks >= MAX_LOOPBACK_AMPS) { | ||
691 | snd_printk(KERN_ERR "hda_generic: Too many loopback ctls\n"); | ||
692 | return; | ||
693 | } | ||
694 | p = &spec->loopback_list[spec->num_loopbacks++]; | ||
695 | p->nid = nid; | ||
696 | p->dir = dir; | ||
697 | p->idx = idx; | ||
698 | spec->loopback.amplist = spec->loopback_list; | ||
699 | } | ||
700 | #else | ||
701 | #define add_input_loopback(codec,nid,dir,idx) | ||
702 | #endif | ||
703 | |||
687 | /* | 704 | /* |
688 | * create mixer controls if possible | 705 | * create mixer controls if possible |
689 | */ | 706 | */ |
690 | static int create_mixer(struct hda_codec *codec, struct hda_gnode *node, | 707 | static int create_mixer(struct hda_codec *codec, struct hda_gnode *node, |
691 | unsigned int index, const char *type, const char *dir_sfx) | 708 | unsigned int index, const char *type, |
709 | const char *dir_sfx, int is_loopback) | ||
692 | { | 710 | { |
693 | char name[32]; | 711 | char name[32]; |
694 | int err; | 712 | int err; |
@@ -702,6 +720,8 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node, | |||
702 | if ((node->wid_caps & AC_WCAP_IN_AMP) && | 720 | if ((node->wid_caps & AC_WCAP_IN_AMP) && |
703 | (node->amp_in_caps & AC_AMPCAP_MUTE)) { | 721 | (node->amp_in_caps & AC_AMPCAP_MUTE)) { |
704 | knew = (struct snd_kcontrol_new)HDA_CODEC_MUTE(name, node->nid, index, HDA_INPUT); | 722 | knew = (struct snd_kcontrol_new)HDA_CODEC_MUTE(name, node->nid, index, HDA_INPUT); |
723 | if (is_loopback) | ||
724 | add_input_loopback(codec, node->nid, HDA_INPUT, index); | ||
705 | snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index); | 725 | snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index); |
706 | if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0) | 726 | if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0) |
707 | return err; | 727 | return err; |
@@ -709,6 +729,8 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node, | |||
709 | } else if ((node->wid_caps & AC_WCAP_OUT_AMP) && | 729 | } else if ((node->wid_caps & AC_WCAP_OUT_AMP) && |
710 | (node->amp_out_caps & AC_AMPCAP_MUTE)) { | 730 | (node->amp_out_caps & AC_AMPCAP_MUTE)) { |
711 | knew = (struct snd_kcontrol_new)HDA_CODEC_MUTE(name, node->nid, 0, HDA_OUTPUT); | 731 | knew = (struct snd_kcontrol_new)HDA_CODEC_MUTE(name, node->nid, 0, HDA_OUTPUT); |
732 | if (is_loopback) | ||
733 | add_input_loopback(codec, node->nid, HDA_OUTPUT, 0); | ||
712 | snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid); | 734 | snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid); |
713 | if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0) | 735 | if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0) |
714 | return err; | 736 | return err; |
@@ -767,7 +789,7 @@ static int create_output_mixers(struct hda_codec *codec, const char **names) | |||
767 | for (i = 0; i < spec->pcm_vol_nodes; i++) { | 789 | for (i = 0; i < spec->pcm_vol_nodes; i++) { |
768 | err = create_mixer(codec, spec->pcm_vol[i].node, | 790 | err = create_mixer(codec, spec->pcm_vol[i].node, |
769 | spec->pcm_vol[i].index, | 791 | spec->pcm_vol[i].index, |
770 | names[i], "Playback"); | 792 | names[i], "Playback", 0); |
771 | if (err < 0) | 793 | if (err < 0) |
772 | return err; | 794 | return err; |
773 | } | 795 | } |
@@ -784,7 +806,7 @@ static int build_output_controls(struct hda_codec *codec) | |||
784 | case 1: | 806 | case 1: |
785 | return create_mixer(codec, spec->pcm_vol[0].node, | 807 | return create_mixer(codec, spec->pcm_vol[0].node, |
786 | spec->pcm_vol[0].index, | 808 | spec->pcm_vol[0].index, |
787 | "Master", "Playback"); | 809 | "Master", "Playback", 0); |
788 | case 2: | 810 | case 2: |
789 | if (defcfg_type(spec->out_pin_node[0]) == AC_JACK_SPEAKER) | 811 | if (defcfg_type(spec->out_pin_node[0]) == AC_JACK_SPEAKER) |
790 | return create_output_mixers(codec, types_speaker); | 812 | return create_output_mixers(codec, types_speaker); |
@@ -820,7 +842,7 @@ static int build_input_controls(struct hda_codec *codec) | |||
820 | if (spec->input_mux.num_items == 1) { | 842 | if (spec->input_mux.num_items == 1) { |
821 | err = create_mixer(codec, adc_node, | 843 | err = create_mixer(codec, adc_node, |
822 | spec->input_mux.items[0].index, | 844 | spec->input_mux.items[0].index, |
823 | NULL, "Capture"); | 845 | NULL, "Capture", 0); |
824 | if (err < 0) | 846 | if (err < 0) |
825 | return err; | 847 | return err; |
826 | return 0; | 848 | return 0; |
@@ -886,7 +908,8 @@ static int parse_loopback_path(struct hda_codec *codec, struct hda_gspec *spec, | |||
886 | return err; | 908 | return err; |
887 | else if (err >= 1) { | 909 | else if (err >= 1) { |
888 | if (err == 1) { | 910 | if (err == 1) { |
889 | err = create_mixer(codec, node, i, type, "Playback"); | 911 | err = create_mixer(codec, node, i, type, |
912 | "Playback", 1); | ||
890 | if (err < 0) | 913 | if (err < 0) |
891 | return err; | 914 | return err; |
892 | if (err > 0) | 915 | if (err > 0) |
@@ -911,7 +934,6 @@ static int parse_loopback_path(struct hda_codec *codec, struct hda_gspec *spec, | |||
911 | static int build_loopback_controls(struct hda_codec *codec) | 934 | static int build_loopback_controls(struct hda_codec *codec) |
912 | { | 935 | { |
913 | struct hda_gspec *spec = codec->spec; | 936 | struct hda_gspec *spec = codec->spec; |
914 | struct list_head *p; | ||
915 | struct hda_gnode *node; | 937 | struct hda_gnode *node; |
916 | int err; | 938 | int err; |
917 | const char *type; | 939 | const char *type; |
@@ -919,8 +941,7 @@ static int build_loopback_controls(struct hda_codec *codec) | |||
919 | if (! spec->out_pin_node[0]) | 941 | if (! spec->out_pin_node[0]) |
920 | return 0; | 942 | return 0; |
921 | 943 | ||
922 | list_for_each(p, &spec->nid_list) { | 944 | list_for_each_entry(node, &spec->nid_list, list) { |
923 | node = list_entry(p, struct hda_gnode, list); | ||
924 | if (node->type != AC_WID_PIN) | 945 | if (node->type != AC_WID_PIN) |
925 | continue; | 946 | continue; |
926 | /* input capable? */ | 947 | /* input capable? */ |
@@ -1022,6 +1043,14 @@ static int build_generic_pcms(struct hda_codec *codec) | |||
1022 | return 0; | 1043 | return 0; |
1023 | } | 1044 | } |
1024 | 1045 | ||
1046 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1047 | static int generic_check_power_status(struct hda_codec *codec, hda_nid_t nid) | ||
1048 | { | ||
1049 | struct hda_gspec *spec = codec->spec; | ||
1050 | return snd_hda_check_amp_list_power(codec, &spec->loopback, nid); | ||
1051 | } | ||
1052 | #endif | ||
1053 | |||
1025 | 1054 | ||
1026 | /* | 1055 | /* |
1027 | */ | 1056 | */ |
@@ -1029,6 +1058,9 @@ static struct hda_codec_ops generic_patch_ops = { | |||
1029 | .build_controls = build_generic_controls, | 1058 | .build_controls = build_generic_controls, |
1030 | .build_pcms = build_generic_pcms, | 1059 | .build_pcms = build_generic_pcms, |
1031 | .free = snd_hda_generic_free, | 1060 | .free = snd_hda_generic_free, |
1061 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1062 | .check_power_status = generic_check_power_status, | ||
1063 | #endif | ||
1032 | }; | 1064 | }; |
1033 | 1065 | ||
1034 | /* | 1066 | /* |
diff --git a/sound/pci/hda/hda_hwdep.c b/sound/pci/hda/hda_hwdep.c new file mode 100644 index 000000000000..bafb7b01f5a1 --- /dev/null +++ b/sound/pci/hda/hda_hwdep.c | |||
@@ -0,0 +1,122 @@ | |||
1 | /* | ||
2 | * HWDEP Interface for HD-audio codec | ||
3 | * | ||
4 | * Copyright (c) 2007 Takashi Iwai <tiwai@suse.de> | ||
5 | * | ||
6 | * This driver is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This driver is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include <sound/driver.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/pci.h> | ||
25 | #include <linux/compat.h> | ||
26 | #include <linux/mutex.h> | ||
27 | #include <sound/core.h> | ||
28 | #include "hda_codec.h" | ||
29 | #include "hda_local.h" | ||
30 | #include <sound/hda_hwdep.h> | ||
31 | |||
32 | /* | ||
33 | * write/read an out-of-bound verb | ||
34 | */ | ||
35 | static int verb_write_ioctl(struct hda_codec *codec, | ||
36 | struct hda_verb_ioctl __user *arg) | ||
37 | { | ||
38 | u32 verb, res; | ||
39 | |||
40 | if (get_user(verb, &arg->verb)) | ||
41 | return -EFAULT; | ||
42 | res = snd_hda_codec_read(codec, verb >> 24, 0, | ||
43 | (verb >> 8) & 0xffff, verb & 0xff); | ||
44 | if (put_user(res, &arg->res)) | ||
45 | return -EFAULT; | ||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | static int get_wcap_ioctl(struct hda_codec *codec, | ||
50 | struct hda_verb_ioctl __user *arg) | ||
51 | { | ||
52 | u32 verb, res; | ||
53 | |||
54 | if (get_user(verb, &arg->verb)) | ||
55 | return -EFAULT; | ||
56 | res = get_wcaps(codec, verb >> 24); | ||
57 | if (put_user(res, &arg->res)) | ||
58 | return -EFAULT; | ||
59 | return 0; | ||
60 | } | ||
61 | |||
62 | |||
63 | /* | ||
64 | */ | ||
65 | static int hda_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, | ||
66 | unsigned int cmd, unsigned long arg) | ||
67 | { | ||
68 | struct hda_codec *codec = hw->private_data; | ||
69 | void __user *argp = (void __user *)arg; | ||
70 | |||
71 | switch (cmd) { | ||
72 | case HDA_IOCTL_PVERSION: | ||
73 | return put_user(HDA_HWDEP_VERSION, (int __user *)argp); | ||
74 | case HDA_IOCTL_VERB_WRITE: | ||
75 | return verb_write_ioctl(codec, argp); | ||
76 | case HDA_IOCTL_GET_WCAP: | ||
77 | return get_wcap_ioctl(codec, argp); | ||
78 | } | ||
79 | return -ENOIOCTLCMD; | ||
80 | } | ||
81 | |||
82 | #ifdef CONFIG_COMPAT | ||
83 | static int hda_hwdep_ioctl_compat(struct snd_hwdep *hw, struct file *file, | ||
84 | unsigned int cmd, unsigned long arg) | ||
85 | { | ||
86 | return hda_hwdep_ioctl(hw, file, cmd, (unsigned long)compat_ptr(arg)); | ||
87 | } | ||
88 | #endif | ||
89 | |||
90 | static int hda_hwdep_open(struct snd_hwdep *hw, struct file *file) | ||
91 | { | ||
92 | #ifndef CONFIG_SND_DEBUG_DETECT | ||
93 | if (!capable(CAP_SYS_RAWIO)) | ||
94 | return -EACCES; | ||
95 | #endif | ||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | int __devinit snd_hda_create_hwdep(struct hda_codec *codec) | ||
100 | { | ||
101 | char hwname[16]; | ||
102 | struct snd_hwdep *hwdep; | ||
103 | int err; | ||
104 | |||
105 | sprintf(hwname, "HDA Codec %d", codec->addr); | ||
106 | err = snd_hwdep_new(codec->bus->card, hwname, codec->addr, &hwdep); | ||
107 | if (err < 0) | ||
108 | return err; | ||
109 | codec->hwdep = hwdep; | ||
110 | sprintf(hwdep->name, "HDA Codec %d", codec->addr); | ||
111 | hwdep->iface = SNDRV_HWDEP_IFACE_HDA; | ||
112 | hwdep->private_data = codec; | ||
113 | hwdep->exclusive = 1; | ||
114 | |||
115 | hwdep->ops.open = hda_hwdep_open; | ||
116 | hwdep->ops.ioctl = hda_hwdep_ioctl; | ||
117 | #ifdef CONFIG_COMPAT | ||
118 | hwdep->ops.ioctl_compat = hda_hwdep_ioctl_compat; | ||
119 | #endif | ||
120 | |||
121 | return 0; | ||
122 | } | ||
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 92bc8b3fa2a0..3fa0f9704909 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -1,6 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * | 2 | * |
3 | * hda_intel.c - Implementation of primary alsa driver code base for Intel HD Audio. | 3 | * hda_intel.c - Implementation of primary alsa driver code base |
4 | * for Intel HD Audio. | ||
4 | * | 5 | * |
5 | * Copyright(c) 2004 Intel Corporation. All rights reserved. | 6 | * Copyright(c) 2004 Intel Corporation. All rights reserved. |
6 | * | 7 | * |
@@ -64,14 +65,27 @@ MODULE_PARM_DESC(id, "ID string for Intel HD audio interface."); | |||
64 | module_param(model, charp, 0444); | 65 | module_param(model, charp, 0444); |
65 | MODULE_PARM_DESC(model, "Use the given board model."); | 66 | MODULE_PARM_DESC(model, "Use the given board model."); |
66 | module_param(position_fix, int, 0444); | 67 | module_param(position_fix, int, 0444); |
67 | MODULE_PARM_DESC(position_fix, "Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size)."); | 68 | MODULE_PARM_DESC(position_fix, "Fix DMA pointer " |
69 | "(0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size)."); | ||
68 | module_param(probe_mask, int, 0444); | 70 | module_param(probe_mask, int, 0444); |
69 | MODULE_PARM_DESC(probe_mask, "Bitmask to probe codecs (default = -1)."); | 71 | MODULE_PARM_DESC(probe_mask, "Bitmask to probe codecs (default = -1)."); |
70 | module_param(single_cmd, bool, 0444); | 72 | module_param(single_cmd, bool, 0444); |
71 | MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs (for debugging only)."); | 73 | MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs " |
74 | "(for debugging only)."); | ||
72 | module_param(enable_msi, int, 0); | 75 | module_param(enable_msi, int, 0); |
73 | MODULE_PARM_DESC(enable_msi, "Enable Message Signaled Interrupt (MSI)"); | 76 | MODULE_PARM_DESC(enable_msi, "Enable Message Signaled Interrupt (MSI)"); |
74 | 77 | ||
78 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
79 | /* power_save option is defined in hda_codec.c */ | ||
80 | |||
81 | /* reset the HD-audio controller in power save mode. | ||
82 | * this may give more power-saving, but will take longer time to | ||
83 | * wake up. | ||
84 | */ | ||
85 | static int power_save_controller = 1; | ||
86 | module_param(power_save_controller, bool, 0644); | ||
87 | MODULE_PARM_DESC(power_save_controller, "Reset controller in power save mode."); | ||
88 | #endif | ||
75 | 89 | ||
76 | /* just for backward compatibility */ | 90 | /* just for backward compatibility */ |
77 | static int enable; | 91 | static int enable; |
@@ -98,6 +112,7 @@ MODULE_DESCRIPTION("Intel HDA driver"); | |||
98 | 112 | ||
99 | #define SFX "hda-intel: " | 113 | #define SFX "hda-intel: " |
100 | 114 | ||
115 | |||
101 | /* | 116 | /* |
102 | * registers | 117 | * registers |
103 | */ | 118 | */ |
@@ -213,15 +228,16 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; | |||
213 | #define SD_INT_DESC_ERR 0x10 /* descriptor error interrupt */ | 228 | #define SD_INT_DESC_ERR 0x10 /* descriptor error interrupt */ |
214 | #define SD_INT_FIFO_ERR 0x08 /* FIFO error interrupt */ | 229 | #define SD_INT_FIFO_ERR 0x08 /* FIFO error interrupt */ |
215 | #define SD_INT_COMPLETE 0x04 /* completion interrupt */ | 230 | #define SD_INT_COMPLETE 0x04 /* completion interrupt */ |
216 | #define SD_INT_MASK (SD_INT_DESC_ERR|SD_INT_FIFO_ERR|SD_INT_COMPLETE) | 231 | #define SD_INT_MASK (SD_INT_DESC_ERR|SD_INT_FIFO_ERR|\ |
232 | SD_INT_COMPLETE) | ||
217 | 233 | ||
218 | /* SD_STS */ | 234 | /* SD_STS */ |
219 | #define SD_STS_FIFO_READY 0x20 /* FIFO ready */ | 235 | #define SD_STS_FIFO_READY 0x20 /* FIFO ready */ |
220 | 236 | ||
221 | /* INTCTL and INTSTS */ | 237 | /* INTCTL and INTSTS */ |
222 | #define ICH6_INT_ALL_STREAM 0xff /* all stream interrupts */ | 238 | #define ICH6_INT_ALL_STREAM 0xff /* all stream interrupts */ |
223 | #define ICH6_INT_CTRL_EN 0x40000000 /* controller interrupt enable bit */ | 239 | #define ICH6_INT_CTRL_EN 0x40000000 /* controller interrupt enable bit */ |
224 | #define ICH6_INT_GLOBAL_EN 0x80000000 /* global interrupt enable bit */ | 240 | #define ICH6_INT_GLOBAL_EN 0x80000000 /* global interrupt enable bit */ |
225 | 241 | ||
226 | /* GCTL unsolicited response enable bit */ | 242 | /* GCTL unsolicited response enable bit */ |
227 | #define ICH6_GCTL_UREN (1<<8) | 243 | #define ICH6_GCTL_UREN (1<<8) |
@@ -257,22 +273,26 @@ enum { | |||
257 | */ | 273 | */ |
258 | 274 | ||
259 | struct azx_dev { | 275 | struct azx_dev { |
260 | u32 *bdl; /* virtual address of the BDL */ | 276 | u32 *bdl; /* virtual address of the BDL */ |
261 | dma_addr_t bdl_addr; /* physical address of the BDL */ | 277 | dma_addr_t bdl_addr; /* physical address of the BDL */ |
262 | u32 *posbuf; /* position buffer pointer */ | 278 | u32 *posbuf; /* position buffer pointer */ |
263 | 279 | ||
264 | unsigned int bufsize; /* size of the play buffer in bytes */ | 280 | unsigned int bufsize; /* size of the play buffer in bytes */ |
265 | unsigned int fragsize; /* size of each period in bytes */ | 281 | unsigned int fragsize; /* size of each period in bytes */ |
266 | unsigned int frags; /* number for period in the play buffer */ | 282 | unsigned int frags; /* number for period in the play buffer */ |
267 | unsigned int fifo_size; /* FIFO size */ | 283 | unsigned int fifo_size; /* FIFO size */ |
268 | 284 | ||
269 | void __iomem *sd_addr; /* stream descriptor pointer */ | 285 | void __iomem *sd_addr; /* stream descriptor pointer */ |
270 | 286 | ||
271 | u32 sd_int_sta_mask; /* stream int status mask */ | 287 | u32 sd_int_sta_mask; /* stream int status mask */ |
272 | 288 | ||
273 | /* pcm support */ | 289 | /* pcm support */ |
274 | struct snd_pcm_substream *substream; /* assigned substream, set in PCM open */ | 290 | struct snd_pcm_substream *substream; /* assigned substream, |
275 | unsigned int format_val; /* format value to be set in the controller and the codec */ | 291 | * set in PCM open |
292 | */ | ||
293 | unsigned int format_val; /* format value to be set in the | ||
294 | * controller and the codec | ||
295 | */ | ||
276 | unsigned char stream_tag; /* assigned stream */ | 296 | unsigned char stream_tag; /* assigned stream */ |
277 | unsigned char index; /* stream index */ | 297 | unsigned char index; /* stream index */ |
278 | /* for sanity check of position buffer */ | 298 | /* for sanity check of position buffer */ |
@@ -337,6 +357,7 @@ struct azx { | |||
337 | 357 | ||
338 | /* flags */ | 358 | /* flags */ |
339 | int position_fix; | 359 | int position_fix; |
360 | unsigned int running :1; | ||
340 | unsigned int initialized :1; | 361 | unsigned int initialized :1; |
341 | unsigned int single_cmd :1; | 362 | unsigned int single_cmd :1; |
342 | unsigned int polling_mode :1; | 363 | unsigned int polling_mode :1; |
@@ -418,7 +439,8 @@ static int azx_alloc_cmd_io(struct azx *chip) | |||
418 | int err; | 439 | int err; |
419 | 440 | ||
420 | /* single page (at least 4096 bytes) must suffice for both ringbuffes */ | 441 | /* single page (at least 4096 bytes) must suffice for both ringbuffes */ |
421 | err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), | 442 | err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, |
443 | snd_dma_pci_data(chip->pci), | ||
422 | PAGE_SIZE, &chip->rb); | 444 | PAGE_SIZE, &chip->rb); |
423 | if (err < 0) { | 445 | if (err < 0) { |
424 | snd_printk(KERN_ERR SFX "cannot allocate CORB/RIRB\n"); | 446 | snd_printk(KERN_ERR SFX "cannot allocate CORB/RIRB\n"); |
@@ -531,9 +553,9 @@ static unsigned int azx_rirb_get_response(struct hda_codec *codec) | |||
531 | azx_update_rirb(chip); | 553 | azx_update_rirb(chip); |
532 | spin_unlock_irq(&chip->reg_lock); | 554 | spin_unlock_irq(&chip->reg_lock); |
533 | } | 555 | } |
534 | if (! chip->rirb.cmds) | 556 | if (!chip->rirb.cmds) |
535 | return chip->rirb.res; /* the last value */ | 557 | return chip->rirb.res; /* the last value */ |
536 | schedule_timeout(1); | 558 | schedule_timeout_uninterruptible(1); |
537 | } while (time_after_eq(timeout, jiffies)); | 559 | } while (time_after_eq(timeout, jiffies)); |
538 | 560 | ||
539 | if (chip->msi) { | 561 | if (chip->msi) { |
@@ -585,16 +607,19 @@ static int azx_single_send_cmd(struct hda_codec *codec, u32 val) | |||
585 | 607 | ||
586 | while (timeout--) { | 608 | while (timeout--) { |
587 | /* check ICB busy bit */ | 609 | /* check ICB busy bit */ |
588 | if (! (azx_readw(chip, IRS) & ICH6_IRS_BUSY)) { | 610 | if (!((azx_readw(chip, IRS) & ICH6_IRS_BUSY))) { |
589 | /* Clear IRV valid bit */ | 611 | /* Clear IRV valid bit */ |
590 | azx_writew(chip, IRS, azx_readw(chip, IRS) | ICH6_IRS_VALID); | 612 | azx_writew(chip, IRS, azx_readw(chip, IRS) | |
613 | ICH6_IRS_VALID); | ||
591 | azx_writel(chip, IC, val); | 614 | azx_writel(chip, IC, val); |
592 | azx_writew(chip, IRS, azx_readw(chip, IRS) | ICH6_IRS_BUSY); | 615 | azx_writew(chip, IRS, azx_readw(chip, IRS) | |
616 | ICH6_IRS_BUSY); | ||
593 | return 0; | 617 | return 0; |
594 | } | 618 | } |
595 | udelay(1); | 619 | udelay(1); |
596 | } | 620 | } |
597 | snd_printd(SFX "send_cmd timeout: IRS=0x%x, val=0x%x\n", azx_readw(chip, IRS), val); | 621 | snd_printd(SFX "send_cmd timeout: IRS=0x%x, val=0x%x\n", |
622 | azx_readw(chip, IRS), val); | ||
598 | return -EIO; | 623 | return -EIO; |
599 | } | 624 | } |
600 | 625 | ||
@@ -610,7 +635,8 @@ static unsigned int azx_single_get_response(struct hda_codec *codec) | |||
610 | return azx_readl(chip, IR); | 635 | return azx_readl(chip, IR); |
611 | udelay(1); | 636 | udelay(1); |
612 | } | 637 | } |
613 | snd_printd(SFX "get_response timeout: IRS=0x%x\n", azx_readw(chip, IRS)); | 638 | snd_printd(SFX "get_response timeout: IRS=0x%x\n", |
639 | azx_readw(chip, IRS)); | ||
614 | return (unsigned int)-1; | 640 | return (unsigned int)-1; |
615 | } | 641 | } |
616 | 642 | ||
@@ -652,12 +678,18 @@ static unsigned int azx_get_response(struct hda_codec *codec) | |||
652 | return azx_rirb_get_response(codec); | 678 | return azx_rirb_get_response(codec); |
653 | } | 679 | } |
654 | 680 | ||
681 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
682 | static void azx_power_notify(struct hda_codec *codec); | ||
683 | #endif | ||
655 | 684 | ||
656 | /* reset codec link */ | 685 | /* reset codec link */ |
657 | static int azx_reset(struct azx *chip) | 686 | static int azx_reset(struct azx *chip) |
658 | { | 687 | { |
659 | int count; | 688 | int count; |
660 | 689 | ||
690 | /* clear STATESTS */ | ||
691 | azx_writeb(chip, STATESTS, STATESTS_INT_MASK); | ||
692 | |||
661 | /* reset controller */ | 693 | /* reset controller */ |
662 | azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~ICH6_GCTL_RESET); | 694 | azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~ICH6_GCTL_RESET); |
663 | 695 | ||
@@ -777,18 +809,12 @@ static void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev) | |||
777 | 809 | ||
778 | 810 | ||
779 | /* | 811 | /* |
780 | * initialize the chip | 812 | * reset and start the controller registers |
781 | */ | 813 | */ |
782 | static void azx_init_chip(struct azx *chip) | 814 | static void azx_init_chip(struct azx *chip) |
783 | { | 815 | { |
784 | unsigned char reg; | 816 | if (chip->initialized) |
785 | 817 | return; | |
786 | /* Clear bits 0-2 of PCI register TCSEL (at offset 0x44) | ||
787 | * TCSEL == Traffic Class Select Register, which sets PCI express QOS | ||
788 | * Ensuring these bits are 0 clears playback static on some HD Audio codecs | ||
789 | */ | ||
790 | pci_read_config_byte (chip->pci, ICH6_PCIREG_TCSEL, ®); | ||
791 | pci_write_config_byte(chip->pci, ICH6_PCIREG_TCSEL, reg & 0xf8); | ||
792 | 818 | ||
793 | /* reset controller */ | 819 | /* reset controller */ |
794 | azx_reset(chip); | 820 | azx_reset(chip); |
@@ -805,19 +831,45 @@ static void azx_init_chip(struct azx *chip) | |||
805 | azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr); | 831 | azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr); |
806 | azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr)); | 832 | azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr)); |
807 | 833 | ||
834 | chip->initialized = 1; | ||
835 | } | ||
836 | |||
837 | /* | ||
838 | * initialize the PCI registers | ||
839 | */ | ||
840 | /* update bits in a PCI register byte */ | ||
841 | static void update_pci_byte(struct pci_dev *pci, unsigned int reg, | ||
842 | unsigned char mask, unsigned char val) | ||
843 | { | ||
844 | unsigned char data; | ||
845 | |||
846 | pci_read_config_byte(pci, reg, &data); | ||
847 | data &= ~mask; | ||
848 | data |= (val & mask); | ||
849 | pci_write_config_byte(pci, reg, data); | ||
850 | } | ||
851 | |||
852 | static void azx_init_pci(struct azx *chip) | ||
853 | { | ||
854 | /* Clear bits 0-2 of PCI register TCSEL (at offset 0x44) | ||
855 | * TCSEL == Traffic Class Select Register, which sets PCI express QOS | ||
856 | * Ensuring these bits are 0 clears playback static on some HD Audio | ||
857 | * codecs | ||
858 | */ | ||
859 | update_pci_byte(chip->pci, ICH6_PCIREG_TCSEL, 0x07, 0); | ||
860 | |||
808 | switch (chip->driver_type) { | 861 | switch (chip->driver_type) { |
809 | case AZX_DRIVER_ATI: | 862 | case AZX_DRIVER_ATI: |
810 | /* For ATI SB450 azalia HD audio, we need to enable snoop */ | 863 | /* For ATI SB450 azalia HD audio, we need to enable snoop */ |
811 | pci_read_config_byte(chip->pci, ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR, | 864 | update_pci_byte(chip->pci, |
812 | ®); | 865 | ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR, |
813 | pci_write_config_byte(chip->pci, ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR, | 866 | 0x07, ATI_SB450_HDAUDIO_ENABLE_SNOOP); |
814 | (reg & 0xf8) | ATI_SB450_HDAUDIO_ENABLE_SNOOP); | ||
815 | break; | 867 | break; |
816 | case AZX_DRIVER_NVIDIA: | 868 | case AZX_DRIVER_NVIDIA: |
817 | /* For NVIDIA HDA, enable snoop */ | 869 | /* For NVIDIA HDA, enable snoop */ |
818 | pci_read_config_byte(chip->pci,NVIDIA_HDA_TRANSREG_ADDR, ®); | 870 | update_pci_byte(chip->pci, |
819 | pci_write_config_byte(chip->pci,NVIDIA_HDA_TRANSREG_ADDR, | 871 | NVIDIA_HDA_TRANSREG_ADDR, |
820 | (reg & 0xf0) | NVIDIA_HDA_ENABLE_COHBITS); | 872 | 0x0f, NVIDIA_HDA_ENABLE_COHBITS); |
821 | break; | 873 | break; |
822 | } | 874 | } |
823 | } | 875 | } |
@@ -857,7 +909,7 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id) | |||
857 | /* clear rirb int */ | 909 | /* clear rirb int */ |
858 | status = azx_readb(chip, RIRBSTS); | 910 | status = azx_readb(chip, RIRBSTS); |
859 | if (status & RIRB_INT_MASK) { | 911 | if (status & RIRB_INT_MASK) { |
860 | if (! chip->single_cmd && (status & RIRB_INT_RESPONSE)) | 912 | if (!chip->single_cmd && (status & RIRB_INT_RESPONSE)) |
861 | azx_update_rirb(chip); | 913 | azx_update_rirb(chip); |
862 | azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); | 914 | azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); |
863 | } | 915 | } |
@@ -911,9 +963,11 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) | |||
911 | int timeout; | 963 | int timeout; |
912 | 964 | ||
913 | /* make sure the run bit is zero for SD */ | 965 | /* make sure the run bit is zero for SD */ |
914 | azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) & ~SD_CTL_DMA_START); | 966 | azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) & |
967 | ~SD_CTL_DMA_START); | ||
915 | /* reset stream */ | 968 | /* reset stream */ |
916 | azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) | SD_CTL_STREAM_RESET); | 969 | azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) | |
970 | SD_CTL_STREAM_RESET); | ||
917 | udelay(3); | 971 | udelay(3); |
918 | timeout = 300; | 972 | timeout = 300; |
919 | while (!((val = azx_sd_readb(azx_dev, SD_CTL)) & SD_CTL_STREAM_RESET) && | 973 | while (!((val = azx_sd_readb(azx_dev, SD_CTL)) & SD_CTL_STREAM_RESET) && |
@@ -931,7 +985,7 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) | |||
931 | 985 | ||
932 | /* program the stream_tag */ | 986 | /* program the stream_tag */ |
933 | azx_sd_writel(azx_dev, SD_CTL, | 987 | azx_sd_writel(azx_dev, SD_CTL, |
934 | (azx_sd_readl(azx_dev, SD_CTL) & ~SD_CTL_STREAM_TAG_MASK) | | 988 | (azx_sd_readl(azx_dev, SD_CTL) & ~SD_CTL_STREAM_TAG_MASK)| |
935 | (azx_dev->stream_tag << SD_CTL_STREAM_TAG_SHIFT)); | 989 | (azx_dev->stream_tag << SD_CTL_STREAM_TAG_SHIFT)); |
936 | 990 | ||
937 | /* program the length of samples in cyclic buffer */ | 991 | /* program the length of samples in cyclic buffer */ |
@@ -951,11 +1005,13 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) | |||
951 | azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl_addr)); | 1005 | azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl_addr)); |
952 | 1006 | ||
953 | /* enable the position buffer */ | 1007 | /* enable the position buffer */ |
954 | if (! (azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE)) | 1008 | if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE)) |
955 | azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE); | 1009 | azx_writel(chip, DPLBASE, |
1010 | (u32)chip->posbuf.addr |ICH6_DPLBASE_ENABLE); | ||
956 | 1011 | ||
957 | /* set the interrupt enable bits in the descriptor control register */ | 1012 | /* set the interrupt enable bits in the descriptor control register */ |
958 | azx_sd_writel(azx_dev, SD_CTL, azx_sd_readl(azx_dev, SD_CTL) | SD_INT_MASK); | 1013 | azx_sd_writel(azx_dev, SD_CTL, |
1014 | azx_sd_readl(azx_dev, SD_CTL) | SD_INT_MASK); | ||
959 | 1015 | ||
960 | return 0; | 1016 | return 0; |
961 | } | 1017 | } |
@@ -986,8 +1042,12 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model) | |||
986 | bus_temp.pci = chip->pci; | 1042 | bus_temp.pci = chip->pci; |
987 | bus_temp.ops.command = azx_send_cmd; | 1043 | bus_temp.ops.command = azx_send_cmd; |
988 | bus_temp.ops.get_response = azx_get_response; | 1044 | bus_temp.ops.get_response = azx_get_response; |
1045 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1046 | bus_temp.ops.pm_notify = azx_power_notify; | ||
1047 | #endif | ||
989 | 1048 | ||
990 | if ((err = snd_hda_bus_new(chip->card, &bus_temp, &chip->bus)) < 0) | 1049 | err = snd_hda_bus_new(chip->card, &bus_temp, &chip->bus); |
1050 | if (err < 0) | ||
991 | return err; | 1051 | return err; |
992 | 1052 | ||
993 | codecs = audio_codecs = 0; | 1053 | codecs = audio_codecs = 0; |
@@ -1038,7 +1098,7 @@ static inline struct azx_dev *azx_assign_device(struct azx *chip, int stream) | |||
1038 | nums = chip->capture_streams; | 1098 | nums = chip->capture_streams; |
1039 | } | 1099 | } |
1040 | for (i = 0; i < nums; i++, dev++) | 1100 | for (i = 0; i < nums; i++, dev++) |
1041 | if (! chip->azx_dev[dev].opened) { | 1101 | if (!chip->azx_dev[dev].opened) { |
1042 | chip->azx_dev[dev].opened = 1; | 1102 | chip->azx_dev[dev].opened = 1; |
1043 | return &chip->azx_dev[dev]; | 1103 | return &chip->azx_dev[dev]; |
1044 | } | 1104 | } |
@@ -1052,7 +1112,8 @@ static inline void azx_release_device(struct azx_dev *azx_dev) | |||
1052 | } | 1112 | } |
1053 | 1113 | ||
1054 | static struct snd_pcm_hardware azx_pcm_hw = { | 1114 | static struct snd_pcm_hardware azx_pcm_hw = { |
1055 | .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | | 1115 | .info = (SNDRV_PCM_INFO_MMAP | |
1116 | SNDRV_PCM_INFO_INTERLEAVED | | ||
1056 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 1117 | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
1057 | SNDRV_PCM_INFO_MMAP_VALID | | 1118 | SNDRV_PCM_INFO_MMAP_VALID | |
1058 | /* No full-resume yet implemented */ | 1119 | /* No full-resume yet implemented */ |
@@ -1105,8 +1166,11 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) | |||
1105 | 128); | 1166 | 128); |
1106 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, | 1167 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, |
1107 | 128); | 1168 | 128); |
1108 | if ((err = hinfo->ops.open(hinfo, apcm->codec, substream)) < 0) { | 1169 | snd_hda_power_up(apcm->codec); |
1170 | err = hinfo->ops.open(hinfo, apcm->codec, substream); | ||
1171 | if (err < 0) { | ||
1109 | azx_release_device(azx_dev); | 1172 | azx_release_device(azx_dev); |
1173 | snd_hda_power_down(apcm->codec); | ||
1110 | mutex_unlock(&chip->open_mutex); | 1174 | mutex_unlock(&chip->open_mutex); |
1111 | return err; | 1175 | return err; |
1112 | } | 1176 | } |
@@ -1135,13 +1199,16 @@ static int azx_pcm_close(struct snd_pcm_substream *substream) | |||
1135 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 1199 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
1136 | azx_release_device(azx_dev); | 1200 | azx_release_device(azx_dev); |
1137 | hinfo->ops.close(hinfo, apcm->codec, substream); | 1201 | hinfo->ops.close(hinfo, apcm->codec, substream); |
1202 | snd_hda_power_down(apcm->codec); | ||
1138 | mutex_unlock(&chip->open_mutex); | 1203 | mutex_unlock(&chip->open_mutex); |
1139 | return 0; | 1204 | return 0; |
1140 | } | 1205 | } |
1141 | 1206 | ||
1142 | static int azx_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) | 1207 | static int azx_pcm_hw_params(struct snd_pcm_substream *substream, |
1208 | struct snd_pcm_hw_params *hw_params) | ||
1143 | { | 1209 | { |
1144 | return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); | 1210 | return snd_pcm_lib_malloc_pages(substream, |
1211 | params_buffer_bytes(hw_params)); | ||
1145 | } | 1212 | } |
1146 | 1213 | ||
1147 | static int azx_pcm_hw_free(struct snd_pcm_substream *substream) | 1214 | static int azx_pcm_hw_free(struct snd_pcm_substream *substream) |
@@ -1175,13 +1242,15 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) | |||
1175 | runtime->channels, | 1242 | runtime->channels, |
1176 | runtime->format, | 1243 | runtime->format, |
1177 | hinfo->maxbps); | 1244 | hinfo->maxbps); |
1178 | if (! azx_dev->format_val) { | 1245 | if (!azx_dev->format_val) { |
1179 | snd_printk(KERN_ERR SFX "invalid format_val, rate=%d, ch=%d, format=%d\n", | 1246 | snd_printk(KERN_ERR SFX |
1247 | "invalid format_val, rate=%d, ch=%d, format=%d\n", | ||
1180 | runtime->rate, runtime->channels, runtime->format); | 1248 | runtime->rate, runtime->channels, runtime->format); |
1181 | return -EINVAL; | 1249 | return -EINVAL; |
1182 | } | 1250 | } |
1183 | 1251 | ||
1184 | snd_printdd("azx_pcm_prepare: bufsize=0x%x, fragsize=0x%x, format=0x%x\n", | 1252 | snd_printdd("azx_pcm_prepare: bufsize=0x%x, fragsize=0x%x, " |
1253 | "format=0x%x\n", | ||
1185 | azx_dev->bufsize, azx_dev->fragsize, azx_dev->format_val); | 1254 | azx_dev->bufsize, azx_dev->fragsize, azx_dev->format_val); |
1186 | azx_setup_periods(azx_dev); | 1255 | azx_setup_periods(azx_dev); |
1187 | azx_setup_controller(chip, azx_dev); | 1256 | azx_setup_controller(chip, azx_dev); |
@@ -1223,7 +1292,8 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
1223 | cmd == SNDRV_PCM_TRIGGER_SUSPEND || | 1292 | cmd == SNDRV_PCM_TRIGGER_SUSPEND || |
1224 | cmd == SNDRV_PCM_TRIGGER_STOP) { | 1293 | cmd == SNDRV_PCM_TRIGGER_STOP) { |
1225 | int timeout = 5000; | 1294 | int timeout = 5000; |
1226 | while (azx_sd_readb(azx_dev, SD_CTL) & SD_CTL_DMA_START && --timeout) | 1295 | while ((azx_sd_readb(azx_dev, SD_CTL) & SD_CTL_DMA_START) && |
1296 | --timeout) | ||
1227 | ; | 1297 | ; |
1228 | } | 1298 | } |
1229 | return err; | 1299 | return err; |
@@ -1241,7 +1311,7 @@ static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream) | |||
1241 | /* use the position buffer */ | 1311 | /* use the position buffer */ |
1242 | pos = le32_to_cpu(*azx_dev->posbuf); | 1312 | pos = le32_to_cpu(*azx_dev->posbuf); |
1243 | if (chip->position_fix == POS_FIX_AUTO && | 1313 | if (chip->position_fix == POS_FIX_AUTO && |
1244 | azx_dev->period_intr == 1 && ! pos) { | 1314 | azx_dev->period_intr == 1 && !pos) { |
1245 | printk(KERN_WARNING | 1315 | printk(KERN_WARNING |
1246 | "hda-intel: Invalid position buffer, " | 1316 | "hda-intel: Invalid position buffer, " |
1247 | "using LPIB read method instead.\n"); | 1317 | "using LPIB read method instead.\n"); |
@@ -1292,7 +1362,8 @@ static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec, | |||
1292 | snd_assert(cpcm->name, return -EINVAL); | 1362 | snd_assert(cpcm->name, return -EINVAL); |
1293 | 1363 | ||
1294 | err = snd_pcm_new(chip->card, cpcm->name, pcm_dev, | 1364 | err = snd_pcm_new(chip->card, cpcm->name, pcm_dev, |
1295 | cpcm->stream[0].substreams, cpcm->stream[1].substreams, | 1365 | cpcm->stream[0].substreams, |
1366 | cpcm->stream[1].substreams, | ||
1296 | &pcm); | 1367 | &pcm); |
1297 | if (err < 0) | 1368 | if (err < 0) |
1298 | return err; | 1369 | return err; |
@@ -1322,26 +1393,27 @@ static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec, | |||
1322 | 1393 | ||
1323 | static int __devinit azx_pcm_create(struct azx *chip) | 1394 | static int __devinit azx_pcm_create(struct azx *chip) |
1324 | { | 1395 | { |
1325 | struct list_head *p; | ||
1326 | struct hda_codec *codec; | 1396 | struct hda_codec *codec; |
1327 | int c, err; | 1397 | int c, err; |
1328 | int pcm_dev; | 1398 | int pcm_dev; |
1329 | 1399 | ||
1330 | if ((err = snd_hda_build_pcms(chip->bus)) < 0) | 1400 | err = snd_hda_build_pcms(chip->bus); |
1401 | if (err < 0) | ||
1331 | return err; | 1402 | return err; |
1332 | 1403 | ||
1333 | /* create audio PCMs */ | 1404 | /* create audio PCMs */ |
1334 | pcm_dev = 0; | 1405 | pcm_dev = 0; |
1335 | list_for_each(p, &chip->bus->codec_list) { | 1406 | list_for_each_entry(codec, &chip->bus->codec_list, list) { |
1336 | codec = list_entry(p, struct hda_codec, list); | ||
1337 | for (c = 0; c < codec->num_pcms; c++) { | 1407 | for (c = 0; c < codec->num_pcms; c++) { |
1338 | if (codec->pcm_info[c].is_modem) | 1408 | if (codec->pcm_info[c].is_modem) |
1339 | continue; /* create later */ | 1409 | continue; /* create later */ |
1340 | if (pcm_dev >= AZX_MAX_AUDIO_PCMS) { | 1410 | if (pcm_dev >= AZX_MAX_AUDIO_PCMS) { |
1341 | snd_printk(KERN_ERR SFX "Too many audio PCMs\n"); | 1411 | snd_printk(KERN_ERR SFX |
1412 | "Too many audio PCMs\n"); | ||
1342 | return -EINVAL; | 1413 | return -EINVAL; |
1343 | } | 1414 | } |
1344 | err = create_codec_pcm(chip, codec, &codec->pcm_info[c], pcm_dev); | 1415 | err = create_codec_pcm(chip, codec, |
1416 | &codec->pcm_info[c], pcm_dev); | ||
1345 | if (err < 0) | 1417 | if (err < 0) |
1346 | return err; | 1418 | return err; |
1347 | pcm_dev++; | 1419 | pcm_dev++; |
@@ -1350,16 +1422,17 @@ static int __devinit azx_pcm_create(struct azx *chip) | |||
1350 | 1422 | ||
1351 | /* create modem PCMs */ | 1423 | /* create modem PCMs */ |
1352 | pcm_dev = AZX_MAX_AUDIO_PCMS; | 1424 | pcm_dev = AZX_MAX_AUDIO_PCMS; |
1353 | list_for_each(p, &chip->bus->codec_list) { | 1425 | list_for_each_entry(codec, &chip->bus->codec_list, list) { |
1354 | codec = list_entry(p, struct hda_codec, list); | ||
1355 | for (c = 0; c < codec->num_pcms; c++) { | 1426 | for (c = 0; c < codec->num_pcms; c++) { |
1356 | if (! codec->pcm_info[c].is_modem) | 1427 | if (!codec->pcm_info[c].is_modem) |
1357 | continue; /* already created */ | 1428 | continue; /* already created */ |
1358 | if (pcm_dev >= AZX_MAX_PCMS) { | 1429 | if (pcm_dev >= AZX_MAX_PCMS) { |
1359 | snd_printk(KERN_ERR SFX "Too many modem PCMs\n"); | 1430 | snd_printk(KERN_ERR SFX |
1431 | "Too many modem PCMs\n"); | ||
1360 | return -EINVAL; | 1432 | return -EINVAL; |
1361 | } | 1433 | } |
1362 | err = create_codec_pcm(chip, codec, &codec->pcm_info[c], pcm_dev); | 1434 | err = create_codec_pcm(chip, codec, |
1435 | &codec->pcm_info[c], pcm_dev); | ||
1363 | if (err < 0) | 1436 | if (err < 0) |
1364 | return err; | 1437 | return err; |
1365 | chip->pcm[pcm_dev]->dev_class = SNDRV_PCM_CLASS_MODEM; | 1438 | chip->pcm[pcm_dev]->dev_class = SNDRV_PCM_CLASS_MODEM; |
@@ -1386,7 +1459,8 @@ static int __devinit azx_init_stream(struct azx *chip) | |||
1386 | int i; | 1459 | int i; |
1387 | 1460 | ||
1388 | /* initialize each stream (aka device) | 1461 | /* initialize each stream (aka device) |
1389 | * assign the starting bdl address to each stream (device) and initialize | 1462 | * assign the starting bdl address to each stream (device) |
1463 | * and initialize | ||
1390 | */ | 1464 | */ |
1391 | for (i = 0; i < chip->num_streams; i++) { | 1465 | for (i = 0; i < chip->num_streams; i++) { |
1392 | unsigned int off = sizeof(u32) * (i * AZX_MAX_FRAG * 4); | 1466 | unsigned int off = sizeof(u32) * (i * AZX_MAX_FRAG * 4); |
@@ -1423,6 +1497,46 @@ static int azx_acquire_irq(struct azx *chip, int do_disconnect) | |||
1423 | } | 1497 | } |
1424 | 1498 | ||
1425 | 1499 | ||
1500 | static void azx_stop_chip(struct azx *chip) | ||
1501 | { | ||
1502 | if (!chip->initialized) | ||
1503 | return; | ||
1504 | |||
1505 | /* disable interrupts */ | ||
1506 | azx_int_disable(chip); | ||
1507 | azx_int_clear(chip); | ||
1508 | |||
1509 | /* disable CORB/RIRB */ | ||
1510 | azx_free_cmd_io(chip); | ||
1511 | |||
1512 | /* disable position buffer */ | ||
1513 | azx_writel(chip, DPLBASE, 0); | ||
1514 | azx_writel(chip, DPUBASE, 0); | ||
1515 | |||
1516 | chip->initialized = 0; | ||
1517 | } | ||
1518 | |||
1519 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1520 | /* power-up/down the controller */ | ||
1521 | static void azx_power_notify(struct hda_codec *codec) | ||
1522 | { | ||
1523 | struct azx *chip = codec->bus->private_data; | ||
1524 | struct hda_codec *c; | ||
1525 | int power_on = 0; | ||
1526 | |||
1527 | list_for_each_entry(c, &codec->bus->codec_list, list) { | ||
1528 | if (c->power_on) { | ||
1529 | power_on = 1; | ||
1530 | break; | ||
1531 | } | ||
1532 | } | ||
1533 | if (power_on) | ||
1534 | azx_init_chip(chip); | ||
1535 | else if (chip->running && power_save_controller) | ||
1536 | azx_stop_chip(chip); | ||
1537 | } | ||
1538 | #endif /* CONFIG_SND_HDA_POWER_SAVE */ | ||
1539 | |||
1426 | #ifdef CONFIG_PM | 1540 | #ifdef CONFIG_PM |
1427 | /* | 1541 | /* |
1428 | * power management | 1542 | * power management |
@@ -1436,8 +1550,9 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state) | |||
1436 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | 1550 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
1437 | for (i = 0; i < chip->pcm_devs; i++) | 1551 | for (i = 0; i < chip->pcm_devs; i++) |
1438 | snd_pcm_suspend_all(chip->pcm[i]); | 1552 | snd_pcm_suspend_all(chip->pcm[i]); |
1439 | snd_hda_suspend(chip->bus, state); | 1553 | if (chip->initialized) |
1440 | azx_free_cmd_io(chip); | 1554 | snd_hda_suspend(chip->bus, state); |
1555 | azx_stop_chip(chip); | ||
1441 | if (chip->irq >= 0) { | 1556 | if (chip->irq >= 0) { |
1442 | synchronize_irq(chip->irq); | 1557 | synchronize_irq(chip->irq); |
1443 | free_irq(chip->irq, chip); | 1558 | free_irq(chip->irq, chip); |
@@ -1470,7 +1585,11 @@ static int azx_resume(struct pci_dev *pci) | |||
1470 | chip->msi = 0; | 1585 | chip->msi = 0; |
1471 | if (azx_acquire_irq(chip, 1) < 0) | 1586 | if (azx_acquire_irq(chip, 1) < 0) |
1472 | return -EIO; | 1587 | return -EIO; |
1473 | azx_init_chip(chip); | 1588 | azx_init_pci(chip); |
1589 | |||
1590 | if (snd_hda_codecs_inuse(chip->bus)) | ||
1591 | azx_init_chip(chip); | ||
1592 | |||
1474 | snd_hda_resume(chip->bus); | 1593 | snd_hda_resume(chip->bus); |
1475 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 1594 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
1476 | return 0; | 1595 | return 0; |
@@ -1485,20 +1604,9 @@ static int azx_free(struct azx *chip) | |||
1485 | { | 1604 | { |
1486 | if (chip->initialized) { | 1605 | if (chip->initialized) { |
1487 | int i; | 1606 | int i; |
1488 | |||
1489 | for (i = 0; i < chip->num_streams; i++) | 1607 | for (i = 0; i < chip->num_streams; i++) |
1490 | azx_stream_stop(chip, &chip->azx_dev[i]); | 1608 | azx_stream_stop(chip, &chip->azx_dev[i]); |
1491 | 1609 | azx_stop_chip(chip); | |
1492 | /* disable interrupts */ | ||
1493 | azx_int_disable(chip); | ||
1494 | azx_int_clear(chip); | ||
1495 | |||
1496 | /* disable CORB/RIRB */ | ||
1497 | azx_free_cmd_io(chip); | ||
1498 | |||
1499 | /* disable position buffer */ | ||
1500 | azx_writel(chip, DPLBASE, 0); | ||
1501 | azx_writel(chip, DPUBASE, 0); | ||
1502 | } | 1610 | } |
1503 | 1611 | ||
1504 | if (chip->irq >= 0) { | 1612 | if (chip->irq >= 0) { |
@@ -1534,6 +1642,7 @@ static int azx_dev_free(struct snd_device *device) | |||
1534 | */ | 1642 | */ |
1535 | static struct snd_pci_quirk position_fix_list[] __devinitdata = { | 1643 | static struct snd_pci_quirk position_fix_list[] __devinitdata = { |
1536 | SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_NONE), | 1644 | SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_NONE), |
1645 | SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_NONE), | ||
1537 | {} | 1646 | {} |
1538 | }; | 1647 | }; |
1539 | 1648 | ||
@@ -1544,7 +1653,7 @@ static int __devinit check_position_fix(struct azx *chip, int fix) | |||
1544 | if (fix == POS_FIX_AUTO) { | 1653 | if (fix == POS_FIX_AUTO) { |
1545 | q = snd_pci_quirk_lookup(chip->pci, position_fix_list); | 1654 | q = snd_pci_quirk_lookup(chip->pci, position_fix_list); |
1546 | if (q) { | 1655 | if (q) { |
1547 | snd_printdd(KERN_INFO | 1656 | printk(KERN_INFO |
1548 | "hda_intel: position_fix set to %d " | 1657 | "hda_intel: position_fix set to %d " |
1549 | "for device %04x:%04x\n", | 1658 | "for device %04x:%04x\n", |
1550 | q->value, q->subvendor, q->subdevice); | 1659 | q->value, q->subvendor, q->subdevice); |
@@ -1555,6 +1664,36 @@ static int __devinit check_position_fix(struct azx *chip, int fix) | |||
1555 | } | 1664 | } |
1556 | 1665 | ||
1557 | /* | 1666 | /* |
1667 | * black-lists for probe_mask | ||
1668 | */ | ||
1669 | static struct snd_pci_quirk probe_mask_list[] __devinitdata = { | ||
1670 | /* Thinkpad often breaks the controller communication when accessing | ||
1671 | * to the non-working (or non-existing) modem codec slot. | ||
1672 | */ | ||
1673 | SND_PCI_QUIRK(0x1014, 0x05b7, "Thinkpad Z60", 0x01), | ||
1674 | SND_PCI_QUIRK(0x17aa, 0x2010, "Thinkpad X/T/R60", 0x01), | ||
1675 | SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X/T/R61", 0x01), | ||
1676 | {} | ||
1677 | }; | ||
1678 | |||
1679 | static void __devinit check_probe_mask(struct azx *chip) | ||
1680 | { | ||
1681 | const struct snd_pci_quirk *q; | ||
1682 | |||
1683 | if (probe_mask == -1) { | ||
1684 | q = snd_pci_quirk_lookup(chip->pci, probe_mask_list); | ||
1685 | if (q) { | ||
1686 | printk(KERN_INFO | ||
1687 | "hda_intel: probe_mask set to 0x%x " | ||
1688 | "for device %04x:%04x\n", | ||
1689 | q->value, q->subvendor, q->subdevice); | ||
1690 | probe_mask = q->value; | ||
1691 | } | ||
1692 | } | ||
1693 | } | ||
1694 | |||
1695 | |||
1696 | /* | ||
1558 | * constructor | 1697 | * constructor |
1559 | */ | 1698 | */ |
1560 | static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | 1699 | static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, |
@@ -1589,6 +1728,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | |||
1589 | chip->msi = enable_msi; | 1728 | chip->msi = enable_msi; |
1590 | 1729 | ||
1591 | chip->position_fix = check_position_fix(chip, position_fix); | 1730 | chip->position_fix = check_position_fix(chip, position_fix); |
1731 | check_probe_mask(chip); | ||
1592 | 1732 | ||
1593 | chip->single_cmd = single_cmd; | 1733 | chip->single_cmd = single_cmd; |
1594 | 1734 | ||
@@ -1650,37 +1790,43 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | |||
1650 | break; | 1790 | break; |
1651 | } | 1791 | } |
1652 | chip->num_streams = chip->playback_streams + chip->capture_streams; | 1792 | chip->num_streams = chip->playback_streams + chip->capture_streams; |
1653 | chip->azx_dev = kcalloc(chip->num_streams, sizeof(*chip->azx_dev), GFP_KERNEL); | 1793 | chip->azx_dev = kcalloc(chip->num_streams, sizeof(*chip->azx_dev), |
1794 | GFP_KERNEL); | ||
1654 | if (!chip->azx_dev) { | 1795 | if (!chip->azx_dev) { |
1655 | snd_printk(KERN_ERR "cannot malloc azx_dev\n"); | 1796 | snd_printk(KERN_ERR "cannot malloc azx_dev\n"); |
1656 | goto errout; | 1797 | goto errout; |
1657 | } | 1798 | } |
1658 | 1799 | ||
1659 | /* allocate memory for the BDL for each stream */ | 1800 | /* allocate memory for the BDL for each stream */ |
1660 | if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), | 1801 | err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, |
1661 | BDL_SIZE, &chip->bdl)) < 0) { | 1802 | snd_dma_pci_data(chip->pci), |
1803 | BDL_SIZE, &chip->bdl); | ||
1804 | if (err < 0) { | ||
1662 | snd_printk(KERN_ERR SFX "cannot allocate BDL\n"); | 1805 | snd_printk(KERN_ERR SFX "cannot allocate BDL\n"); |
1663 | goto errout; | 1806 | goto errout; |
1664 | } | 1807 | } |
1665 | /* allocate memory for the position buffer */ | 1808 | /* allocate memory for the position buffer */ |
1666 | if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), | 1809 | err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, |
1667 | chip->num_streams * 8, &chip->posbuf)) < 0) { | 1810 | snd_dma_pci_data(chip->pci), |
1811 | chip->num_streams * 8, &chip->posbuf); | ||
1812 | if (err < 0) { | ||
1668 | snd_printk(KERN_ERR SFX "cannot allocate posbuf\n"); | 1813 | snd_printk(KERN_ERR SFX "cannot allocate posbuf\n"); |
1669 | goto errout; | 1814 | goto errout; |
1670 | } | 1815 | } |
1671 | /* allocate CORB/RIRB */ | 1816 | /* allocate CORB/RIRB */ |
1672 | if (! chip->single_cmd) | 1817 | if (!chip->single_cmd) { |
1673 | if ((err = azx_alloc_cmd_io(chip)) < 0) | 1818 | err = azx_alloc_cmd_io(chip); |
1819 | if (err < 0) | ||
1674 | goto errout; | 1820 | goto errout; |
1821 | } | ||
1675 | 1822 | ||
1676 | /* initialize streams */ | 1823 | /* initialize streams */ |
1677 | azx_init_stream(chip); | 1824 | azx_init_stream(chip); |
1678 | 1825 | ||
1679 | /* initialize chip */ | 1826 | /* initialize chip */ |
1827 | azx_init_pci(chip); | ||
1680 | azx_init_chip(chip); | 1828 | azx_init_chip(chip); |
1681 | 1829 | ||
1682 | chip->initialized = 1; | ||
1683 | |||
1684 | /* codec detection */ | 1830 | /* codec detection */ |
1685 | if (!chip->codec_mask) { | 1831 | if (!chip->codec_mask) { |
1686 | snd_printk(KERN_ERR SFX "no codecs found!\n"); | 1832 | snd_printk(KERN_ERR SFX "no codecs found!\n"); |
@@ -1688,14 +1834,16 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | |||
1688 | goto errout; | 1834 | goto errout; |
1689 | } | 1835 | } |
1690 | 1836 | ||
1691 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) <0) { | 1837 | err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); |
1838 | if (err <0) { | ||
1692 | snd_printk(KERN_ERR SFX "Error creating device [card]!\n"); | 1839 | snd_printk(KERN_ERR SFX "Error creating device [card]!\n"); |
1693 | goto errout; | 1840 | goto errout; |
1694 | } | 1841 | } |
1695 | 1842 | ||
1696 | strcpy(card->driver, "HDA-Intel"); | 1843 | strcpy(card->driver, "HDA-Intel"); |
1697 | strcpy(card->shortname, driver_short_names[chip->driver_type]); | 1844 | strcpy(card->shortname, driver_short_names[chip->driver_type]); |
1698 | sprintf(card->longname, "%s at 0x%lx irq %i", card->shortname, chip->addr, chip->irq); | 1845 | sprintf(card->longname, "%s at 0x%lx irq %i", |
1846 | card->shortname, chip->addr, chip->irq); | ||
1699 | 1847 | ||
1700 | *rchip = chip; | 1848 | *rchip = chip; |
1701 | return 0; | 1849 | return 0; |
@@ -1705,7 +1853,21 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | |||
1705 | return err; | 1853 | return err; |
1706 | } | 1854 | } |
1707 | 1855 | ||
1708 | static int __devinit azx_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) | 1856 | static void power_down_all_codecs(struct azx *chip) |
1857 | { | ||
1858 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1859 | /* The codecs were powered up in snd_hda_codec_new(). | ||
1860 | * Now all initialization done, so turn them down if possible | ||
1861 | */ | ||
1862 | struct hda_codec *codec; | ||
1863 | list_for_each_entry(codec, &chip->bus->codec_list, list) { | ||
1864 | snd_hda_power_down(codec); | ||
1865 | } | ||
1866 | #endif | ||
1867 | } | ||
1868 | |||
1869 | static int __devinit azx_probe(struct pci_dev *pci, | ||
1870 | const struct pci_device_id *pci_id) | ||
1709 | { | 1871 | { |
1710 | struct snd_card *card; | 1872 | struct snd_card *card; |
1711 | struct azx *chip; | 1873 | struct azx *chip; |
@@ -1725,31 +1887,37 @@ static int __devinit azx_probe(struct pci_dev *pci, const struct pci_device_id * | |||
1725 | card->private_data = chip; | 1887 | card->private_data = chip; |
1726 | 1888 | ||
1727 | /* create codec instances */ | 1889 | /* create codec instances */ |
1728 | if ((err = azx_codec_create(chip, model)) < 0) { | 1890 | err = azx_codec_create(chip, model); |
1891 | if (err < 0) { | ||
1729 | snd_card_free(card); | 1892 | snd_card_free(card); |
1730 | return err; | 1893 | return err; |
1731 | } | 1894 | } |
1732 | 1895 | ||
1733 | /* create PCM streams */ | 1896 | /* create PCM streams */ |
1734 | if ((err = azx_pcm_create(chip)) < 0) { | 1897 | err = azx_pcm_create(chip); |
1898 | if (err < 0) { | ||
1735 | snd_card_free(card); | 1899 | snd_card_free(card); |
1736 | return err; | 1900 | return err; |
1737 | } | 1901 | } |
1738 | 1902 | ||
1739 | /* create mixer controls */ | 1903 | /* create mixer controls */ |
1740 | if ((err = azx_mixer_create(chip)) < 0) { | 1904 | err = azx_mixer_create(chip); |
1905 | if (err < 0) { | ||
1741 | snd_card_free(card); | 1906 | snd_card_free(card); |
1742 | return err; | 1907 | return err; |
1743 | } | 1908 | } |
1744 | 1909 | ||
1745 | snd_card_set_dev(card, &pci->dev); | 1910 | snd_card_set_dev(card, &pci->dev); |
1746 | 1911 | ||
1747 | if ((err = snd_card_register(card)) < 0) { | 1912 | err = snd_card_register(card); |
1913 | if (err < 0) { | ||
1748 | snd_card_free(card); | 1914 | snd_card_free(card); |
1749 | return err; | 1915 | return err; |
1750 | } | 1916 | } |
1751 | 1917 | ||
1752 | pci_set_drvdata(pci, card); | 1918 | pci_set_drvdata(pci, card); |
1919 | chip->running = 1; | ||
1920 | power_down_all_codecs(chip); | ||
1753 | 1921 | ||
1754 | return err; | 1922 | return err; |
1755 | } | 1923 | } |
@@ -1791,6 +1959,10 @@ static struct pci_device_id azx_ids[] = { | |||
1791 | { 0x10de, 0x0775, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */ | 1959 | { 0x10de, 0x0775, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */ |
1792 | { 0x10de, 0x0776, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */ | 1960 | { 0x10de, 0x0776, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */ |
1793 | { 0x10de, 0x0777, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */ | 1961 | { 0x10de, 0x0777, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */ |
1962 | { 0x10de, 0x0ac0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP79 */ | ||
1963 | { 0x10de, 0x0ac1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP79 */ | ||
1964 | { 0x10de, 0x0ac2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP79 */ | ||
1965 | { 0x10de, 0x0ac3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP79 */ | ||
1794 | { 0, } | 1966 | { 0, } |
1795 | }; | 1967 | }; |
1796 | MODULE_DEVICE_TABLE(pci, azx_ids); | 1968 | MODULE_DEVICE_TABLE(pci, azx_ids); |
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index f91ea5ec9f6d..a79d0ed5469c 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -26,7 +26,8 @@ | |||
26 | /* | 26 | /* |
27 | * for mixer controls | 27 | * for mixer controls |
28 | */ | 28 | */ |
29 | #define HDA_COMPOSE_AMP_VAL(nid,chs,idx,dir) ((nid) | ((chs)<<16) | ((dir)<<18) | ((idx)<<19)) | 29 | #define HDA_COMPOSE_AMP_VAL(nid,chs,idx,dir) \ |
30 | ((nid) | ((chs)<<16) | ((dir)<<18) | ((idx)<<19)) | ||
30 | /* mono volume with index (index=0,1,...) (channel=1,2) */ | 31 | /* mono volume with index (index=0,1,...) (channel=1,2) */ |
31 | #define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ | 32 | #define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ |
32 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ | 33 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ |
@@ -64,18 +65,35 @@ | |||
64 | #define HDA_CODEC_MUTE(xname, nid, xindex, direction) \ | 65 | #define HDA_CODEC_MUTE(xname, nid, xindex, direction) \ |
65 | HDA_CODEC_MUTE_MONO(xname, nid, 3, xindex, direction) | 66 | HDA_CODEC_MUTE_MONO(xname, nid, 3, xindex, direction) |
66 | 67 | ||
67 | int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); | 68 | int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, |
68 | int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); | 69 | struct snd_ctl_elem_info *uinfo); |
69 | int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); | 70 | int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, |
70 | int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, unsigned int size, unsigned int __user *tlv); | 71 | struct snd_ctl_elem_value *ucontrol); |
71 | int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); | 72 | int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, |
72 | int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); | 73 | struct snd_ctl_elem_value *ucontrol); |
73 | int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); | 74 | int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, |
75 | unsigned int size, unsigned int __user *tlv); | ||
76 | int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, | ||
77 | struct snd_ctl_elem_info *uinfo); | ||
78 | int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol, | ||
79 | struct snd_ctl_elem_value *ucontrol); | ||
80 | int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, | ||
81 | struct snd_ctl_elem_value *ucontrol); | ||
74 | /* lowlevel accessor with caching; use carefully */ | 82 | /* lowlevel accessor with caching; use carefully */ |
75 | int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, | 83 | int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, |
76 | int direction, int index); | 84 | int direction, int index); |
77 | int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch, | 85 | int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch, |
78 | int direction, int idx, int mask, int val); | 86 | int direction, int idx, int mask, int val); |
87 | int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid, | ||
88 | int dir, int idx, int mask, int val); | ||
89 | #ifdef SND_HDA_NEEDS_RESUME | ||
90 | void snd_hda_codec_resume_amp(struct hda_codec *codec); | ||
91 | #endif | ||
92 | |||
93 | /* amp value bits */ | ||
94 | #define HDA_AMP_MUTE 0x80 | ||
95 | #define HDA_AMP_UNMUTE 0x00 | ||
96 | #define HDA_AMP_VOLMASK 0x7f | ||
79 | 97 | ||
80 | /* mono switch binding multiple inputs */ | 98 | /* mono switch binding multiple inputs */ |
81 | #define HDA_BIND_MUTE_MONO(xname, nid, channel, indices, direction) \ | 99 | #define HDA_BIND_MUTE_MONO(xname, nid, channel, indices, direction) \ |
@@ -86,11 +104,61 @@ int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch, | |||
86 | .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, indices, direction) } | 104 | .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, indices, direction) } |
87 | 105 | ||
88 | /* stereo switch binding multiple inputs */ | 106 | /* stereo switch binding multiple inputs */ |
89 | #define HDA_BIND_MUTE(xname,nid,indices,dir) HDA_BIND_MUTE_MONO(xname,nid,3,indices,dir) | 107 | #define HDA_BIND_MUTE(xname,nid,indices,dir) \ |
108 | HDA_BIND_MUTE_MONO(xname,nid,3,indices,dir) | ||
109 | |||
110 | int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol, | ||
111 | struct snd_ctl_elem_value *ucontrol); | ||
112 | int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol, | ||
113 | struct snd_ctl_elem_value *ucontrol); | ||
114 | |||
115 | /* more generic bound controls */ | ||
116 | struct hda_ctl_ops { | ||
117 | snd_kcontrol_info_t *info; | ||
118 | snd_kcontrol_get_t *get; | ||
119 | snd_kcontrol_put_t *put; | ||
120 | snd_kcontrol_tlv_rw_t *tlv; | ||
121 | }; | ||
90 | 122 | ||
91 | int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); | 123 | extern struct hda_ctl_ops snd_hda_bind_vol; /* for bind-volume with TLV */ |
92 | int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); | 124 | extern struct hda_ctl_ops snd_hda_bind_sw; /* for bind-switch */ |
93 | 125 | ||
126 | struct hda_bind_ctls { | ||
127 | struct hda_ctl_ops *ops; | ||
128 | long values[]; | ||
129 | }; | ||
130 | |||
131 | int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol, | ||
132 | struct snd_ctl_elem_info *uinfo); | ||
133 | int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol, | ||
134 | struct snd_ctl_elem_value *ucontrol); | ||
135 | int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol, | ||
136 | struct snd_ctl_elem_value *ucontrol); | ||
137 | int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag, | ||
138 | unsigned int size, unsigned int __user *tlv); | ||
139 | |||
140 | #define HDA_BIND_VOL(xname, bindrec) \ | ||
141 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
142 | .name = xname, \ | ||
143 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\ | ||
144 | SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ | ||
145 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK,\ | ||
146 | .info = snd_hda_mixer_bind_ctls_info,\ | ||
147 | .get = snd_hda_mixer_bind_ctls_get,\ | ||
148 | .put = snd_hda_mixer_bind_ctls_put,\ | ||
149 | .tlv = { .c = snd_hda_mixer_bind_tlv },\ | ||
150 | .private_value = (long) (bindrec) } | ||
151 | #define HDA_BIND_SW(xname, bindrec) \ | ||
152 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,\ | ||
153 | .name = xname, \ | ||
154 | .info = snd_hda_mixer_bind_ctls_info,\ | ||
155 | .get = snd_hda_mixer_bind_ctls_get,\ | ||
156 | .put = snd_hda_mixer_bind_ctls_put,\ | ||
157 | .private_value = (long) (bindrec) } | ||
158 | |||
159 | /* | ||
160 | * SPDIF I/O | ||
161 | */ | ||
94 | int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid); | 162 | int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid); |
95 | int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid); | 163 | int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid); |
96 | 164 | ||
@@ -107,8 +175,10 @@ struct hda_input_mux { | |||
107 | struct hda_input_mux_item items[HDA_MAX_NUM_INPUTS]; | 175 | struct hda_input_mux_item items[HDA_MAX_NUM_INPUTS]; |
108 | }; | 176 | }; |
109 | 177 | ||
110 | int snd_hda_input_mux_info(const struct hda_input_mux *imux, struct snd_ctl_elem_info *uinfo); | 178 | int snd_hda_input_mux_info(const struct hda_input_mux *imux, |
111 | int snd_hda_input_mux_put(struct hda_codec *codec, const struct hda_input_mux *imux, | 179 | struct snd_ctl_elem_info *uinfo); |
180 | int snd_hda_input_mux_put(struct hda_codec *codec, | ||
181 | const struct hda_input_mux *imux, | ||
112 | struct snd_ctl_elem_value *ucontrol, hda_nid_t nid, | 182 | struct snd_ctl_elem_value *ucontrol, hda_nid_t nid, |
113 | unsigned int *cur_val); | 183 | unsigned int *cur_val); |
114 | 184 | ||
@@ -120,13 +190,19 @@ struct hda_channel_mode { | |||
120 | const struct hda_verb *sequence; | 190 | const struct hda_verb *sequence; |
121 | }; | 191 | }; |
122 | 192 | ||
123 | int snd_hda_ch_mode_info(struct hda_codec *codec, struct snd_ctl_elem_info *uinfo, | 193 | int snd_hda_ch_mode_info(struct hda_codec *codec, |
124 | const struct hda_channel_mode *chmode, int num_chmodes); | 194 | struct snd_ctl_elem_info *uinfo, |
125 | int snd_hda_ch_mode_get(struct hda_codec *codec, struct snd_ctl_elem_value *ucontrol, | 195 | const struct hda_channel_mode *chmode, |
126 | const struct hda_channel_mode *chmode, int num_chmodes, | 196 | int num_chmodes); |
197 | int snd_hda_ch_mode_get(struct hda_codec *codec, | ||
198 | struct snd_ctl_elem_value *ucontrol, | ||
199 | const struct hda_channel_mode *chmode, | ||
200 | int num_chmodes, | ||
127 | int max_channels); | 201 | int max_channels); |
128 | int snd_hda_ch_mode_put(struct hda_codec *codec, struct snd_ctl_elem_value *ucontrol, | 202 | int snd_hda_ch_mode_put(struct hda_codec *codec, |
129 | const struct hda_channel_mode *chmode, int num_chmodes, | 203 | struct snd_ctl_elem_value *ucontrol, |
204 | const struct hda_channel_mode *chmode, | ||
205 | int num_chmodes, | ||
130 | int *max_channelsp); | 206 | int *max_channelsp); |
131 | 207 | ||
132 | /* | 208 | /* |
@@ -146,20 +222,25 @@ struct hda_multi_out { | |||
146 | int dig_out_used; /* current usage of digital out (HDA_DIG_XXX) */ | 222 | int dig_out_used; /* current usage of digital out (HDA_DIG_XXX) */ |
147 | }; | 223 | }; |
148 | 224 | ||
149 | int snd_hda_multi_out_dig_open(struct hda_codec *codec, struct hda_multi_out *mout); | 225 | int snd_hda_multi_out_dig_open(struct hda_codec *codec, |
150 | int snd_hda_multi_out_dig_close(struct hda_codec *codec, struct hda_multi_out *mout); | 226 | struct hda_multi_out *mout); |
227 | int snd_hda_multi_out_dig_close(struct hda_codec *codec, | ||
228 | struct hda_multi_out *mout); | ||
151 | int snd_hda_multi_out_dig_prepare(struct hda_codec *codec, | 229 | int snd_hda_multi_out_dig_prepare(struct hda_codec *codec, |
152 | struct hda_multi_out *mout, | 230 | struct hda_multi_out *mout, |
153 | unsigned int stream_tag, | 231 | unsigned int stream_tag, |
154 | unsigned int format, | 232 | unsigned int format, |
155 | struct snd_pcm_substream *substream); | 233 | struct snd_pcm_substream *substream); |
156 | int snd_hda_multi_out_analog_open(struct hda_codec *codec, struct hda_multi_out *mout, | 234 | int snd_hda_multi_out_analog_open(struct hda_codec *codec, |
235 | struct hda_multi_out *mout, | ||
157 | struct snd_pcm_substream *substream); | 236 | struct snd_pcm_substream *substream); |
158 | int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_out *mout, | 237 | int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, |
238 | struct hda_multi_out *mout, | ||
159 | unsigned int stream_tag, | 239 | unsigned int stream_tag, |
160 | unsigned int format, | 240 | unsigned int format, |
161 | struct snd_pcm_substream *substream); | 241 | struct snd_pcm_substream *substream); |
162 | int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, struct hda_multi_out *mout); | 242 | int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, |
243 | struct hda_multi_out *mout); | ||
163 | 244 | ||
164 | /* | 245 | /* |
165 | * generic codec parser | 246 | * generic codec parser |
@@ -181,16 +262,8 @@ static inline int snd_hda_codec_proc_new(struct hda_codec *codec) { return 0; } | |||
181 | int snd_hda_check_board_config(struct hda_codec *codec, int num_configs, | 262 | int snd_hda_check_board_config(struct hda_codec *codec, int num_configs, |
182 | const char **modelnames, | 263 | const char **modelnames, |
183 | const struct snd_pci_quirk *pci_list); | 264 | const struct snd_pci_quirk *pci_list); |
184 | int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew); | 265 | int snd_hda_add_new_ctls(struct hda_codec *codec, |
185 | 266 | struct snd_kcontrol_new *knew); | |
186 | /* | ||
187 | * power management | ||
188 | */ | ||
189 | #ifdef CONFIG_PM | ||
190 | int snd_hda_resume_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew); | ||
191 | int snd_hda_resume_spdif_out(struct hda_codec *codec); | ||
192 | int snd_hda_resume_spdif_in(struct hda_codec *codec); | ||
193 | #endif | ||
194 | 267 | ||
195 | /* | 268 | /* |
196 | * unsolicited event handler | 269 | * unsolicited event handler |
@@ -232,7 +305,9 @@ extern const char *auto_pin_cfg_labels[AUTO_PIN_LAST]; | |||
232 | 305 | ||
233 | struct auto_pin_cfg { | 306 | struct auto_pin_cfg { |
234 | int line_outs; | 307 | int line_outs; |
235 | hda_nid_t line_out_pins[5]; /* sorted in the order of Front/Surr/CLFE/Side */ | 308 | hda_nid_t line_out_pins[5]; /* sorted in the order of |
309 | * Front/Surr/CLFE/Side | ||
310 | */ | ||
236 | int speaker_outs; | 311 | int speaker_outs; |
237 | hda_nid_t speaker_pins[5]; | 312 | hda_nid_t speaker_pins[5]; |
238 | int hp_outs; | 313 | int hp_outs; |
@@ -243,13 +318,19 @@ struct auto_pin_cfg { | |||
243 | hda_nid_t dig_in_pin; | 318 | hda_nid_t dig_in_pin; |
244 | }; | 319 | }; |
245 | 320 | ||
246 | #define get_defcfg_connect(cfg) ((cfg & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT) | 321 | #define get_defcfg_connect(cfg) \ |
247 | #define get_defcfg_association(cfg) ((cfg & AC_DEFCFG_DEF_ASSOC) >> AC_DEFCFG_ASSOC_SHIFT) | 322 | ((cfg & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT) |
248 | #define get_defcfg_location(cfg) ((cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT) | 323 | #define get_defcfg_association(cfg) \ |
249 | #define get_defcfg_sequence(cfg) (cfg & AC_DEFCFG_SEQUENCE) | 324 | ((cfg & AC_DEFCFG_DEF_ASSOC) >> AC_DEFCFG_ASSOC_SHIFT) |
250 | #define get_defcfg_device(cfg) ((cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT) | 325 | #define get_defcfg_location(cfg) \ |
251 | 326 | ((cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT) | |
252 | int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *cfg, | 327 | #define get_defcfg_sequence(cfg) \ |
328 | (cfg & AC_DEFCFG_SEQUENCE) | ||
329 | #define get_defcfg_device(cfg) \ | ||
330 | ((cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT) | ||
331 | |||
332 | int snd_hda_parse_pin_def_config(struct hda_codec *codec, | ||
333 | struct auto_pin_cfg *cfg, | ||
253 | hda_nid_t *ignore_nids); | 334 | hda_nid_t *ignore_nids); |
254 | 335 | ||
255 | /* amp values */ | 336 | /* amp values */ |
@@ -280,4 +361,32 @@ static inline u32 get_wcaps(struct hda_codec *codec, hda_nid_t nid) | |||
280 | int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, | 361 | int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, |
281 | unsigned int caps); | 362 | unsigned int caps); |
282 | 363 | ||
364 | /* | ||
365 | * hwdep interface | ||
366 | */ | ||
367 | int snd_hda_create_hwdep(struct hda_codec *codec); | ||
368 | |||
369 | /* | ||
370 | * power-management | ||
371 | */ | ||
372 | |||
373 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
374 | void snd_hda_schedule_power_save(struct hda_codec *codec); | ||
375 | |||
376 | struct hda_amp_list { | ||
377 | hda_nid_t nid; | ||
378 | unsigned char dir; | ||
379 | unsigned char idx; | ||
380 | }; | ||
381 | |||
382 | struct hda_loopback_check { | ||
383 | struct hda_amp_list *amplist; | ||
384 | int power_on; | ||
385 | }; | ||
386 | |||
387 | int snd_hda_check_amp_list_power(struct hda_codec *codec, | ||
388 | struct hda_loopback_check *check, | ||
389 | hda_nid_t nid); | ||
390 | #endif /* CONFIG_SND_HDA_POWER_SAVE */ | ||
391 | |||
283 | #endif /* __SOUND_HDA_LOCAL_H */ | 392 | #endif /* __SOUND_HDA_LOCAL_H */ |
diff --git a/sound/pci/hda/hda_patch.h b/sound/pci/hda/hda_patch.h index 9f9e9ae44a9d..f5c23bb16d7e 100644 --- a/sound/pci/hda/hda_patch.h +++ b/sound/pci/hda/hda_patch.h | |||
@@ -20,13 +20,29 @@ extern struct hda_codec_preset snd_hda_preset_conexant[]; | |||
20 | extern struct hda_codec_preset snd_hda_preset_via[]; | 20 | extern struct hda_codec_preset snd_hda_preset_via[]; |
21 | 21 | ||
22 | static const struct hda_codec_preset *hda_preset_tables[] = { | 22 | static const struct hda_codec_preset *hda_preset_tables[] = { |
23 | #ifdef CONFIG_SND_HDA_CODEC_REALTEK | ||
23 | snd_hda_preset_realtek, | 24 | snd_hda_preset_realtek, |
25 | #endif | ||
26 | #ifdef CONFIG_SND_HDA_CODEC_CMEDIA | ||
24 | snd_hda_preset_cmedia, | 27 | snd_hda_preset_cmedia, |
28 | #endif | ||
29 | #ifdef CONFIG_SND_HDA_CODEC_ANALOG | ||
25 | snd_hda_preset_analog, | 30 | snd_hda_preset_analog, |
31 | #endif | ||
32 | #ifdef CONFIG_SND_HDA_CODEC_SIGMATEL | ||
26 | snd_hda_preset_sigmatel, | 33 | snd_hda_preset_sigmatel, |
34 | #endif | ||
35 | #ifdef CONFIG_SND_HDA_CODEC_SI3054 | ||
27 | snd_hda_preset_si3054, | 36 | snd_hda_preset_si3054, |
37 | #endif | ||
38 | #ifdef CONFIG_SND_HDA_CODEC_ATIHDMI | ||
28 | snd_hda_preset_atihdmi, | 39 | snd_hda_preset_atihdmi, |
40 | #endif | ||
41 | #ifdef CONFIG_SND_HDA_CODEC_CONEXANT | ||
29 | snd_hda_preset_conexant, | 42 | snd_hda_preset_conexant, |
43 | #endif | ||
44 | #ifdef CONFIG_SND_HDA_CODEC_VIA | ||
30 | snd_hda_preset_via, | 45 | snd_hda_preset_via, |
46 | #endif | ||
31 | NULL | 47 | NULL |
32 | }; | 48 | }; |
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index ac15066fd300..e94944f34ffd 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c | |||
@@ -58,7 +58,8 @@ static void print_amp_caps(struct snd_info_buffer *buffer, | |||
58 | snd_iprintf(buffer, "N/A\n"); | 58 | snd_iprintf(buffer, "N/A\n"); |
59 | return; | 59 | return; |
60 | } | 60 | } |
61 | snd_iprintf(buffer, "ofs=0x%02x, nsteps=0x%02x, stepsize=0x%02x, mute=%x\n", | 61 | snd_iprintf(buffer, "ofs=0x%02x, nsteps=0x%02x, stepsize=0x%02x, " |
62 | "mute=%x\n", | ||
62 | caps & AC_AMPCAP_OFFSET, | 63 | caps & AC_AMPCAP_OFFSET, |
63 | (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT, | 64 | (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT, |
64 | (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT, | 65 | (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT, |
@@ -76,11 +77,13 @@ static void print_amp_vals(struct snd_info_buffer *buffer, | |||
76 | for (i = 0; i < indices; i++) { | 77 | for (i = 0; i < indices; i++) { |
77 | snd_iprintf(buffer, " ["); | 78 | snd_iprintf(buffer, " ["); |
78 | if (stereo) { | 79 | if (stereo) { |
79 | val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, | 80 | val = snd_hda_codec_read(codec, nid, 0, |
81 | AC_VERB_GET_AMP_GAIN_MUTE, | ||
80 | AC_AMP_GET_LEFT | dir | i); | 82 | AC_AMP_GET_LEFT | dir | i); |
81 | snd_iprintf(buffer, "0x%02x ", val); | 83 | snd_iprintf(buffer, "0x%02x ", val); |
82 | } | 84 | } |
83 | val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, | 85 | val = snd_hda_codec_read(codec, nid, 0, |
86 | AC_VERB_GET_AMP_GAIN_MUTE, | ||
84 | AC_AMP_GET_RIGHT | dir | i); | 87 | AC_AMP_GET_RIGHT | dir | i); |
85 | snd_iprintf(buffer, "0x%02x]", val); | 88 | snd_iprintf(buffer, "0x%02x]", val); |
86 | } | 89 | } |
@@ -237,7 +240,8 @@ static void print_pin_caps(struct snd_info_buffer *buffer, | |||
237 | } | 240 | } |
238 | 241 | ||
239 | 242 | ||
240 | static void print_codec_info(struct snd_info_entry *entry, struct snd_info_buffer *buffer) | 243 | static void print_codec_info(struct snd_info_entry *entry, |
244 | struct snd_info_buffer *buffer) | ||
241 | { | 245 | { |
242 | struct hda_codec *codec = entry->private_data; | 246 | struct hda_codec *codec = entry->private_data; |
243 | char buf[32]; | 247 | char buf[32]; |
@@ -258,6 +262,7 @@ static void print_codec_info(struct snd_info_entry *entry, struct snd_info_buffe | |||
258 | 262 | ||
259 | if (! codec->afg) | 263 | if (! codec->afg) |
260 | return; | 264 | return; |
265 | snd_hda_power_up(codec); | ||
261 | snd_iprintf(buffer, "Default PCM:\n"); | 266 | snd_iprintf(buffer, "Default PCM:\n"); |
262 | print_pcm_caps(buffer, codec, codec->afg); | 267 | print_pcm_caps(buffer, codec, codec->afg); |
263 | snd_iprintf(buffer, "Default Amp-In caps: "); | 268 | snd_iprintf(buffer, "Default Amp-In caps: "); |
@@ -268,12 +273,15 @@ static void print_codec_info(struct snd_info_entry *entry, struct snd_info_buffe | |||
268 | nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid); | 273 | nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid); |
269 | if (! nid || nodes < 0) { | 274 | if (! nid || nodes < 0) { |
270 | snd_iprintf(buffer, "Invalid AFG subtree\n"); | 275 | snd_iprintf(buffer, "Invalid AFG subtree\n"); |
276 | snd_hda_power_down(codec); | ||
271 | return; | 277 | return; |
272 | } | 278 | } |
273 | for (i = 0; i < nodes; i++, nid++) { | 279 | for (i = 0; i < nodes; i++, nid++) { |
274 | unsigned int wid_caps = snd_hda_param_read(codec, nid, | 280 | unsigned int wid_caps = |
275 | AC_PAR_AUDIO_WIDGET_CAP); | 281 | snd_hda_param_read(codec, nid, |
276 | unsigned int wid_type = (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; | 282 | AC_PAR_AUDIO_WIDGET_CAP); |
283 | unsigned int wid_type = | ||
284 | (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; | ||
277 | int conn_len = 0; | 285 | int conn_len = 0; |
278 | hda_nid_t conn[HDA_MAX_CONNECTIONS]; | 286 | hda_nid_t conn[HDA_MAX_CONNECTIONS]; |
279 | 287 | ||
@@ -313,7 +321,9 @@ static void print_codec_info(struct snd_info_entry *entry, struct snd_info_buffe | |||
313 | if (wid_type == AC_WID_PIN) { | 321 | if (wid_type == AC_WID_PIN) { |
314 | unsigned int pinctls; | 322 | unsigned int pinctls; |
315 | print_pin_caps(buffer, codec, nid); | 323 | print_pin_caps(buffer, codec, nid); |
316 | pinctls = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | 324 | pinctls = snd_hda_codec_read(codec, nid, 0, |
325 | AC_VERB_GET_PIN_WIDGET_CONTROL, | ||
326 | 0); | ||
317 | snd_iprintf(buffer, " Pin-ctls: 0x%02x:", pinctls); | 327 | snd_iprintf(buffer, " Pin-ctls: 0x%02x:", pinctls); |
318 | if (pinctls & AC_PINCTL_IN_EN) | 328 | if (pinctls & AC_PINCTL_IN_EN) |
319 | snd_iprintf(buffer, " IN"); | 329 | snd_iprintf(buffer, " IN"); |
@@ -333,7 +343,8 @@ static void print_codec_info(struct snd_info_entry *entry, struct snd_info_buffe | |||
333 | if (wid_caps & AC_WCAP_POWER) | 343 | if (wid_caps & AC_WCAP_POWER) |
334 | snd_iprintf(buffer, " Power: 0x%x\n", | 344 | snd_iprintf(buffer, " Power: 0x%x\n", |
335 | snd_hda_codec_read(codec, nid, 0, | 345 | snd_hda_codec_read(codec, nid, 0, |
336 | AC_VERB_GET_POWER_STATE, 0)); | 346 | AC_VERB_GET_POWER_STATE, |
347 | 0)); | ||
337 | 348 | ||
338 | if (wid_caps & AC_WCAP_CONN_LIST) { | 349 | if (wid_caps & AC_WCAP_CONN_LIST) { |
339 | int c, curr = -1; | 350 | int c, curr = -1; |
@@ -350,6 +361,7 @@ static void print_codec_info(struct snd_info_entry *entry, struct snd_info_buffe | |||
350 | snd_iprintf(buffer, "\n"); | 361 | snd_iprintf(buffer, "\n"); |
351 | } | 362 | } |
352 | } | 363 | } |
364 | snd_hda_power_down(codec); | ||
353 | } | 365 | } |
354 | 366 | ||
355 | /* | 367 | /* |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 4d7f8d11ad75..54cfd4526d20 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -73,6 +73,12 @@ struct ad198x_spec { | |||
73 | struct snd_kcontrol_new *kctl_alloc; | 73 | struct snd_kcontrol_new *kctl_alloc; |
74 | struct hda_input_mux private_imux; | 74 | struct hda_input_mux private_imux; |
75 | hda_nid_t private_dac_nids[4]; | 75 | hda_nid_t private_dac_nids[4]; |
76 | |||
77 | unsigned int jack_present :1; | ||
78 | |||
79 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
80 | struct hda_loopback_check loopback; | ||
81 | #endif | ||
76 | }; | 82 | }; |
77 | 83 | ||
78 | /* | 84 | /* |
@@ -144,6 +150,14 @@ static int ad198x_build_controls(struct hda_codec *codec) | |||
144 | return 0; | 150 | return 0; |
145 | } | 151 | } |
146 | 152 | ||
153 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
154 | static int ad198x_check_power_status(struct hda_codec *codec, hda_nid_t nid) | ||
155 | { | ||
156 | struct ad198x_spec *spec = codec->spec; | ||
157 | return snd_hda_check_amp_list_power(codec, &spec->loopback, nid); | ||
158 | } | ||
159 | #endif | ||
160 | |||
147 | /* | 161 | /* |
148 | * Analog playback callbacks | 162 | * Analog playback callbacks |
149 | */ | 163 | */ |
@@ -318,30 +332,13 @@ static void ad198x_free(struct hda_codec *codec) | |||
318 | kfree(codec->spec); | 332 | kfree(codec->spec); |
319 | } | 333 | } |
320 | 334 | ||
321 | #ifdef CONFIG_PM | ||
322 | static int ad198x_resume(struct hda_codec *codec) | ||
323 | { | ||
324 | struct ad198x_spec *spec = codec->spec; | ||
325 | int i; | ||
326 | |||
327 | codec->patch_ops.init(codec); | ||
328 | for (i = 0; i < spec->num_mixers; i++) | ||
329 | snd_hda_resume_ctls(codec, spec->mixers[i]); | ||
330 | if (spec->multiout.dig_out_nid) | ||
331 | snd_hda_resume_spdif_out(codec); | ||
332 | if (spec->dig_in_nid) | ||
333 | snd_hda_resume_spdif_in(codec); | ||
334 | return 0; | ||
335 | } | ||
336 | #endif | ||
337 | |||
338 | static struct hda_codec_ops ad198x_patch_ops = { | 335 | static struct hda_codec_ops ad198x_patch_ops = { |
339 | .build_controls = ad198x_build_controls, | 336 | .build_controls = ad198x_build_controls, |
340 | .build_pcms = ad198x_build_pcms, | 337 | .build_pcms = ad198x_build_pcms, |
341 | .init = ad198x_init, | 338 | .init = ad198x_init, |
342 | .free = ad198x_free, | 339 | .free = ad198x_free, |
343 | #ifdef CONFIG_PM | 340 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
344 | .resume = ad198x_resume, | 341 | .check_power_status = ad198x_check_power_status, |
345 | #endif | 342 | #endif |
346 | }; | 343 | }; |
347 | 344 | ||
@@ -350,15 +347,7 @@ static struct hda_codec_ops ad198x_patch_ops = { | |||
350 | * EAPD control | 347 | * EAPD control |
351 | * the private value = nid | (invert << 8) | 348 | * the private value = nid | (invert << 8) |
352 | */ | 349 | */ |
353 | static int ad198x_eapd_info(struct snd_kcontrol *kcontrol, | 350 | #define ad198x_eapd_info snd_ctl_boolean_mono_info |
354 | struct snd_ctl_elem_info *uinfo) | ||
355 | { | ||
356 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
357 | uinfo->count = 1; | ||
358 | uinfo->value.integer.min = 0; | ||
359 | uinfo->value.integer.max = 1; | ||
360 | return 0; | ||
361 | } | ||
362 | 351 | ||
363 | static int ad198x_eapd_get(struct snd_kcontrol *kcontrol, | 352 | static int ad198x_eapd_get(struct snd_kcontrol *kcontrol, |
364 | struct snd_ctl_elem_value *ucontrol) | 353 | struct snd_ctl_elem_value *ucontrol) |
@@ -384,12 +373,12 @@ static int ad198x_eapd_put(struct snd_kcontrol *kcontrol, | |||
384 | eapd = ucontrol->value.integer.value[0]; | 373 | eapd = ucontrol->value.integer.value[0]; |
385 | if (invert) | 374 | if (invert) |
386 | eapd = !eapd; | 375 | eapd = !eapd; |
387 | if (eapd == spec->cur_eapd && ! codec->in_resume) | 376 | if (eapd == spec->cur_eapd) |
388 | return 0; | 377 | return 0; |
389 | spec->cur_eapd = eapd; | 378 | spec->cur_eapd = eapd; |
390 | snd_hda_codec_write(codec, nid, | 379 | snd_hda_codec_write_cache(codec, nid, |
391 | 0, AC_VERB_SET_EAPD_BTLENABLE, | 380 | 0, AC_VERB_SET_EAPD_BTLENABLE, |
392 | eapd ? 0x02 : 0x00); | 381 | eapd ? 0x02 : 0x00); |
393 | return 1; | 382 | return 1; |
394 | } | 383 | } |
395 | 384 | ||
@@ -430,94 +419,36 @@ static struct hda_input_mux ad1986a_capture_source = { | |||
430 | }, | 419 | }, |
431 | }; | 420 | }; |
432 | 421 | ||
433 | /* | ||
434 | * PCM control | ||
435 | * | ||
436 | * bind volumes/mutes of 3 DACs as a single PCM control for simplicity | ||
437 | */ | ||
438 | |||
439 | #define ad1986a_pcm_amp_vol_info snd_hda_mixer_amp_volume_info | ||
440 | |||
441 | static int ad1986a_pcm_amp_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
442 | { | ||
443 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
444 | struct ad198x_spec *ad = codec->spec; | ||
445 | |||
446 | mutex_lock(&ad->amp_mutex); | ||
447 | snd_hda_mixer_amp_volume_get(kcontrol, ucontrol); | ||
448 | mutex_unlock(&ad->amp_mutex); | ||
449 | return 0; | ||
450 | } | ||
451 | |||
452 | static int ad1986a_pcm_amp_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
453 | { | ||
454 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
455 | struct ad198x_spec *ad = codec->spec; | ||
456 | int i, change = 0; | ||
457 | |||
458 | mutex_lock(&ad->amp_mutex); | ||
459 | for (i = 0; i < ARRAY_SIZE(ad1986a_dac_nids); i++) { | ||
460 | kcontrol->private_value = HDA_COMPOSE_AMP_VAL(ad1986a_dac_nids[i], 3, 0, HDA_OUTPUT); | ||
461 | change |= snd_hda_mixer_amp_volume_put(kcontrol, ucontrol); | ||
462 | } | ||
463 | kcontrol->private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT); | ||
464 | mutex_unlock(&ad->amp_mutex); | ||
465 | return change; | ||
466 | } | ||
467 | |||
468 | #define ad1986a_pcm_amp_sw_info snd_hda_mixer_amp_switch_info | ||
469 | 422 | ||
470 | static int ad1986a_pcm_amp_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 423 | static struct hda_bind_ctls ad1986a_bind_pcm_vol = { |
471 | { | 424 | .ops = &snd_hda_bind_vol, |
472 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 425 | .values = { |
473 | struct ad198x_spec *ad = codec->spec; | 426 | HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT), |
474 | 427 | HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT), | |
475 | mutex_lock(&ad->amp_mutex); | 428 | HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT), |
476 | snd_hda_mixer_amp_switch_get(kcontrol, ucontrol); | 429 | 0 |
477 | mutex_unlock(&ad->amp_mutex); | 430 | }, |
478 | return 0; | 431 | }; |
479 | } | ||
480 | |||
481 | static int ad1986a_pcm_amp_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
482 | { | ||
483 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
484 | struct ad198x_spec *ad = codec->spec; | ||
485 | int i, change = 0; | ||
486 | 432 | ||
487 | mutex_lock(&ad->amp_mutex); | 433 | static struct hda_bind_ctls ad1986a_bind_pcm_sw = { |
488 | for (i = 0; i < ARRAY_SIZE(ad1986a_dac_nids); i++) { | 434 | .ops = &snd_hda_bind_sw, |
489 | kcontrol->private_value = HDA_COMPOSE_AMP_VAL(ad1986a_dac_nids[i], 3, 0, HDA_OUTPUT); | 435 | .values = { |
490 | change |= snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); | 436 | HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT), |
491 | } | 437 | HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT), |
492 | kcontrol->private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT); | 438 | HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT), |
493 | mutex_unlock(&ad->amp_mutex); | 439 | 0 |
494 | return change; | 440 | }, |
495 | } | 441 | }; |
496 | 442 | ||
497 | /* | 443 | /* |
498 | * mixers | 444 | * mixers |
499 | */ | 445 | */ |
500 | static struct snd_kcontrol_new ad1986a_mixers[] = { | 446 | static struct snd_kcontrol_new ad1986a_mixers[] = { |
501 | { | 447 | /* |
502 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 448 | * bind volumes/mutes of 3 DACs as a single PCM control for simplicity |
503 | .name = "PCM Playback Volume", | 449 | */ |
504 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | | 450 | HDA_BIND_VOL("PCM Playback Volume", &ad1986a_bind_pcm_vol), |
505 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | | 451 | HDA_BIND_SW("PCM Playback Switch", &ad1986a_bind_pcm_sw), |
506 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, | ||
507 | .info = ad1986a_pcm_amp_vol_info, | ||
508 | .get = ad1986a_pcm_amp_vol_get, | ||
509 | .put = ad1986a_pcm_amp_vol_put, | ||
510 | .tlv = { .c = snd_hda_mixer_amp_tlv }, | ||
511 | .private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT) | ||
512 | }, | ||
513 | { | ||
514 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
515 | .name = "PCM Playback Switch", | ||
516 | .info = ad1986a_pcm_amp_sw_info, | ||
517 | .get = ad1986a_pcm_amp_sw_get, | ||
518 | .put = ad1986a_pcm_amp_sw_put, | ||
519 | .private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT) | ||
520 | }, | ||
521 | HDA_CODEC_VOLUME("Front Playback Volume", 0x1b, 0x0, HDA_OUTPUT), | 452 | HDA_CODEC_VOLUME("Front Playback Volume", 0x1b, 0x0, HDA_OUTPUT), |
522 | HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | 453 | HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT), |
523 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x1c, 0x0, HDA_OUTPUT), | 454 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x1c, 0x0, HDA_OUTPUT), |
@@ -569,13 +500,30 @@ static struct snd_kcontrol_new ad1986a_3st_mixers[] = { | |||
569 | /* laptop model - 2ch only */ | 500 | /* laptop model - 2ch only */ |
570 | static hda_nid_t ad1986a_laptop_dac_nids[1] = { AD1986A_FRONT_DAC }; | 501 | static hda_nid_t ad1986a_laptop_dac_nids[1] = { AD1986A_FRONT_DAC }; |
571 | 502 | ||
503 | /* master controls both pins 0x1a and 0x1b */ | ||
504 | static struct hda_bind_ctls ad1986a_laptop_master_vol = { | ||
505 | .ops = &snd_hda_bind_vol, | ||
506 | .values = { | ||
507 | HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT), | ||
508 | HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT), | ||
509 | 0, | ||
510 | }, | ||
511 | }; | ||
512 | |||
513 | static struct hda_bind_ctls ad1986a_laptop_master_sw = { | ||
514 | .ops = &snd_hda_bind_sw, | ||
515 | .values = { | ||
516 | HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT), | ||
517 | HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT), | ||
518 | 0, | ||
519 | }, | ||
520 | }; | ||
521 | |||
572 | static struct snd_kcontrol_new ad1986a_laptop_mixers[] = { | 522 | static struct snd_kcontrol_new ad1986a_laptop_mixers[] = { |
573 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT), | 523 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT), |
574 | HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), | 524 | HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), |
575 | HDA_CODEC_VOLUME("Master Playback Volume", 0x1b, 0x0, HDA_OUTPUT), | 525 | HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol), |
576 | HDA_CODEC_MUTE("Master Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | 526 | HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw), |
577 | /* HDA_CODEC_VOLUME("Headphone Playback Volume", 0x1a, 0x0, HDA_OUTPUT), | ||
578 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT), */ | ||
579 | HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT), | 527 | HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT), |
580 | HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT), | 528 | HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT), |
581 | HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT), | 529 | HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT), |
@@ -603,68 +551,114 @@ static struct snd_kcontrol_new ad1986a_laptop_mixers[] = { | |||
603 | 551 | ||
604 | /* laptop-eapd model - 2ch only */ | 552 | /* laptop-eapd model - 2ch only */ |
605 | 553 | ||
606 | /* master controls both pins 0x1a and 0x1b */ | 554 | static struct hda_input_mux ad1986a_laptop_eapd_capture_source = { |
607 | static int ad1986a_laptop_master_vol_put(struct snd_kcontrol *kcontrol, | 555 | .num_items = 3, |
608 | struct snd_ctl_elem_value *ucontrol) | 556 | .items = { |
557 | { "Mic", 0x0 }, | ||
558 | { "Internal Mic", 0x4 }, | ||
559 | { "Mix", 0x5 }, | ||
560 | }, | ||
561 | }; | ||
562 | |||
563 | static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = { | ||
564 | HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol), | ||
565 | HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw), | ||
566 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT), | ||
567 | HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), | ||
568 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x0, HDA_OUTPUT), | ||
569 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0x0, HDA_OUTPUT), | ||
570 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), | ||
571 | HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), | ||
572 | HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT), | ||
573 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), | ||
574 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT), | ||
575 | { | ||
576 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
577 | .name = "Capture Source", | ||
578 | .info = ad198x_mux_enum_info, | ||
579 | .get = ad198x_mux_enum_get, | ||
580 | .put = ad198x_mux_enum_put, | ||
581 | }, | ||
582 | { | ||
583 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
584 | .name = "External Amplifier", | ||
585 | .info = ad198x_eapd_info, | ||
586 | .get = ad198x_eapd_get, | ||
587 | .put = ad198x_eapd_put, | ||
588 | .private_value = 0x1b | (1 << 8), /* port-D, inversed */ | ||
589 | }, | ||
590 | { } /* end */ | ||
591 | }; | ||
592 | |||
593 | /* laptop-automute - 2ch only */ | ||
594 | |||
595 | static void ad1986a_update_hp(struct hda_codec *codec) | ||
609 | { | 596 | { |
610 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 597 | struct ad198x_spec *spec = codec->spec; |
611 | long *valp = ucontrol->value.integer.value; | 598 | unsigned int mute; |
612 | int change; | ||
613 | 599 | ||
614 | change = snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_OUTPUT, 0, | 600 | if (spec->jack_present) |
615 | 0x7f, valp[0] & 0x7f); | 601 | mute = HDA_AMP_MUTE; /* mute internal speaker */ |
616 | change |= snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_OUTPUT, 0, | 602 | else |
617 | 0x7f, valp[1] & 0x7f); | 603 | /* unmute internal speaker if necessary */ |
618 | snd_hda_codec_amp_update(codec, 0x1b, 0, HDA_OUTPUT, 0, | 604 | mute = snd_hda_codec_amp_read(codec, 0x1a, 0, HDA_OUTPUT, 0); |
619 | 0x7f, valp[0] & 0x7f); | 605 | snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0, |
620 | snd_hda_codec_amp_update(codec, 0x1b, 1, HDA_OUTPUT, 0, | 606 | HDA_AMP_MUTE, mute); |
621 | 0x7f, valp[1] & 0x7f); | ||
622 | return change; | ||
623 | } | 607 | } |
624 | 608 | ||
625 | static int ad1986a_laptop_master_sw_put(struct snd_kcontrol *kcontrol, | 609 | static void ad1986a_hp_automute(struct hda_codec *codec) |
626 | struct snd_ctl_elem_value *ucontrol) | 610 | { |
611 | struct ad198x_spec *spec = codec->spec; | ||
612 | unsigned int present; | ||
613 | |||
614 | present = snd_hda_codec_read(codec, 0x1a, 0, AC_VERB_GET_PIN_SENSE, 0); | ||
615 | spec->jack_present = (present & 0x80000000) != 0; | ||
616 | ad1986a_update_hp(codec); | ||
617 | } | ||
618 | |||
619 | #define AD1986A_HP_EVENT 0x37 | ||
620 | |||
621 | static void ad1986a_hp_unsol_event(struct hda_codec *codec, unsigned int res) | ||
622 | { | ||
623 | if ((res >> 26) != AD1986A_HP_EVENT) | ||
624 | return; | ||
625 | ad1986a_hp_automute(codec); | ||
626 | } | ||
627 | |||
628 | static int ad1986a_hp_init(struct hda_codec *codec) | ||
629 | { | ||
630 | ad198x_init(codec); | ||
631 | ad1986a_hp_automute(codec); | ||
632 | return 0; | ||
633 | } | ||
634 | |||
635 | /* bind hp and internal speaker mute (with plug check) */ | ||
636 | static int ad1986a_hp_master_sw_put(struct snd_kcontrol *kcontrol, | ||
637 | struct snd_ctl_elem_value *ucontrol) | ||
627 | { | 638 | { |
628 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 639 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
629 | long *valp = ucontrol->value.integer.value; | 640 | long *valp = ucontrol->value.integer.value; |
630 | int change; | 641 | int change; |
631 | 642 | ||
632 | change = snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_OUTPUT, 0, | 643 | change = snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_OUTPUT, 0, |
633 | 0x80, valp[0] ? 0 : 0x80); | 644 | HDA_AMP_MUTE, |
645 | valp[0] ? 0 : HDA_AMP_MUTE); | ||
634 | change |= snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_OUTPUT, 0, | 646 | change |= snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_OUTPUT, 0, |
635 | 0x80, valp[1] ? 0 : 0x80); | 647 | HDA_AMP_MUTE, |
636 | snd_hda_codec_amp_update(codec, 0x1b, 0, HDA_OUTPUT, 0, | 648 | valp[1] ? 0 : HDA_AMP_MUTE); |
637 | 0x80, valp[0] ? 0 : 0x80); | 649 | if (change) |
638 | snd_hda_codec_amp_update(codec, 0x1b, 1, HDA_OUTPUT, 0, | 650 | ad1986a_update_hp(codec); |
639 | 0x80, valp[1] ? 0 : 0x80); | ||
640 | return change; | 651 | return change; |
641 | } | 652 | } |
642 | 653 | ||
643 | static struct hda_input_mux ad1986a_laptop_eapd_capture_source = { | 654 | static struct snd_kcontrol_new ad1986a_laptop_automute_mixers[] = { |
644 | .num_items = 3, | 655 | HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol), |
645 | .items = { | ||
646 | { "Mic", 0x0 }, | ||
647 | { "Internal Mic", 0x4 }, | ||
648 | { "Mix", 0x5 }, | ||
649 | }, | ||
650 | }; | ||
651 | |||
652 | static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = { | ||
653 | { | ||
654 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
655 | .name = "Master Playback Volume", | ||
656 | .info = snd_hda_mixer_amp_volume_info, | ||
657 | .get = snd_hda_mixer_amp_volume_get, | ||
658 | .put = ad1986a_laptop_master_vol_put, | ||
659 | .tlv = { .c = snd_hda_mixer_amp_tlv }, | ||
660 | .private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT), | ||
661 | }, | ||
662 | { | 656 | { |
663 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 657 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
664 | .name = "Master Playback Switch", | 658 | .name = "Master Playback Switch", |
665 | .info = snd_hda_mixer_amp_switch_info, | 659 | .info = snd_hda_mixer_amp_switch_info, |
666 | .get = snd_hda_mixer_amp_switch_get, | 660 | .get = snd_hda_mixer_amp_switch_get, |
667 | .put = ad1986a_laptop_master_sw_put, | 661 | .put = ad1986a_hp_master_sw_put, |
668 | .private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT), | 662 | .private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT), |
669 | }, | 663 | }, |
670 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT), | 664 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT), |
@@ -674,6 +668,8 @@ static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = { | |||
674 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), | 668 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), |
675 | HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), | 669 | HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), |
676 | HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT), | 670 | HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT), |
671 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x18, 0x0, HDA_OUTPUT), | ||
672 | HDA_CODEC_MUTE("Beep Playback Switch", 0x18, 0x0, HDA_OUTPUT), | ||
677 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), | 673 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), |
678 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT), | 674 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT), |
679 | { | 675 | { |
@@ -807,12 +803,20 @@ static struct hda_verb ad1986a_ultra_init[] = { | |||
807 | { } /* end */ | 803 | { } /* end */ |
808 | }; | 804 | }; |
809 | 805 | ||
806 | /* pin sensing on HP jack */ | ||
807 | static struct hda_verb ad1986a_hp_init_verbs[] = { | ||
808 | {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_HP_EVENT}, | ||
809 | {} | ||
810 | }; | ||
811 | |||
812 | |||
810 | /* models */ | 813 | /* models */ |
811 | enum { | 814 | enum { |
812 | AD1986A_6STACK, | 815 | AD1986A_6STACK, |
813 | AD1986A_3STACK, | 816 | AD1986A_3STACK, |
814 | AD1986A_LAPTOP, | 817 | AD1986A_LAPTOP, |
815 | AD1986A_LAPTOP_EAPD, | 818 | AD1986A_LAPTOP_EAPD, |
819 | AD1986A_LAPTOP_AUTOMUTE, | ||
816 | AD1986A_ULTRA, | 820 | AD1986A_ULTRA, |
817 | AD1986A_MODELS | 821 | AD1986A_MODELS |
818 | }; | 822 | }; |
@@ -822,6 +826,7 @@ static const char *ad1986a_models[AD1986A_MODELS] = { | |||
822 | [AD1986A_3STACK] = "3stack", | 826 | [AD1986A_3STACK] = "3stack", |
823 | [AD1986A_LAPTOP] = "laptop", | 827 | [AD1986A_LAPTOP] = "laptop", |
824 | [AD1986A_LAPTOP_EAPD] = "laptop-eapd", | 828 | [AD1986A_LAPTOP_EAPD] = "laptop-eapd", |
829 | [AD1986A_LAPTOP_AUTOMUTE] = "laptop-automute", | ||
825 | [AD1986A_ULTRA] = "ultra", | 830 | [AD1986A_ULTRA] = "ultra", |
826 | }; | 831 | }; |
827 | 832 | ||
@@ -850,11 +855,22 @@ static struct snd_pci_quirk ad1986a_cfg_tbl[] = { | |||
850 | SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA), | 855 | SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA), |
851 | SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_LAPTOP), | 856 | SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_LAPTOP), |
852 | SND_PCI_QUIRK(0x17aa, 0x1017, "Lenovo A60", AD1986A_3STACK), | 857 | SND_PCI_QUIRK(0x17aa, 0x1017, "Lenovo A60", AD1986A_3STACK), |
853 | SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_LAPTOP_EAPD), | 858 | SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_LAPTOP_AUTOMUTE), |
854 | SND_PCI_QUIRK(0x17c0, 0x2017, "Samsung M50", AD1986A_LAPTOP), | 859 | SND_PCI_QUIRK(0x17c0, 0x2017, "Samsung M50", AD1986A_LAPTOP), |
855 | {} | 860 | {} |
856 | }; | 861 | }; |
857 | 862 | ||
863 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
864 | static struct hda_amp_list ad1986a_loopbacks[] = { | ||
865 | { 0x13, HDA_OUTPUT, 0 }, /* Mic */ | ||
866 | { 0x14, HDA_OUTPUT, 0 }, /* Phone */ | ||
867 | { 0x15, HDA_OUTPUT, 0 }, /* CD */ | ||
868 | { 0x16, HDA_OUTPUT, 0 }, /* Aux */ | ||
869 | { 0x17, HDA_OUTPUT, 0 }, /* Line */ | ||
870 | { } /* end */ | ||
871 | }; | ||
872 | #endif | ||
873 | |||
858 | static int patch_ad1986a(struct hda_codec *codec) | 874 | static int patch_ad1986a(struct hda_codec *codec) |
859 | { | 875 | { |
860 | struct ad198x_spec *spec; | 876 | struct ad198x_spec *spec; |
@@ -864,7 +880,6 @@ static int patch_ad1986a(struct hda_codec *codec) | |||
864 | if (spec == NULL) | 880 | if (spec == NULL) |
865 | return -ENOMEM; | 881 | return -ENOMEM; |
866 | 882 | ||
867 | mutex_init(&spec->amp_mutex); | ||
868 | codec->spec = spec; | 883 | codec->spec = spec; |
869 | 884 | ||
870 | spec->multiout.max_channels = 6; | 885 | spec->multiout.max_channels = 6; |
@@ -879,6 +894,9 @@ static int patch_ad1986a(struct hda_codec *codec) | |||
879 | spec->mixers[0] = ad1986a_mixers; | 894 | spec->mixers[0] = ad1986a_mixers; |
880 | spec->num_init_verbs = 1; | 895 | spec->num_init_verbs = 1; |
881 | spec->init_verbs[0] = ad1986a_init_verbs; | 896 | spec->init_verbs[0] = ad1986a_init_verbs; |
897 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
898 | spec->loopback.amplist = ad1986a_loopbacks; | ||
899 | #endif | ||
882 | 900 | ||
883 | codec->patch_ops = ad198x_patch_ops; | 901 | codec->patch_ops = ad198x_patch_ops; |
884 | 902 | ||
@@ -914,6 +932,19 @@ static int patch_ad1986a(struct hda_codec *codec) | |||
914 | spec->multiout.dig_out_nid = 0; | 932 | spec->multiout.dig_out_nid = 0; |
915 | spec->input_mux = &ad1986a_laptop_eapd_capture_source; | 933 | spec->input_mux = &ad1986a_laptop_eapd_capture_source; |
916 | break; | 934 | break; |
935 | case AD1986A_LAPTOP_AUTOMUTE: | ||
936 | spec->mixers[0] = ad1986a_laptop_automute_mixers; | ||
937 | spec->num_init_verbs = 3; | ||
938 | spec->init_verbs[1] = ad1986a_eapd_init_verbs; | ||
939 | spec->init_verbs[2] = ad1986a_hp_init_verbs; | ||
940 | spec->multiout.max_channels = 2; | ||
941 | spec->multiout.num_dacs = 1; | ||
942 | spec->multiout.dac_nids = ad1986a_laptop_dac_nids; | ||
943 | spec->multiout.dig_out_nid = 0; | ||
944 | spec->input_mux = &ad1986a_laptop_eapd_capture_source; | ||
945 | codec->patch_ops.unsol_event = ad1986a_hp_unsol_event; | ||
946 | codec->patch_ops.init = ad1986a_hp_init; | ||
947 | break; | ||
917 | case AD1986A_ULTRA: | 948 | case AD1986A_ULTRA: |
918 | spec->mixers[0] = ad1986a_laptop_eapd_mixers; | 949 | spec->mixers[0] = ad1986a_laptop_eapd_mixers; |
919 | spec->num_init_verbs = 2; | 950 | spec->num_init_verbs = 2; |
@@ -982,8 +1013,9 @@ static int ad1983_spdif_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
982 | 1013 | ||
983 | if (spec->spdif_route != ucontrol->value.enumerated.item[0]) { | 1014 | if (spec->spdif_route != ucontrol->value.enumerated.item[0]) { |
984 | spec->spdif_route = ucontrol->value.enumerated.item[0]; | 1015 | spec->spdif_route = ucontrol->value.enumerated.item[0]; |
985 | snd_hda_codec_write(codec, spec->multiout.dig_out_nid, 0, | 1016 | snd_hda_codec_write_cache(codec, spec->multiout.dig_out_nid, 0, |
986 | AC_VERB_SET_CONNECT_SEL, spec->spdif_route); | 1017 | AC_VERB_SET_CONNECT_SEL, |
1018 | spec->spdif_route); | ||
987 | return 1; | 1019 | return 1; |
988 | } | 1020 | } |
989 | return 0; | 1021 | return 0; |
@@ -1063,6 +1095,13 @@ static struct hda_verb ad1983_init_verbs[] = { | |||
1063 | { } /* end */ | 1095 | { } /* end */ |
1064 | }; | 1096 | }; |
1065 | 1097 | ||
1098 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1099 | static struct hda_amp_list ad1983_loopbacks[] = { | ||
1100 | { 0x12, HDA_OUTPUT, 0 }, /* Mic */ | ||
1101 | { 0x13, HDA_OUTPUT, 0 }, /* Line */ | ||
1102 | { } /* end */ | ||
1103 | }; | ||
1104 | #endif | ||
1066 | 1105 | ||
1067 | static int patch_ad1983(struct hda_codec *codec) | 1106 | static int patch_ad1983(struct hda_codec *codec) |
1068 | { | 1107 | { |
@@ -1072,7 +1111,6 @@ static int patch_ad1983(struct hda_codec *codec) | |||
1072 | if (spec == NULL) | 1111 | if (spec == NULL) |
1073 | return -ENOMEM; | 1112 | return -ENOMEM; |
1074 | 1113 | ||
1075 | mutex_init(&spec->amp_mutex); | ||
1076 | codec->spec = spec; | 1114 | codec->spec = spec; |
1077 | 1115 | ||
1078 | spec->multiout.max_channels = 2; | 1116 | spec->multiout.max_channels = 2; |
@@ -1088,6 +1126,9 @@ static int patch_ad1983(struct hda_codec *codec) | |||
1088 | spec->num_init_verbs = 1; | 1126 | spec->num_init_verbs = 1; |
1089 | spec->init_verbs[0] = ad1983_init_verbs; | 1127 | spec->init_verbs[0] = ad1983_init_verbs; |
1090 | spec->spdif_route = 0; | 1128 | spec->spdif_route = 0; |
1129 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1130 | spec->loopback.amplist = ad1983_loopbacks; | ||
1131 | #endif | ||
1091 | 1132 | ||
1092 | codec->patch_ops = ad198x_patch_ops; | 1133 | codec->patch_ops = ad198x_patch_ops; |
1093 | 1134 | ||
@@ -1211,6 +1252,17 @@ static struct hda_verb ad1981_init_verbs[] = { | |||
1211 | { } /* end */ | 1252 | { } /* end */ |
1212 | }; | 1253 | }; |
1213 | 1254 | ||
1255 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1256 | static struct hda_amp_list ad1981_loopbacks[] = { | ||
1257 | { 0x12, HDA_OUTPUT, 0 }, /* Front Mic */ | ||
1258 | { 0x13, HDA_OUTPUT, 0 }, /* Line */ | ||
1259 | { 0x1b, HDA_OUTPUT, 0 }, /* Aux */ | ||
1260 | { 0x1c, HDA_OUTPUT, 0 }, /* Mic */ | ||
1261 | { 0x1d, HDA_OUTPUT, 0 }, /* CD */ | ||
1262 | { } /* end */ | ||
1263 | }; | ||
1264 | #endif | ||
1265 | |||
1214 | /* | 1266 | /* |
1215 | * Patch for HP nx6320 | 1267 | * Patch for HP nx6320 |
1216 | * | 1268 | * |
@@ -1240,31 +1292,21 @@ static int ad1981_hp_master_sw_put(struct snd_kcontrol *kcontrol, | |||
1240 | return 0; | 1292 | return 0; |
1241 | 1293 | ||
1242 | /* toggle HP mute appropriately */ | 1294 | /* toggle HP mute appropriately */ |
1243 | snd_hda_codec_amp_update(codec, 0x06, 0, HDA_OUTPUT, 0, | 1295 | snd_hda_codec_amp_stereo(codec, 0x06, HDA_OUTPUT, 0, |
1244 | 0x80, spec->cur_eapd ? 0 : 0x80); | 1296 | HDA_AMP_MUTE, |
1245 | snd_hda_codec_amp_update(codec, 0x06, 1, HDA_OUTPUT, 0, | 1297 | spec->cur_eapd ? 0 : HDA_AMP_MUTE); |
1246 | 0x80, spec->cur_eapd ? 0 : 0x80); | ||
1247 | return 1; | 1298 | return 1; |
1248 | } | 1299 | } |
1249 | 1300 | ||
1250 | /* bind volumes of both NID 0x05 and 0x06 */ | 1301 | /* bind volumes of both NID 0x05 and 0x06 */ |
1251 | static int ad1981_hp_master_vol_put(struct snd_kcontrol *kcontrol, | 1302 | static struct hda_bind_ctls ad1981_hp_bind_master_vol = { |
1252 | struct snd_ctl_elem_value *ucontrol) | 1303 | .ops = &snd_hda_bind_vol, |
1253 | { | 1304 | .values = { |
1254 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 1305 | HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT), |
1255 | long *valp = ucontrol->value.integer.value; | 1306 | HDA_COMPOSE_AMP_VAL(0x06, 3, 0, HDA_OUTPUT), |
1256 | int change; | 1307 | 0 |
1257 | 1308 | }, | |
1258 | change = snd_hda_codec_amp_update(codec, 0x05, 0, HDA_OUTPUT, 0, | 1309 | }; |
1259 | 0x7f, valp[0] & 0x7f); | ||
1260 | change |= snd_hda_codec_amp_update(codec, 0x05, 1, HDA_OUTPUT, 0, | ||
1261 | 0x7f, valp[1] & 0x7f); | ||
1262 | snd_hda_codec_amp_update(codec, 0x06, 0, HDA_OUTPUT, 0, | ||
1263 | 0x7f, valp[0] & 0x7f); | ||
1264 | snd_hda_codec_amp_update(codec, 0x06, 1, HDA_OUTPUT, 0, | ||
1265 | 0x7f, valp[1] & 0x7f); | ||
1266 | return change; | ||
1267 | } | ||
1268 | 1310 | ||
1269 | /* mute internal speaker if HP is plugged */ | 1311 | /* mute internal speaker if HP is plugged */ |
1270 | static void ad1981_hp_automute(struct hda_codec *codec) | 1312 | static void ad1981_hp_automute(struct hda_codec *codec) |
@@ -1273,10 +1315,8 @@ static void ad1981_hp_automute(struct hda_codec *codec) | |||
1273 | 1315 | ||
1274 | present = snd_hda_codec_read(codec, 0x06, 0, | 1316 | present = snd_hda_codec_read(codec, 0x06, 0, |
1275 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 1317 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
1276 | snd_hda_codec_amp_update(codec, 0x05, 0, HDA_OUTPUT, 0, | 1318 | snd_hda_codec_amp_stereo(codec, 0x05, HDA_OUTPUT, 0, |
1277 | 0x80, present ? 0x80 : 0); | 1319 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); |
1278 | snd_hda_codec_amp_update(codec, 0x05, 1, HDA_OUTPUT, 0, | ||
1279 | 0x80, present ? 0x80 : 0); | ||
1280 | } | 1320 | } |
1281 | 1321 | ||
1282 | /* toggle input of built-in and mic jack appropriately */ | 1322 | /* toggle input of built-in and mic jack appropriately */ |
@@ -1327,14 +1367,7 @@ static struct hda_input_mux ad1981_hp_capture_source = { | |||
1327 | }; | 1367 | }; |
1328 | 1368 | ||
1329 | static struct snd_kcontrol_new ad1981_hp_mixers[] = { | 1369 | static struct snd_kcontrol_new ad1981_hp_mixers[] = { |
1330 | { | 1370 | HDA_BIND_VOL("Master Playback Volume", &ad1981_hp_bind_master_vol), |
1331 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1332 | .name = "Master Playback Volume", | ||
1333 | .info = snd_hda_mixer_amp_volume_info, | ||
1334 | .get = snd_hda_mixer_amp_volume_get, | ||
1335 | .put = ad1981_hp_master_vol_put, | ||
1336 | .private_value = HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT), | ||
1337 | }, | ||
1338 | { | 1371 | { |
1339 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1372 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1340 | .name = "Master Playback Switch", | 1373 | .name = "Master Playback Switch", |
@@ -1474,7 +1507,6 @@ static int patch_ad1981(struct hda_codec *codec) | |||
1474 | if (spec == NULL) | 1507 | if (spec == NULL) |
1475 | return -ENOMEM; | 1508 | return -ENOMEM; |
1476 | 1509 | ||
1477 | mutex_init(&spec->amp_mutex); | ||
1478 | codec->spec = spec; | 1510 | codec->spec = spec; |
1479 | 1511 | ||
1480 | spec->multiout.max_channels = 2; | 1512 | spec->multiout.max_channels = 2; |
@@ -1490,6 +1522,9 @@ static int patch_ad1981(struct hda_codec *codec) | |||
1490 | spec->num_init_verbs = 1; | 1522 | spec->num_init_verbs = 1; |
1491 | spec->init_verbs[0] = ad1981_init_verbs; | 1523 | spec->init_verbs[0] = ad1981_init_verbs; |
1492 | spec->spdif_route = 0; | 1524 | spec->spdif_route = 0; |
1525 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1526 | spec->loopback.amplist = ad1981_loopbacks; | ||
1527 | #endif | ||
1493 | 1528 | ||
1494 | codec->patch_ops = ad198x_patch_ops; | 1529 | codec->patch_ops = ad198x_patch_ops; |
1495 | 1530 | ||
@@ -1897,16 +1932,19 @@ static int ad1988_spdif_playback_source_get(struct snd_kcontrol *kcontrol, | |||
1897 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 1932 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
1898 | unsigned int sel; | 1933 | unsigned int sel; |
1899 | 1934 | ||
1900 | sel = snd_hda_codec_read(codec, 0x02, 0, AC_VERB_GET_CONNECT_SEL, 0); | 1935 | sel = snd_hda_codec_read(codec, 0x1d, 0, AC_VERB_GET_AMP_GAIN_MUTE, |
1901 | if (sel > 0) { | 1936 | AC_AMP_GET_INPUT); |
1937 | if (!(sel & 0x80)) | ||
1938 | ucontrol->value.enumerated.item[0] = 0; | ||
1939 | else { | ||
1902 | sel = snd_hda_codec_read(codec, 0x0b, 0, | 1940 | sel = snd_hda_codec_read(codec, 0x0b, 0, |
1903 | AC_VERB_GET_CONNECT_SEL, 0); | 1941 | AC_VERB_GET_CONNECT_SEL, 0); |
1904 | if (sel < 3) | 1942 | if (sel < 3) |
1905 | sel++; | 1943 | sel++; |
1906 | else | 1944 | else |
1907 | sel = 0; | 1945 | sel = 0; |
1946 | ucontrol->value.enumerated.item[0] = sel; | ||
1908 | } | 1947 | } |
1909 | ucontrol->value.enumerated.item[0] = sel; | ||
1910 | return 0; | 1948 | return 0; |
1911 | } | 1949 | } |
1912 | 1950 | ||
@@ -1918,23 +1956,39 @@ static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol, | |||
1918 | int change; | 1956 | int change; |
1919 | 1957 | ||
1920 | val = ucontrol->value.enumerated.item[0]; | 1958 | val = ucontrol->value.enumerated.item[0]; |
1921 | sel = snd_hda_codec_read(codec, 0x02, 0, AC_VERB_GET_CONNECT_SEL, 0); | ||
1922 | if (!val) { | 1959 | if (!val) { |
1923 | change = sel != 0; | 1960 | sel = snd_hda_codec_read(codec, 0x1d, 0, |
1924 | if (change || codec->in_resume) | 1961 | AC_VERB_GET_AMP_GAIN_MUTE, |
1925 | snd_hda_codec_write(codec, 0x02, 0, | 1962 | AC_AMP_GET_INPUT); |
1926 | AC_VERB_SET_CONNECT_SEL, 0); | 1963 | change = sel & 0x80; |
1964 | if (change) { | ||
1965 | snd_hda_codec_write_cache(codec, 0x1d, 0, | ||
1966 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
1967 | AMP_IN_UNMUTE(0)); | ||
1968 | snd_hda_codec_write_cache(codec, 0x1d, 0, | ||
1969 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
1970 | AMP_IN_MUTE(1)); | ||
1971 | } | ||
1927 | } else { | 1972 | } else { |
1928 | change = sel == 0; | 1973 | sel = snd_hda_codec_read(codec, 0x1d, 0, |
1929 | if (change || codec->in_resume) | 1974 | AC_VERB_GET_AMP_GAIN_MUTE, |
1930 | snd_hda_codec_write(codec, 0x02, 0, | 1975 | AC_AMP_GET_INPUT | 0x01); |
1931 | AC_VERB_SET_CONNECT_SEL, 1); | 1976 | change = sel & 0x80; |
1977 | if (change) { | ||
1978 | snd_hda_codec_write_cache(codec, 0x1d, 0, | ||
1979 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
1980 | AMP_IN_MUTE(0)); | ||
1981 | snd_hda_codec_write_cache(codec, 0x1d, 0, | ||
1982 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
1983 | AMP_IN_UNMUTE(1)); | ||
1984 | } | ||
1932 | sel = snd_hda_codec_read(codec, 0x0b, 0, | 1985 | sel = snd_hda_codec_read(codec, 0x0b, 0, |
1933 | AC_VERB_GET_CONNECT_SEL, 0) + 1; | 1986 | AC_VERB_GET_CONNECT_SEL, 0) + 1; |
1934 | change |= sel != val; | 1987 | change |= sel != val; |
1935 | if (change || codec->in_resume) | 1988 | if (change) |
1936 | snd_hda_codec_write(codec, 0x0b, 0, | 1989 | snd_hda_codec_write_cache(codec, 0x0b, 0, |
1937 | AC_VERB_SET_CONNECT_SEL, val - 1); | 1990 | AC_VERB_SET_CONNECT_SEL, |
1991 | val - 1); | ||
1938 | } | 1992 | } |
1939 | return change; | 1993 | return change; |
1940 | } | 1994 | } |
@@ -2047,10 +2101,9 @@ static struct hda_verb ad1988_spdif_init_verbs[] = { | |||
2047 | {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */ | 2101 | {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */ |
2048 | {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, /* ADC1 */ | 2102 | {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, /* ADC1 */ |
2049 | {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 2103 | {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
2050 | {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 2104 | {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
2051 | /* SPDIF out pin */ | 2105 | /* SPDIF out pin */ |
2052 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ | 2106 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ |
2053 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x17}, /* 0dB */ | ||
2054 | 2107 | ||
2055 | { } | 2108 | { } |
2056 | }; | 2109 | }; |
@@ -2225,6 +2278,15 @@ static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res) | |||
2225 | snd_hda_sequence_write(codec, ad1988_laptop_hp_off); | 2278 | snd_hda_sequence_write(codec, ad1988_laptop_hp_off); |
2226 | } | 2279 | } |
2227 | 2280 | ||
2281 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
2282 | static struct hda_amp_list ad1988_loopbacks[] = { | ||
2283 | { 0x20, HDA_INPUT, 0 }, /* Front Mic */ | ||
2284 | { 0x20, HDA_INPUT, 1 }, /* Line */ | ||
2285 | { 0x20, HDA_INPUT, 4 }, /* Mic */ | ||
2286 | { 0x20, HDA_INPUT, 6 }, /* CD */ | ||
2287 | { } /* end */ | ||
2288 | }; | ||
2289 | #endif | ||
2228 | 2290 | ||
2229 | /* | 2291 | /* |
2230 | * Automatic parse of I/O pins from the BIOS configuration | 2292 | * Automatic parse of I/O pins from the BIOS configuration |
@@ -2663,7 +2725,6 @@ static int patch_ad1988(struct hda_codec *codec) | |||
2663 | if (spec == NULL) | 2725 | if (spec == NULL) |
2664 | return -ENOMEM; | 2726 | return -ENOMEM; |
2665 | 2727 | ||
2666 | mutex_init(&spec->amp_mutex); | ||
2667 | codec->spec = spec; | 2728 | codec->spec = spec; |
2668 | 2729 | ||
2669 | if (is_rev2(codec)) | 2730 | if (is_rev2(codec)) |
@@ -2770,6 +2831,9 @@ static int patch_ad1988(struct hda_codec *codec) | |||
2770 | codec->patch_ops.unsol_event = ad1988_laptop_unsol_event; | 2831 | codec->patch_ops.unsol_event = ad1988_laptop_unsol_event; |
2771 | break; | 2832 | break; |
2772 | } | 2833 | } |
2834 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
2835 | spec->loopback.amplist = ad1988_loopbacks; | ||
2836 | #endif | ||
2773 | 2837 | ||
2774 | return 0; | 2838 | return 0; |
2775 | } | 2839 | } |
@@ -2926,6 +2990,16 @@ static struct hda_verb ad1884_init_verbs[] = { | |||
2926 | { } /* end */ | 2990 | { } /* end */ |
2927 | }; | 2991 | }; |
2928 | 2992 | ||
2993 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
2994 | static struct hda_amp_list ad1884_loopbacks[] = { | ||
2995 | { 0x20, HDA_INPUT, 0 }, /* Front Mic */ | ||
2996 | { 0x20, HDA_INPUT, 1 }, /* Mic */ | ||
2997 | { 0x20, HDA_INPUT, 2 }, /* CD */ | ||
2998 | { 0x20, HDA_INPUT, 4 }, /* Docking */ | ||
2999 | { } /* end */ | ||
3000 | }; | ||
3001 | #endif | ||
3002 | |||
2929 | static int patch_ad1884(struct hda_codec *codec) | 3003 | static int patch_ad1884(struct hda_codec *codec) |
2930 | { | 3004 | { |
2931 | struct ad198x_spec *spec; | 3005 | struct ad198x_spec *spec; |
@@ -2950,6 +3024,9 @@ static int patch_ad1884(struct hda_codec *codec) | |||
2950 | spec->num_init_verbs = 1; | 3024 | spec->num_init_verbs = 1; |
2951 | spec->init_verbs[0] = ad1884_init_verbs; | 3025 | spec->init_verbs[0] = ad1884_init_verbs; |
2952 | spec->spdif_route = 0; | 3026 | spec->spdif_route = 0; |
3027 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
3028 | spec->loopback.amplist = ad1884_loopbacks; | ||
3029 | #endif | ||
2953 | 3030 | ||
2954 | codec->patch_ops = ad198x_patch_ops; | 3031 | codec->patch_ops = ad198x_patch_ops; |
2955 | 3032 | ||
@@ -3331,6 +3408,16 @@ static struct hda_verb ad1882_init_verbs[] = { | |||
3331 | { } /* end */ | 3408 | { } /* end */ |
3332 | }; | 3409 | }; |
3333 | 3410 | ||
3411 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
3412 | static struct hda_amp_list ad1882_loopbacks[] = { | ||
3413 | { 0x20, HDA_INPUT, 0 }, /* Front Mic */ | ||
3414 | { 0x20, HDA_INPUT, 1 }, /* Mic */ | ||
3415 | { 0x20, HDA_INPUT, 4 }, /* Line */ | ||
3416 | { 0x20, HDA_INPUT, 6 }, /* CD */ | ||
3417 | { } /* end */ | ||
3418 | }; | ||
3419 | #endif | ||
3420 | |||
3334 | /* models */ | 3421 | /* models */ |
3335 | enum { | 3422 | enum { |
3336 | AD1882_3STACK, | 3423 | AD1882_3STACK, |
@@ -3369,6 +3456,9 @@ static int patch_ad1882(struct hda_codec *codec) | |||
3369 | spec->num_init_verbs = 1; | 3456 | spec->num_init_verbs = 1; |
3370 | spec->init_verbs[0] = ad1882_init_verbs; | 3457 | spec->init_verbs[0] = ad1882_init_verbs; |
3371 | spec->spdif_route = 0; | 3458 | spec->spdif_route = 0; |
3459 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
3460 | spec->loopback.amplist = ad1882_loopbacks; | ||
3461 | #endif | ||
3372 | 3462 | ||
3373 | codec->patch_ops = ad198x_patch_ops; | 3463 | codec->patch_ops = ad198x_patch_ops; |
3374 | 3464 | ||
diff --git a/sound/pci/hda/patch_atihdmi.c b/sound/pci/hda/patch_atihdmi.c index 72d3ab9751ac..fbb8969dc559 100644 --- a/sound/pci/hda/patch_atihdmi.c +++ b/sound/pci/hda/patch_atihdmi.c | |||
@@ -62,19 +62,6 @@ static int atihdmi_init(struct hda_codec *codec) | |||
62 | return 0; | 62 | return 0; |
63 | } | 63 | } |
64 | 64 | ||
65 | #ifdef CONFIG_PM | ||
66 | /* | ||
67 | * resume | ||
68 | */ | ||
69 | static int atihdmi_resume(struct hda_codec *codec) | ||
70 | { | ||
71 | atihdmi_init(codec); | ||
72 | snd_hda_resume_spdif_out(codec); | ||
73 | |||
74 | return 0; | ||
75 | } | ||
76 | #endif | ||
77 | |||
78 | /* | 65 | /* |
79 | * Digital out | 66 | * Digital out |
80 | */ | 67 | */ |
@@ -141,9 +128,6 @@ static struct hda_codec_ops atihdmi_patch_ops = { | |||
141 | .build_pcms = atihdmi_build_pcms, | 128 | .build_pcms = atihdmi_build_pcms, |
142 | .init = atihdmi_init, | 129 | .init = atihdmi_init, |
143 | .free = atihdmi_free, | 130 | .free = atihdmi_free, |
144 | #ifdef CONFIG_PM | ||
145 | .resume = atihdmi_resume, | ||
146 | #endif | ||
147 | }; | 131 | }; |
148 | 132 | ||
149 | static int patch_atihdmi(struct hda_codec *codec) | 133 | static int patch_atihdmi(struct hda_codec *codec) |
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c index 3c722e667bc8..2468f3171222 100644 --- a/sound/pci/hda/patch_cmedia.c +++ b/sound/pci/hda/patch_cmedia.c | |||
@@ -427,27 +427,6 @@ static int cmi9880_init(struct hda_codec *codec) | |||
427 | return 0; | 427 | return 0; |
428 | } | 428 | } |
429 | 429 | ||
430 | #ifdef CONFIG_PM | ||
431 | /* | ||
432 | * resume | ||
433 | */ | ||
434 | static int cmi9880_resume(struct hda_codec *codec) | ||
435 | { | ||
436 | struct cmi_spec *spec = codec->spec; | ||
437 | |||
438 | cmi9880_init(codec); | ||
439 | snd_hda_resume_ctls(codec, cmi9880_basic_mixer); | ||
440 | if (spec->channel_modes) | ||
441 | snd_hda_resume_ctls(codec, cmi9880_ch_mode_mixer); | ||
442 | if (spec->multiout.dig_out_nid) | ||
443 | snd_hda_resume_spdif_out(codec); | ||
444 | if (spec->dig_in_nid) | ||
445 | snd_hda_resume_spdif_in(codec); | ||
446 | |||
447 | return 0; | ||
448 | } | ||
449 | #endif | ||
450 | |||
451 | /* | 430 | /* |
452 | * Analog playback callbacks | 431 | * Analog playback callbacks |
453 | */ | 432 | */ |
@@ -635,9 +614,6 @@ static struct hda_codec_ops cmi9880_patch_ops = { | |||
635 | .build_pcms = cmi9880_build_pcms, | 614 | .build_pcms = cmi9880_build_pcms, |
636 | .init = cmi9880_init, | 615 | .init = cmi9880_init, |
637 | .free = cmi9880_free, | 616 | .free = cmi9880_free, |
638 | #ifdef CONFIG_PM | ||
639 | .resume = cmi9880_resume, | ||
640 | #endif | ||
641 | }; | 617 | }; |
642 | 618 | ||
643 | static int patch_cmi9880(struct hda_codec *codec) | 619 | static int patch_cmi9880(struct hda_codec *codec) |
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 4d8e8af5c819..080e3001d9c5 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -311,23 +311,6 @@ static void conexant_free(struct hda_codec *codec) | |||
311 | kfree(codec->spec); | 311 | kfree(codec->spec); |
312 | } | 312 | } |
313 | 313 | ||
314 | #ifdef CONFIG_PM | ||
315 | static int conexant_resume(struct hda_codec *codec) | ||
316 | { | ||
317 | struct conexant_spec *spec = codec->spec; | ||
318 | int i; | ||
319 | |||
320 | codec->patch_ops.init(codec); | ||
321 | for (i = 0; i < spec->num_mixers; i++) | ||
322 | snd_hda_resume_ctls(codec, spec->mixers[i]); | ||
323 | if (spec->multiout.dig_out_nid) | ||
324 | snd_hda_resume_spdif_out(codec); | ||
325 | if (spec->dig_in_nid) | ||
326 | snd_hda_resume_spdif_in(codec); | ||
327 | return 0; | ||
328 | } | ||
329 | #endif | ||
330 | |||
331 | static int conexant_build_controls(struct hda_codec *codec) | 314 | static int conexant_build_controls(struct hda_codec *codec) |
332 | { | 315 | { |
333 | struct conexant_spec *spec = codec->spec; | 316 | struct conexant_spec *spec = codec->spec; |
@@ -358,9 +341,6 @@ static struct hda_codec_ops conexant_patch_ops = { | |||
358 | .build_pcms = conexant_build_pcms, | 341 | .build_pcms = conexant_build_pcms, |
359 | .init = conexant_init, | 342 | .init = conexant_init, |
360 | .free = conexant_free, | 343 | .free = conexant_free, |
361 | #ifdef CONFIG_PM | ||
362 | .resume = conexant_resume, | ||
363 | #endif | ||
364 | }; | 344 | }; |
365 | 345 | ||
366 | /* | 346 | /* |
@@ -368,15 +348,7 @@ static struct hda_codec_ops conexant_patch_ops = { | |||
368 | * the private value = nid | (invert << 8) | 348 | * the private value = nid | (invert << 8) |
369 | */ | 349 | */ |
370 | 350 | ||
371 | static int cxt_eapd_info(struct snd_kcontrol *kcontrol, | 351 | #define cxt_eapd_info snd_ctl_boolean_mono_info |
372 | struct snd_ctl_elem_info *uinfo) | ||
373 | { | ||
374 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
375 | uinfo->count = 1; | ||
376 | uinfo->value.integer.min = 0; | ||
377 | uinfo->value.integer.max = 1; | ||
378 | return 0; | ||
379 | } | ||
380 | 352 | ||
381 | static int cxt_eapd_get(struct snd_kcontrol *kcontrol, | 353 | static int cxt_eapd_get(struct snd_kcontrol *kcontrol, |
382 | struct snd_ctl_elem_value *ucontrol) | 354 | struct snd_ctl_elem_value *ucontrol) |
@@ -404,13 +376,13 @@ static int cxt_eapd_put(struct snd_kcontrol *kcontrol, | |||
404 | eapd = ucontrol->value.integer.value[0]; | 376 | eapd = ucontrol->value.integer.value[0]; |
405 | if (invert) | 377 | if (invert) |
406 | eapd = !eapd; | 378 | eapd = !eapd; |
407 | if (eapd == spec->cur_eapd && !codec->in_resume) | 379 | if (eapd == spec->cur_eapd) |
408 | return 0; | 380 | return 0; |
409 | 381 | ||
410 | spec->cur_eapd = eapd; | 382 | spec->cur_eapd = eapd; |
411 | snd_hda_codec_write(codec, nid, | 383 | snd_hda_codec_write_cache(codec, nid, |
412 | 0, AC_VERB_SET_EAPD_BTLENABLE, | 384 | 0, AC_VERB_SET_EAPD_BTLENABLE, |
413 | eapd ? 0x02 : 0x00); | 385 | eapd ? 0x02 : 0x00); |
414 | return 1; | 386 | return 1; |
415 | } | 387 | } |
416 | 388 | ||
@@ -500,34 +472,25 @@ static int cxt5045_hp_master_sw_put(struct snd_kcontrol *kcontrol, | |||
500 | /* toggle internal speakers mute depending of presence of | 472 | /* toggle internal speakers mute depending of presence of |
501 | * the headphone jack | 473 | * the headphone jack |
502 | */ | 474 | */ |
503 | bits = (!spec->hp_present && spec->cur_eapd) ? 0 : 0x80; | 475 | bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE; |
504 | snd_hda_codec_amp_update(codec, 0x10, 0, HDA_OUTPUT, 0, 0x80, bits); | 476 | snd_hda_codec_amp_stereo(codec, 0x10, HDA_OUTPUT, 0, |
505 | snd_hda_codec_amp_update(codec, 0x10, 1, HDA_OUTPUT, 0, 0x80, bits); | 477 | HDA_AMP_MUTE, bits); |
506 | 478 | ||
507 | bits = spec->cur_eapd ? 0 : 0x80; | 479 | bits = spec->cur_eapd ? 0 : HDA_AMP_MUTE; |
508 | snd_hda_codec_amp_update(codec, 0x11, 0, HDA_OUTPUT, 0, 0x80, bits); | 480 | snd_hda_codec_amp_stereo(codec, 0x11, HDA_OUTPUT, 0, |
509 | snd_hda_codec_amp_update(codec, 0x11, 1, HDA_OUTPUT, 0, 0x80, bits); | 481 | HDA_AMP_MUTE, bits); |
510 | return 1; | 482 | return 1; |
511 | } | 483 | } |
512 | 484 | ||
513 | /* bind volumes of both NID 0x10 and 0x11 */ | 485 | /* bind volumes of both NID 0x10 and 0x11 */ |
514 | static int cxt5045_hp_master_vol_put(struct snd_kcontrol *kcontrol, | 486 | static struct hda_bind_ctls cxt5045_hp_bind_master_vol = { |
515 | struct snd_ctl_elem_value *ucontrol) | 487 | .ops = &snd_hda_bind_vol, |
516 | { | 488 | .values = { |
517 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 489 | HDA_COMPOSE_AMP_VAL(0x10, 3, 0, HDA_OUTPUT), |
518 | long *valp = ucontrol->value.integer.value; | 490 | HDA_COMPOSE_AMP_VAL(0x11, 3, 0, HDA_OUTPUT), |
519 | int change; | 491 | 0 |
520 | 492 | }, | |
521 | change = snd_hda_codec_amp_update(codec, 0x10, 0, HDA_OUTPUT, 0, | 493 | }; |
522 | 0x7f, valp[0] & 0x7f); | ||
523 | change |= snd_hda_codec_amp_update(codec, 0x10, 1, HDA_OUTPUT, 0, | ||
524 | 0x7f, valp[1] & 0x7f); | ||
525 | snd_hda_codec_amp_update(codec, 0x11, 0, HDA_OUTPUT, 0, | ||
526 | 0x7f, valp[0] & 0x7f); | ||
527 | snd_hda_codec_amp_update(codec, 0x11, 1, HDA_OUTPUT, 0, | ||
528 | 0x7f, valp[1] & 0x7f); | ||
529 | return change; | ||
530 | } | ||
531 | 494 | ||
532 | /* toggle input of built-in and mic jack appropriately */ | 495 | /* toggle input of built-in and mic jack appropriately */ |
533 | static void cxt5045_hp_automic(struct hda_codec *codec) | 496 | static void cxt5045_hp_automic(struct hda_codec *codec) |
@@ -562,9 +525,9 @@ static void cxt5045_hp_automute(struct hda_codec *codec) | |||
562 | spec->hp_present = snd_hda_codec_read(codec, 0x11, 0, | 525 | spec->hp_present = snd_hda_codec_read(codec, 0x11, 0, |
563 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 526 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
564 | 527 | ||
565 | bits = (spec->hp_present || !spec->cur_eapd) ? 0x80 : 0; | 528 | bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0; |
566 | snd_hda_codec_amp_update(codec, 0x10, 0, HDA_OUTPUT, 0, 0x80, bits); | 529 | snd_hda_codec_amp_stereo(codec, 0x10, HDA_OUTPUT, 0, |
567 | snd_hda_codec_amp_update(codec, 0x10, 1, HDA_OUTPUT, 0, 0x80, bits); | 530 | HDA_AMP_MUTE, bits); |
568 | } | 531 | } |
569 | 532 | ||
570 | /* unsolicited event for HP jack sensing */ | 533 | /* unsolicited event for HP jack sensing */ |
@@ -595,14 +558,7 @@ static struct snd_kcontrol_new cxt5045_mixers[] = { | |||
595 | HDA_CODEC_MUTE("Int Mic Switch", 0x1a, 0x01, HDA_INPUT), | 558 | HDA_CODEC_MUTE("Int Mic Switch", 0x1a, 0x01, HDA_INPUT), |
596 | HDA_CODEC_VOLUME("Ext Mic Volume", 0x1a, 0x02, HDA_INPUT), | 559 | HDA_CODEC_VOLUME("Ext Mic Volume", 0x1a, 0x02, HDA_INPUT), |
597 | HDA_CODEC_MUTE("Ext Mic Switch", 0x1a, 0x02, HDA_INPUT), | 560 | HDA_CODEC_MUTE("Ext Mic Switch", 0x1a, 0x02, HDA_INPUT), |
598 | { | 561 | HDA_BIND_VOL("Master Playback Volume", &cxt5045_hp_bind_master_vol), |
599 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
600 | .name = "Master Playback Volume", | ||
601 | .info = snd_hda_mixer_amp_volume_info, | ||
602 | .get = snd_hda_mixer_amp_volume_get, | ||
603 | .put = cxt5045_hp_master_vol_put, | ||
604 | .private_value = HDA_COMPOSE_AMP_VAL(0x10, 3, 0, HDA_OUTPUT), | ||
605 | }, | ||
606 | { | 562 | { |
607 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 563 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
608 | .name = "Master Playback Switch", | 564 | .name = "Master Playback Switch", |
@@ -915,33 +871,24 @@ static int cxt5047_hp_master_sw_put(struct snd_kcontrol *kcontrol, | |||
915 | /* toggle internal speakers mute depending of presence of | 871 | /* toggle internal speakers mute depending of presence of |
916 | * the headphone jack | 872 | * the headphone jack |
917 | */ | 873 | */ |
918 | bits = (!spec->hp_present && spec->cur_eapd) ? 0 : 0x80; | 874 | bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE; |
919 | snd_hda_codec_amp_update(codec, 0x1d, 0, HDA_OUTPUT, 0, 0x80, bits); | 875 | snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0, |
920 | snd_hda_codec_amp_update(codec, 0x1d, 1, HDA_OUTPUT, 0, 0x80, bits); | 876 | HDA_AMP_MUTE, bits); |
921 | bits = spec->cur_eapd ? 0 : 0x80; | 877 | bits = spec->cur_eapd ? 0 : HDA_AMP_MUTE; |
922 | snd_hda_codec_amp_update(codec, 0x13, 0, HDA_OUTPUT, 0, 0x80, bits); | 878 | snd_hda_codec_amp_stereo(codec, 0x13, HDA_OUTPUT, 0, |
923 | snd_hda_codec_amp_update(codec, 0x13, 1, HDA_OUTPUT, 0, 0x80, bits); | 879 | HDA_AMP_MUTE, bits); |
924 | return 1; | 880 | return 1; |
925 | } | 881 | } |
926 | 882 | ||
927 | /* bind volumes of both NID 0x13 (Headphones) and 0x1d (Speakers) */ | 883 | /* bind volumes of both NID 0x13 (Headphones) and 0x1d (Speakers) */ |
928 | static int cxt5047_hp_master_vol_put(struct snd_kcontrol *kcontrol, | 884 | static struct hda_bind_ctls cxt5047_bind_master_vol = { |
929 | struct snd_ctl_elem_value *ucontrol) | 885 | .ops = &snd_hda_bind_vol, |
930 | { | 886 | .values = { |
931 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 887 | HDA_COMPOSE_AMP_VAL(0x13, 3, 0, HDA_OUTPUT), |
932 | long *valp = ucontrol->value.integer.value; | 888 | HDA_COMPOSE_AMP_VAL(0x1d, 3, 0, HDA_OUTPUT), |
933 | int change; | 889 | 0 |
934 | 890 | }, | |
935 | change = snd_hda_codec_amp_update(codec, 0x1d, 0, HDA_OUTPUT, 0, | 891 | }; |
936 | 0x7f, valp[0] & 0x7f); | ||
937 | change |= snd_hda_codec_amp_update(codec, 0x1d, 1, HDA_OUTPUT, 0, | ||
938 | 0x7f, valp[1] & 0x7f); | ||
939 | snd_hda_codec_amp_update(codec, 0x13, 0, HDA_OUTPUT, 0, | ||
940 | 0x7f, valp[0] & 0x7f); | ||
941 | snd_hda_codec_amp_update(codec, 0x13, 1, HDA_OUTPUT, 0, | ||
942 | 0x7f, valp[1] & 0x7f); | ||
943 | return change; | ||
944 | } | ||
945 | 892 | ||
946 | /* mute internal speaker if HP is plugged */ | 893 | /* mute internal speaker if HP is plugged */ |
947 | static void cxt5047_hp_automute(struct hda_codec *codec) | 894 | static void cxt5047_hp_automute(struct hda_codec *codec) |
@@ -952,12 +899,12 @@ static void cxt5047_hp_automute(struct hda_codec *codec) | |||
952 | spec->hp_present = snd_hda_codec_read(codec, 0x13, 0, | 899 | spec->hp_present = snd_hda_codec_read(codec, 0x13, 0, |
953 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 900 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
954 | 901 | ||
955 | bits = (spec->hp_present || !spec->cur_eapd) ? 0x80 : 0; | 902 | bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0; |
956 | snd_hda_codec_amp_update(codec, 0x1d, 0, HDA_OUTPUT, 0, 0x80, bits); | 903 | snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0, |
957 | snd_hda_codec_amp_update(codec, 0x1d, 1, HDA_OUTPUT, 0, 0x80, bits); | 904 | HDA_AMP_MUTE, bits); |
958 | /* Mute/Unmute PCM 2 for good measure - some systems need this */ | 905 | /* Mute/Unmute PCM 2 for good measure - some systems need this */ |
959 | snd_hda_codec_amp_update(codec, 0x1c, 0, HDA_OUTPUT, 0, 0x80, bits); | 906 | snd_hda_codec_amp_stereo(codec, 0x1c, HDA_OUTPUT, 0, |
960 | snd_hda_codec_amp_update(codec, 0x1c, 1, HDA_OUTPUT, 0, 0x80, bits); | 907 | HDA_AMP_MUTE, bits); |
961 | } | 908 | } |
962 | 909 | ||
963 | /* mute internal speaker if HP is plugged */ | 910 | /* mute internal speaker if HP is plugged */ |
@@ -969,12 +916,12 @@ static void cxt5047_hp2_automute(struct hda_codec *codec) | |||
969 | spec->hp_present = snd_hda_codec_read(codec, 0x13, 0, | 916 | spec->hp_present = snd_hda_codec_read(codec, 0x13, 0, |
970 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 917 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
971 | 918 | ||
972 | bits = spec->hp_present ? 0x80 : 0; | 919 | bits = spec->hp_present ? HDA_AMP_MUTE : 0; |
973 | snd_hda_codec_amp_update(codec, 0x1d, 0, HDA_OUTPUT, 0, 0x80, bits); | 920 | snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0, |
974 | snd_hda_codec_amp_update(codec, 0x1d, 1, HDA_OUTPUT, 0, 0x80, bits); | 921 | HDA_AMP_MUTE, bits); |
975 | /* Mute/Unmute PCM 2 for good measure - some systems need this */ | 922 | /* Mute/Unmute PCM 2 for good measure - some systems need this */ |
976 | snd_hda_codec_amp_update(codec, 0x1c, 0, HDA_OUTPUT, 0, 0x80, bits); | 923 | snd_hda_codec_amp_stereo(codec, 0x1c, HDA_OUTPUT, 0, |
977 | snd_hda_codec_amp_update(codec, 0x1c, 1, HDA_OUTPUT, 0, 0x80, bits); | 924 | HDA_AMP_MUTE, bits); |
978 | } | 925 | } |
979 | 926 | ||
980 | /* toggle input of built-in and mic jack appropriately */ | 927 | /* toggle input of built-in and mic jack appropriately */ |
@@ -1063,14 +1010,7 @@ static struct snd_kcontrol_new cxt5047_toshiba_mixers[] = { | |||
1063 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT), | 1010 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT), |
1064 | HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT), | 1011 | HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT), |
1065 | HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT), | 1012 | HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT), |
1066 | { | 1013 | HDA_BIND_VOL("Master Playback Volume", &cxt5047_bind_master_vol), |
1067 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1068 | .name = "Master Playback Volume", | ||
1069 | .info = snd_hda_mixer_amp_volume_info, | ||
1070 | .get = snd_hda_mixer_amp_volume_get, | ||
1071 | .put = cxt5047_hp_master_vol_put, | ||
1072 | .private_value = HDA_COMPOSE_AMP_VAL(0x13, 3, 0, HDA_OUTPUT), | ||
1073 | }, | ||
1074 | { | 1014 | { |
1075 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1015 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1076 | .name = "Master Playback Switch", | 1016 | .name = "Master Playback Switch", |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 9a47eec5a27b..53b0428abfc2 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -102,6 +102,8 @@ enum { | |||
102 | /* ALC268 models */ | 102 | /* ALC268 models */ |
103 | enum { | 103 | enum { |
104 | ALC268_3ST, | 104 | ALC268_3ST, |
105 | ALC268_TOSHIBA, | ||
106 | ALC268_ACER, | ||
105 | ALC268_AUTO, | 107 | ALC268_AUTO, |
106 | ALC268_MODEL_LAST /* last tag */ | 108 | ALC268_MODEL_LAST /* last tag */ |
107 | }; | 109 | }; |
@@ -129,6 +131,7 @@ enum { | |||
129 | ALC861VD_6ST_DIG, | 131 | ALC861VD_6ST_DIG, |
130 | ALC861VD_LENOVO, | 132 | ALC861VD_LENOVO, |
131 | ALC861VD_DALLAS, | 133 | ALC861VD_DALLAS, |
134 | ALC861VD_HP, | ||
132 | ALC861VD_AUTO, | 135 | ALC861VD_AUTO, |
133 | ALC861VD_MODEL_LAST, | 136 | ALC861VD_MODEL_LAST, |
134 | }; | 137 | }; |
@@ -140,6 +143,7 @@ enum { | |||
140 | ALC662_3ST_6ch, | 143 | ALC662_3ST_6ch, |
141 | ALC662_5ST_DIG, | 144 | ALC662_5ST_DIG, |
142 | ALC662_LENOVO_101E, | 145 | ALC662_LENOVO_101E, |
146 | ALC662_ASUS_EEEPC_P701, | ||
143 | ALC662_AUTO, | 147 | ALC662_AUTO, |
144 | ALC662_MODEL_LAST, | 148 | ALC662_MODEL_LAST, |
145 | }; | 149 | }; |
@@ -152,7 +156,9 @@ enum { | |||
152 | ALC882_W2JC, | 156 | ALC882_W2JC, |
153 | ALC882_TARGA, | 157 | ALC882_TARGA, |
154 | ALC882_ASUS_A7J, | 158 | ALC882_ASUS_A7J, |
159 | ALC882_ASUS_A7M, | ||
155 | ALC885_MACPRO, | 160 | ALC885_MACPRO, |
161 | ALC885_MBP3, | ||
156 | ALC885_IMAC24, | 162 | ALC885_IMAC24, |
157 | ALC882_AUTO, | 163 | ALC882_AUTO, |
158 | ALC882_MODEL_LAST, | 164 | ALC882_MODEL_LAST, |
@@ -167,12 +173,14 @@ enum { | |||
167 | ALC883_TARGA_DIG, | 173 | ALC883_TARGA_DIG, |
168 | ALC883_TARGA_2ch_DIG, | 174 | ALC883_TARGA_2ch_DIG, |
169 | ALC883_ACER, | 175 | ALC883_ACER, |
176 | ALC883_ACER_ASPIRE, | ||
170 | ALC883_MEDION, | 177 | ALC883_MEDION, |
171 | ALC883_MEDION_MD2, | 178 | ALC883_MEDION_MD2, |
172 | ALC883_LAPTOP_EAPD, | 179 | ALC883_LAPTOP_EAPD, |
173 | ALC883_LENOVO_101E_2ch, | 180 | ALC883_LENOVO_101E_2ch, |
174 | ALC883_LENOVO_NB0763, | 181 | ALC883_LENOVO_NB0763, |
175 | ALC888_LENOVO_MS7195_DIG, | 182 | ALC888_LENOVO_MS7195_DIG, |
183 | ALC883_HAIER_W66, | ||
176 | ALC888_6ST_HP, | 184 | ALC888_6ST_HP, |
177 | ALC888_3ST_HP, | 185 | ALC888_3ST_HP, |
178 | ALC883_AUTO, | 186 | ALC883_AUTO, |
@@ -239,6 +247,10 @@ struct alc_spec { | |||
239 | /* for pin sensing */ | 247 | /* for pin sensing */ |
240 | unsigned int sense_updated: 1; | 248 | unsigned int sense_updated: 1; |
241 | unsigned int jack_present: 1; | 249 | unsigned int jack_present: 1; |
250 | |||
251 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
252 | struct hda_loopback_check loopback; | ||
253 | #endif | ||
242 | }; | 254 | }; |
243 | 255 | ||
244 | /* | 256 | /* |
@@ -263,6 +275,9 @@ struct alc_config_preset { | |||
263 | const struct hda_input_mux *input_mux; | 275 | const struct hda_input_mux *input_mux; |
264 | void (*unsol_event)(struct hda_codec *, unsigned int); | 276 | void (*unsol_event)(struct hda_codec *, unsigned int); |
265 | void (*init_hook)(struct hda_codec *); | 277 | void (*init_hook)(struct hda_codec *); |
278 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
279 | struct hda_amp_list *loopbacks; | ||
280 | #endif | ||
266 | }; | 281 | }; |
267 | 282 | ||
268 | 283 | ||
@@ -441,8 +456,9 @@ static int alc_pin_mode_put(struct snd_kcontrol *kcontrol, | |||
441 | change = pinctl != alc_pin_mode_values[val]; | 456 | change = pinctl != alc_pin_mode_values[val]; |
442 | if (change) { | 457 | if (change) { |
443 | /* Set pin mode to that requested */ | 458 | /* Set pin mode to that requested */ |
444 | snd_hda_codec_write(codec,nid,0,AC_VERB_SET_PIN_WIDGET_CONTROL, | 459 | snd_hda_codec_write_cache(codec, nid, 0, |
445 | alc_pin_mode_values[val]); | 460 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
461 | alc_pin_mode_values[val]); | ||
446 | 462 | ||
447 | /* Also enable the retasking pin's input/output as required | 463 | /* Also enable the retasking pin's input/output as required |
448 | * for the requested pin mode. Enum values of 2 or less are | 464 | * for the requested pin mode. Enum values of 2 or less are |
@@ -455,19 +471,15 @@ static int alc_pin_mode_put(struct snd_kcontrol *kcontrol, | |||
455 | * this turns out to be necessary in the future. | 471 | * this turns out to be necessary in the future. |
456 | */ | 472 | */ |
457 | if (val <= 2) { | 473 | if (val <= 2) { |
458 | snd_hda_codec_write(codec, nid, 0, | 474 | snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, |
459 | AC_VERB_SET_AMP_GAIN_MUTE, | 475 | HDA_AMP_MUTE, HDA_AMP_MUTE); |
460 | AMP_OUT_MUTE); | 476 | snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0, |
461 | snd_hda_codec_write(codec, nid, 0, | 477 | HDA_AMP_MUTE, 0); |
462 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
463 | AMP_IN_UNMUTE(0)); | ||
464 | } else { | 478 | } else { |
465 | snd_hda_codec_write(codec, nid, 0, | 479 | snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0, |
466 | AC_VERB_SET_AMP_GAIN_MUTE, | 480 | HDA_AMP_MUTE, HDA_AMP_MUTE); |
467 | AMP_IN_MUTE(0)); | 481 | snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, |
468 | snd_hda_codec_write(codec, nid, 0, | 482 | HDA_AMP_MUTE, 0); |
469 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
470 | AMP_OUT_UNMUTE); | ||
471 | } | 483 | } |
472 | } | 484 | } |
473 | return change; | 485 | return change; |
@@ -486,15 +498,7 @@ static int alc_pin_mode_put(struct snd_kcontrol *kcontrol, | |||
486 | * needed for any "production" models. | 498 | * needed for any "production" models. |
487 | */ | 499 | */ |
488 | #ifdef CONFIG_SND_DEBUG | 500 | #ifdef CONFIG_SND_DEBUG |
489 | static int alc_gpio_data_info(struct snd_kcontrol *kcontrol, | 501 | #define alc_gpio_data_info snd_ctl_boolean_mono_info |
490 | struct snd_ctl_elem_info *uinfo) | ||
491 | { | ||
492 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
493 | uinfo->count = 1; | ||
494 | uinfo->value.integer.min = 0; | ||
495 | uinfo->value.integer.max = 1; | ||
496 | return 0; | ||
497 | } | ||
498 | 502 | ||
499 | static int alc_gpio_data_get(struct snd_kcontrol *kcontrol, | 503 | static int alc_gpio_data_get(struct snd_kcontrol *kcontrol, |
500 | struct snd_ctl_elem_value *ucontrol) | 504 | struct snd_ctl_elem_value *ucontrol) |
@@ -527,7 +531,8 @@ static int alc_gpio_data_put(struct snd_kcontrol *kcontrol, | |||
527 | gpio_data &= ~mask; | 531 | gpio_data &= ~mask; |
528 | else | 532 | else |
529 | gpio_data |= mask; | 533 | gpio_data |= mask; |
530 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_GPIO_DATA, gpio_data); | 534 | snd_hda_codec_write_cache(codec, nid, 0, |
535 | AC_VERB_SET_GPIO_DATA, gpio_data); | ||
531 | 536 | ||
532 | return change; | 537 | return change; |
533 | } | 538 | } |
@@ -547,15 +552,7 @@ static int alc_gpio_data_put(struct snd_kcontrol *kcontrol, | |||
547 | * necessary. | 552 | * necessary. |
548 | */ | 553 | */ |
549 | #ifdef CONFIG_SND_DEBUG | 554 | #ifdef CONFIG_SND_DEBUG |
550 | static int alc_spdif_ctrl_info(struct snd_kcontrol *kcontrol, | 555 | #define alc_spdif_ctrl_info snd_ctl_boolean_mono_info |
551 | struct snd_ctl_elem_info *uinfo) | ||
552 | { | ||
553 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
554 | uinfo->count = 1; | ||
555 | uinfo->value.integer.min = 0; | ||
556 | uinfo->value.integer.max = 1; | ||
557 | return 0; | ||
558 | } | ||
559 | 556 | ||
560 | static int alc_spdif_ctrl_get(struct snd_kcontrol *kcontrol, | 557 | static int alc_spdif_ctrl_get(struct snd_kcontrol *kcontrol, |
561 | struct snd_ctl_elem_value *ucontrol) | 558 | struct snd_ctl_elem_value *ucontrol) |
@@ -588,8 +585,8 @@ static int alc_spdif_ctrl_put(struct snd_kcontrol *kcontrol, | |||
588 | ctrl_data &= ~mask; | 585 | ctrl_data &= ~mask; |
589 | else | 586 | else |
590 | ctrl_data |= mask; | 587 | ctrl_data |= mask; |
591 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, | 588 | snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, |
592 | ctrl_data); | 589 | ctrl_data); |
593 | 590 | ||
594 | return change; | 591 | return change; |
595 | } | 592 | } |
@@ -638,6 +635,9 @@ static void setup_preset(struct alc_spec *spec, | |||
638 | 635 | ||
639 | spec->unsol_event = preset->unsol_event; | 636 | spec->unsol_event = preset->unsol_event; |
640 | spec->init_hook = preset->init_hook; | 637 | spec->init_hook = preset->init_hook; |
638 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
639 | spec->loopback.amplist = preset->loopbacks; | ||
640 | #endif | ||
641 | } | 641 | } |
642 | 642 | ||
643 | /* Enable GPIO mask and set output */ | 643 | /* Enable GPIO mask and set output */ |
@@ -662,6 +662,44 @@ static struct hda_verb alc_gpio3_init_verbs[] = { | |||
662 | { } | 662 | { } |
663 | }; | 663 | }; |
664 | 664 | ||
665 | static void alc_sku_automute(struct hda_codec *codec) | ||
666 | { | ||
667 | struct alc_spec *spec = codec->spec; | ||
668 | unsigned int mute; | ||
669 | unsigned int present; | ||
670 | unsigned int hp_nid = spec->autocfg.hp_pins[0]; | ||
671 | unsigned int sp_nid = spec->autocfg.speaker_pins[0]; | ||
672 | |||
673 | /* need to execute and sync at first */ | ||
674 | snd_hda_codec_read(codec, hp_nid, 0, AC_VERB_SET_PIN_SENSE, 0); | ||
675 | present = snd_hda_codec_read(codec, hp_nid, 0, | ||
676 | AC_VERB_GET_PIN_SENSE, 0); | ||
677 | spec->jack_present = (present & 0x80000000) != 0; | ||
678 | if (spec->jack_present) { | ||
679 | /* mute internal speaker */ | ||
680 | snd_hda_codec_amp_stereo(codec, sp_nid, HDA_OUTPUT, 0, | ||
681 | HDA_AMP_MUTE, HDA_AMP_MUTE); | ||
682 | } else { | ||
683 | /* unmute internal speaker if necessary */ | ||
684 | mute = snd_hda_codec_amp_read(codec, hp_nid, 0, HDA_OUTPUT, 0); | ||
685 | snd_hda_codec_amp_stereo(codec, sp_nid, HDA_OUTPUT, 0, | ||
686 | HDA_AMP_MUTE, mute); | ||
687 | } | ||
688 | } | ||
689 | |||
690 | /* unsolicited event for HP jack sensing */ | ||
691 | static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res) | ||
692 | { | ||
693 | if (codec->vendor_id == 0x10ec0880) | ||
694 | res >>= 28; | ||
695 | else | ||
696 | res >>= 26; | ||
697 | if (res != ALC880_HP_EVENT) | ||
698 | return; | ||
699 | |||
700 | alc_sku_automute(codec); | ||
701 | } | ||
702 | |||
665 | /* 32-bit subsystem ID for BIOS loading in HD Audio codec. | 703 | /* 32-bit subsystem ID for BIOS loading in HD Audio codec. |
666 | * 31 ~ 16 : Manufacture ID | 704 | * 31 ~ 16 : Manufacture ID |
667 | * 15 ~ 8 : SKU ID | 705 | * 15 ~ 8 : SKU ID |
@@ -672,13 +710,48 @@ static void alc_subsystem_id(struct hda_codec *codec, | |||
672 | unsigned int porta, unsigned int porte, | 710 | unsigned int porta, unsigned int porte, |
673 | unsigned int portd) | 711 | unsigned int portd) |
674 | { | 712 | { |
675 | unsigned int ass, tmp; | 713 | unsigned int ass, tmp, i; |
714 | unsigned nid; | ||
715 | struct alc_spec *spec = codec->spec; | ||
676 | 716 | ||
677 | ass = codec->subsystem_id; | 717 | ass = codec->subsystem_id & 0xffff; |
678 | if (!(ass & 1)) | 718 | if ((ass != codec->bus->pci->subsystem_device) && (ass & 1)) |
719 | goto do_sku; | ||
720 | |||
721 | /* | ||
722 | * 31~30 : port conetcivity | ||
723 | * 29~21 : reserve | ||
724 | * 20 : PCBEEP input | ||
725 | * 19~16 : Check sum (15:1) | ||
726 | * 15~1 : Custom | ||
727 | * 0 : override | ||
728 | */ | ||
729 | nid = 0x1d; | ||
730 | if (codec->vendor_id == 0x10ec0260) | ||
731 | nid = 0x17; | ||
732 | ass = snd_hda_codec_read(codec, nid, 0, | ||
733 | AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
734 | if (!(ass & 1) && !(ass & 0x100000)) | ||
735 | return; | ||
736 | if ((ass >> 30) != 1) /* no physical connection */ | ||
679 | return; | 737 | return; |
680 | 738 | ||
681 | /* Override */ | 739 | /* check sum */ |
740 | tmp = 0; | ||
741 | for (i = 1; i < 16; i++) { | ||
742 | if ((ass >> i) && 1) | ||
743 | tmp++; | ||
744 | } | ||
745 | if (((ass >> 16) & 0xf) != tmp) | ||
746 | return; | ||
747 | do_sku: | ||
748 | /* | ||
749 | * 0 : override | ||
750 | * 1 : Swap Jack | ||
751 | * 2 : 0 --> Desktop, 1 --> Laptop | ||
752 | * 3~5 : External Amplifier control | ||
753 | * 7~6 : Reserved | ||
754 | */ | ||
682 | tmp = (ass & 0x38) >> 3; /* external Amp control */ | 755 | tmp = (ass & 0x38) >> 3; /* external Amp control */ |
683 | switch (tmp) { | 756 | switch (tmp) { |
684 | case 1: | 757 | case 1: |
@@ -690,38 +763,108 @@ static void alc_subsystem_id(struct hda_codec *codec, | |||
690 | case 7: | 763 | case 7: |
691 | snd_hda_sequence_write(codec, alc_gpio3_init_verbs); | 764 | snd_hda_sequence_write(codec, alc_gpio3_init_verbs); |
692 | break; | 765 | break; |
693 | case 5: | 766 | case 5: /* set EAPD output high */ |
694 | switch (codec->vendor_id) { | 767 | switch (codec->vendor_id) { |
695 | case 0x10ec0862: | 768 | case 0x10ec0260: |
696 | case 0x10ec0660: | 769 | snd_hda_codec_write(codec, 0x0f, 0, |
697 | case 0x10ec0662: | 770 | AC_VERB_SET_EAPD_BTLENABLE, 2); |
771 | snd_hda_codec_write(codec, 0x10, 0, | ||
772 | AC_VERB_SET_EAPD_BTLENABLE, 2); | ||
773 | break; | ||
774 | case 0x10ec0262: | ||
698 | case 0x10ec0267: | 775 | case 0x10ec0267: |
699 | case 0x10ec0268: | 776 | case 0x10ec0268: |
777 | case 0x10ec0269: | ||
778 | case 0x10ec0862: | ||
779 | case 0x10ec0662: | ||
700 | snd_hda_codec_write(codec, 0x14, 0, | 780 | snd_hda_codec_write(codec, 0x14, 0, |
701 | AC_VERB_SET_EAPD_BTLENABLE, 2); | 781 | AC_VERB_SET_EAPD_BTLENABLE, 2); |
702 | snd_hda_codec_write(codec, 0x15, 0, | 782 | snd_hda_codec_write(codec, 0x15, 0, |
703 | AC_VERB_SET_EAPD_BTLENABLE, 2); | 783 | AC_VERB_SET_EAPD_BTLENABLE, 2); |
704 | return; | 784 | break; |
705 | } | 785 | } |
706 | case 6: | 786 | switch (codec->vendor_id) { |
707 | if (ass & 4) { /* bit 2 : 0 = Desktop, 1 = Laptop */ | 787 | case 0x10ec0260: |
708 | hda_nid_t port = 0; | 788 | snd_hda_codec_write(codec, 0x1a, 0, |
709 | tmp = (ass & 0x1800) >> 11; | 789 | AC_VERB_SET_COEF_INDEX, 7); |
710 | switch (tmp) { | 790 | tmp = snd_hda_codec_read(codec, 0x1a, 0, |
711 | case 0: port = porta; break; | 791 | AC_VERB_GET_PROC_COEF, 0); |
712 | case 1: port = porte; break; | 792 | snd_hda_codec_write(codec, 0x1a, 0, |
713 | case 2: port = portd; break; | 793 | AC_VERB_SET_COEF_INDEX, 7); |
714 | } | 794 | snd_hda_codec_write(codec, 0x1a, 0, |
715 | if (port) | 795 | AC_VERB_SET_PROC_COEF, |
716 | snd_hda_codec_write(codec, port, 0, | 796 | tmp | 0x2010); |
717 | AC_VERB_SET_EAPD_BTLENABLE, | 797 | break; |
718 | 2); | 798 | case 0x10ec0262: |
799 | case 0x10ec0880: | ||
800 | case 0x10ec0882: | ||
801 | case 0x10ec0883: | ||
802 | case 0x10ec0885: | ||
803 | case 0x10ec0888: | ||
804 | snd_hda_codec_write(codec, 0x20, 0, | ||
805 | AC_VERB_SET_COEF_INDEX, 7); | ||
806 | tmp = snd_hda_codec_read(codec, 0x20, 0, | ||
807 | AC_VERB_GET_PROC_COEF, 0); | ||
808 | snd_hda_codec_write(codec, 0x20, 0, | ||
809 | AC_VERB_SET_COEF_INDEX, 7); | ||
810 | snd_hda_codec_write(codec, 0x20, 0, | ||
811 | AC_VERB_SET_PROC_COEF, | ||
812 | tmp | 0x2010); | ||
813 | break; | ||
814 | case 0x10ec0267: | ||
815 | case 0x10ec0268: | ||
816 | snd_hda_codec_write(codec, 0x20, 0, | ||
817 | AC_VERB_SET_COEF_INDEX, 7); | ||
818 | tmp = snd_hda_codec_read(codec, 0x20, 0, | ||
819 | AC_VERB_GET_PROC_COEF, 0); | ||
820 | snd_hda_codec_write(codec, 0x20, 0, | ||
821 | AC_VERB_SET_COEF_INDEX, 7); | ||
822 | snd_hda_codec_write(codec, 0x20, 0, | ||
823 | AC_VERB_SET_PROC_COEF, | ||
824 | tmp | 0x3000); | ||
825 | break; | ||
719 | } | 826 | } |
720 | snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7); | 827 | default: |
721 | snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, | ||
722 | (tmp == 5 ? 0x3040 : 0x3050)); | ||
723 | break; | 828 | break; |
724 | } | 829 | } |
830 | |||
831 | /* is laptop and enable the function "Mute internal speaker | ||
832 | * when the external headphone out jack is plugged" | ||
833 | */ | ||
834 | if (!(ass & 0x4) || !(ass & 0x8000)) | ||
835 | return; | ||
836 | /* | ||
837 | * 10~8 : Jack location | ||
838 | * 12~11: Headphone out -> 00: PortA, 01: PortE, 02: PortD, 03: Resvered | ||
839 | * 14~13: Resvered | ||
840 | * 15 : 1 --> enable the function "Mute internal speaker | ||
841 | * when the external headphone out jack is plugged" | ||
842 | */ | ||
843 | if (!spec->autocfg.speaker_pins[0]) { | ||
844 | if (spec->multiout.dac_nids[0]) | ||
845 | spec->autocfg.speaker_pins[0] = | ||
846 | spec->multiout.dac_nids[0]; | ||
847 | else | ||
848 | return; | ||
849 | } | ||
850 | |||
851 | if (!spec->autocfg.hp_pins[0]) { | ||
852 | tmp = (ass >> 11) & 0x3; /* HP to chassis */ | ||
853 | if (tmp == 0) | ||
854 | spec->autocfg.hp_pins[0] = porta; | ||
855 | else if (tmp == 1) | ||
856 | spec->autocfg.hp_pins[0] = porte; | ||
857 | else if (tmp == 2) | ||
858 | spec->autocfg.hp_pins[0] = portd; | ||
859 | else | ||
860 | return; | ||
861 | } | ||
862 | |||
863 | snd_hda_codec_write(codec, spec->autocfg.hp_pins[0], 0, | ||
864 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
865 | AC_USRSP_EN | ALC880_HP_EVENT); | ||
866 | spec->unsol_event = alc_sku_unsol_event; | ||
867 | spec->init_hook = alc_sku_automute; | ||
725 | } | 868 | } |
726 | 869 | ||
727 | /* | 870 | /* |
@@ -1304,11 +1447,13 @@ static struct hda_verb alc880_volume_init_verbs[] = { | |||
1304 | * panel mic (mic 2) | 1447 | * panel mic (mic 2) |
1305 | */ | 1448 | */ |
1306 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | 1449 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ |
1307 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 1450 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
1308 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 1451 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
1309 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 1452 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
1310 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 1453 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
1311 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 1454 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
1455 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, | ||
1456 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, | ||
1312 | 1457 | ||
1313 | /* | 1458 | /* |
1314 | * Set up output mixers (0x0c - 0x0f) | 1459 | * Set up output mixers (0x0c - 0x0f) |
@@ -1568,15 +1713,11 @@ static void alc880_uniwill_hp_automute(struct hda_codec *codec) | |||
1568 | 1713 | ||
1569 | present = snd_hda_codec_read(codec, 0x14, 0, | 1714 | present = snd_hda_codec_read(codec, 0x14, 0, |
1570 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 1715 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
1571 | bits = present ? 0x80 : 0; | 1716 | bits = present ? HDA_AMP_MUTE : 0; |
1572 | snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, | 1717 | snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, |
1573 | 0x80, bits); | 1718 | HDA_AMP_MUTE, bits); |
1574 | snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, | 1719 | snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0, |
1575 | 0x80, bits); | 1720 | HDA_AMP_MUTE, bits); |
1576 | snd_hda_codec_amp_update(codec, 0x16, 0, HDA_OUTPUT, 0, | ||
1577 | 0x80, bits); | ||
1578 | snd_hda_codec_amp_update(codec, 0x16, 1, HDA_OUTPUT, 0, | ||
1579 | 0x80, bits); | ||
1580 | } | 1721 | } |
1581 | 1722 | ||
1582 | /* auto-toggle front mic */ | 1723 | /* auto-toggle front mic */ |
@@ -1587,11 +1728,8 @@ static void alc880_uniwill_mic_automute(struct hda_codec *codec) | |||
1587 | 1728 | ||
1588 | present = snd_hda_codec_read(codec, 0x18, 0, | 1729 | present = snd_hda_codec_read(codec, 0x18, 0, |
1589 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 1730 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
1590 | bits = present ? 0x80 : 0; | 1731 | bits = present ? HDA_AMP_MUTE : 0; |
1591 | snd_hda_codec_amp_update(codec, 0x0b, 0, HDA_INPUT, 1, | 1732 | snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, HDA_AMP_MUTE, bits); |
1592 | 0x80, bits); | ||
1593 | snd_hda_codec_amp_update(codec, 0x0b, 1, HDA_INPUT, 1, | ||
1594 | 0x80, bits); | ||
1595 | } | 1733 | } |
1596 | 1734 | ||
1597 | static void alc880_uniwill_automute(struct hda_codec *codec) | 1735 | static void alc880_uniwill_automute(struct hda_codec *codec) |
@@ -1623,11 +1761,8 @@ static void alc880_uniwill_p53_hp_automute(struct hda_codec *codec) | |||
1623 | 1761 | ||
1624 | present = snd_hda_codec_read(codec, 0x14, 0, | 1762 | present = snd_hda_codec_read(codec, 0x14, 0, |
1625 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 1763 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
1626 | bits = present ? 0x80 : 0; | 1764 | bits = present ? HDA_AMP_MUTE : 0; |
1627 | snd_hda_codec_amp_update(codec, 0x15, 0, HDA_INPUT, 0, | 1765 | snd_hda_codec_amp_stereo(codec, 0x15, HDA_INPUT, 0, HDA_AMP_MUTE, bits); |
1628 | 0x80, bits); | ||
1629 | snd_hda_codec_amp_update(codec, 0x15, 1, HDA_INPUT, 0, | ||
1630 | 0x80, bits); | ||
1631 | } | 1766 | } |
1632 | 1767 | ||
1633 | static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec) | 1768 | static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec) |
@@ -1635,19 +1770,14 @@ static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec) | |||
1635 | unsigned int present; | 1770 | unsigned int present; |
1636 | 1771 | ||
1637 | present = snd_hda_codec_read(codec, 0x21, 0, | 1772 | present = snd_hda_codec_read(codec, 0x21, 0, |
1638 | AC_VERB_GET_VOLUME_KNOB_CONTROL, 0) & 0x7f; | 1773 | AC_VERB_GET_VOLUME_KNOB_CONTROL, 0); |
1639 | 1774 | present &= HDA_AMP_VOLMASK; | |
1640 | snd_hda_codec_amp_update(codec, 0x0c, 0, HDA_OUTPUT, 0, | 1775 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_OUTPUT, 0, |
1641 | 0x7f, present); | 1776 | HDA_AMP_VOLMASK, present); |
1642 | snd_hda_codec_amp_update(codec, 0x0c, 1, HDA_OUTPUT, 0, | 1777 | snd_hda_codec_amp_stereo(codec, 0x0d, HDA_OUTPUT, 0, |
1643 | 0x7f, present); | 1778 | HDA_AMP_VOLMASK, present); |
1644 | |||
1645 | snd_hda_codec_amp_update(codec, 0x0d, 0, HDA_OUTPUT, 0, | ||
1646 | 0x7f, present); | ||
1647 | snd_hda_codec_amp_update(codec, 0x0d, 1, HDA_OUTPUT, 0, | ||
1648 | 0x7f, present); | ||
1649 | |||
1650 | } | 1779 | } |
1780 | |||
1651 | static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec, | 1781 | static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec, |
1652 | unsigned int res) | 1782 | unsigned int res) |
1653 | { | 1783 | { |
@@ -1868,8 +1998,8 @@ static struct hda_verb alc880_lg_init_verbs[] = { | |||
1868 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 1998 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
1869 | /* mute all amp mixer inputs */ | 1999 | /* mute all amp mixer inputs */ |
1870 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)}, | 2000 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)}, |
1871 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(6)}, | 2001 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, |
1872 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(7)}, | 2002 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, |
1873 | /* line-in to input */ | 2003 | /* line-in to input */ |
1874 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | 2004 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, |
1875 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | 2005 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
@@ -1900,11 +2030,9 @@ static void alc880_lg_automute(struct hda_codec *codec) | |||
1900 | 2030 | ||
1901 | present = snd_hda_codec_read(codec, 0x1b, 0, | 2031 | present = snd_hda_codec_read(codec, 0x1b, 0, |
1902 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 2032 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
1903 | bits = present ? 0x80 : 0; | 2033 | bits = present ? HDA_AMP_MUTE : 0; |
1904 | snd_hda_codec_amp_update(codec, 0x17, 0, HDA_OUTPUT, 0, | 2034 | snd_hda_codec_amp_stereo(codec, 0x17, HDA_OUTPUT, 0, |
1905 | 0x80, bits); | 2035 | HDA_AMP_MUTE, bits); |
1906 | snd_hda_codec_amp_update(codec, 0x17, 1, HDA_OUTPUT, 0, | ||
1907 | 0x80, bits); | ||
1908 | } | 2036 | } |
1909 | 2037 | ||
1910 | static void alc880_lg_unsol_event(struct hda_codec *codec, unsigned int res) | 2038 | static void alc880_lg_unsol_event(struct hda_codec *codec, unsigned int res) |
@@ -1973,7 +2101,7 @@ static struct hda_verb alc880_lg_lw_init_verbs[] = { | |||
1973 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 2101 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
1974 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 2102 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
1975 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 2103 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
1976 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(7)}, | 2104 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, |
1977 | /* speaker-out */ | 2105 | /* speaker-out */ |
1978 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | 2106 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, |
1979 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | 2107 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
@@ -1999,11 +2127,9 @@ static void alc880_lg_lw_automute(struct hda_codec *codec) | |||
1999 | 2127 | ||
2000 | present = snd_hda_codec_read(codec, 0x1b, 0, | 2128 | present = snd_hda_codec_read(codec, 0x1b, 0, |
2001 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 2129 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
2002 | bits = present ? 0x80 : 0; | 2130 | bits = present ? HDA_AMP_MUTE : 0; |
2003 | snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, | 2131 | snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, |
2004 | 0x80, bits); | 2132 | HDA_AMP_MUTE, bits); |
2005 | snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, | ||
2006 | 0x80, bits); | ||
2007 | } | 2133 | } |
2008 | 2134 | ||
2009 | static void alc880_lg_lw_unsol_event(struct hda_codec *codec, unsigned int res) | 2135 | static void alc880_lg_lw_unsol_event(struct hda_codec *codec, unsigned int res) |
@@ -2015,6 +2141,24 @@ static void alc880_lg_lw_unsol_event(struct hda_codec *codec, unsigned int res) | |||
2015 | alc880_lg_lw_automute(codec); | 2141 | alc880_lg_lw_automute(codec); |
2016 | } | 2142 | } |
2017 | 2143 | ||
2144 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
2145 | static struct hda_amp_list alc880_loopbacks[] = { | ||
2146 | { 0x0b, HDA_INPUT, 0 }, | ||
2147 | { 0x0b, HDA_INPUT, 1 }, | ||
2148 | { 0x0b, HDA_INPUT, 2 }, | ||
2149 | { 0x0b, HDA_INPUT, 3 }, | ||
2150 | { 0x0b, HDA_INPUT, 4 }, | ||
2151 | { } /* end */ | ||
2152 | }; | ||
2153 | |||
2154 | static struct hda_amp_list alc880_lg_loopbacks[] = { | ||
2155 | { 0x0b, HDA_INPUT, 1 }, | ||
2156 | { 0x0b, HDA_INPUT, 6 }, | ||
2157 | { 0x0b, HDA_INPUT, 7 }, | ||
2158 | { } /* end */ | ||
2159 | }; | ||
2160 | #endif | ||
2161 | |||
2018 | /* | 2162 | /* |
2019 | * Common callbacks | 2163 | * Common callbacks |
2020 | */ | 2164 | */ |
@@ -2041,24 +2185,11 @@ static void alc_unsol_event(struct hda_codec *codec, unsigned int res) | |||
2041 | spec->unsol_event(codec, res); | 2185 | spec->unsol_event(codec, res); |
2042 | } | 2186 | } |
2043 | 2187 | ||
2044 | #ifdef CONFIG_PM | 2188 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
2045 | /* | 2189 | static int alc_check_power_status(struct hda_codec *codec, hda_nid_t nid) |
2046 | * resume | ||
2047 | */ | ||
2048 | static int alc_resume(struct hda_codec *codec) | ||
2049 | { | 2190 | { |
2050 | struct alc_spec *spec = codec->spec; | 2191 | struct alc_spec *spec = codec->spec; |
2051 | int i; | 2192 | return snd_hda_check_amp_list_power(codec, &spec->loopback, nid); |
2052 | |||
2053 | alc_init(codec); | ||
2054 | for (i = 0; i < spec->num_mixers; i++) | ||
2055 | snd_hda_resume_ctls(codec, spec->mixers[i]); | ||
2056 | if (spec->multiout.dig_out_nid) | ||
2057 | snd_hda_resume_spdif_out(codec); | ||
2058 | if (spec->dig_in_nid) | ||
2059 | snd_hda_resume_spdif_in(codec); | ||
2060 | |||
2061 | return 0; | ||
2062 | } | 2193 | } |
2063 | #endif | 2194 | #endif |
2064 | 2195 | ||
@@ -2293,8 +2424,8 @@ static struct hda_codec_ops alc_patch_ops = { | |||
2293 | .init = alc_init, | 2424 | .init = alc_init, |
2294 | .free = alc_free, | 2425 | .free = alc_free, |
2295 | .unsol_event = alc_unsol_event, | 2426 | .unsol_event = alc_unsol_event, |
2296 | #ifdef CONFIG_PM | 2427 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
2297 | .resume = alc_resume, | 2428 | .check_power_status = alc_check_power_status, |
2298 | #endif | 2429 | #endif |
2299 | }; | 2430 | }; |
2300 | 2431 | ||
@@ -2392,11 +2523,14 @@ static int alc_test_pin_ctl_put(struct snd_kcontrol *kcontrol, | |||
2392 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | 2523 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); |
2393 | new_ctl = ctls[ucontrol->value.enumerated.item[0]]; | 2524 | new_ctl = ctls[ucontrol->value.enumerated.item[0]]; |
2394 | if (old_ctl != new_ctl) { | 2525 | if (old_ctl != new_ctl) { |
2395 | snd_hda_codec_write(codec, nid, 0, | 2526 | int val; |
2396 | AC_VERB_SET_PIN_WIDGET_CONTROL, new_ctl); | 2527 | snd_hda_codec_write_cache(codec, nid, 0, |
2397 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, | 2528 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
2398 | (ucontrol->value.enumerated.item[0] >= 3 ? | 2529 | new_ctl); |
2399 | 0xb080 : 0xb000)); | 2530 | val = ucontrol->value.enumerated.item[0] >= 3 ? |
2531 | HDA_AMP_MUTE : 0; | ||
2532 | snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, | ||
2533 | HDA_AMP_MUTE, val); | ||
2400 | return 1; | 2534 | return 1; |
2401 | } | 2535 | } |
2402 | return 0; | 2536 | return 0; |
@@ -2439,7 +2573,8 @@ static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol, | |||
2439 | sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3; | 2573 | sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3; |
2440 | if (ucontrol->value.enumerated.item[0] != sel) { | 2574 | if (ucontrol->value.enumerated.item[0] != sel) { |
2441 | sel = ucontrol->value.enumerated.item[0] & 3; | 2575 | sel = ucontrol->value.enumerated.item[0] & 3; |
2442 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, sel); | 2576 | snd_hda_codec_write_cache(codec, nid, 0, |
2577 | AC_VERB_SET_CONNECT_SEL, sel); | ||
2443 | return 1; | 2578 | return 1; |
2444 | } | 2579 | } |
2445 | return 0; | 2580 | return 0; |
@@ -2885,6 +3020,7 @@ static struct alc_config_preset alc880_presets[] = { | |||
2885 | alc880_beep_init_verbs }, | 3020 | alc880_beep_init_verbs }, |
2886 | .num_dacs = ARRAY_SIZE(alc880_dac_nids), | 3021 | .num_dacs = ARRAY_SIZE(alc880_dac_nids), |
2887 | .dac_nids = alc880_dac_nids, | 3022 | .dac_nids = alc880_dac_nids, |
3023 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
2888 | .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), | 3024 | .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), |
2889 | .channel_mode = alc880_2_jack_modes, | 3025 | .channel_mode = alc880_2_jack_modes, |
2890 | .input_mux = &alc880_capture_source, | 3026 | .input_mux = &alc880_capture_source, |
@@ -2916,6 +3052,9 @@ static struct alc_config_preset alc880_presets[] = { | |||
2916 | .input_mux = &alc880_lg_capture_source, | 3052 | .input_mux = &alc880_lg_capture_source, |
2917 | .unsol_event = alc880_lg_unsol_event, | 3053 | .unsol_event = alc880_lg_unsol_event, |
2918 | .init_hook = alc880_lg_automute, | 3054 | .init_hook = alc880_lg_automute, |
3055 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
3056 | .loopbacks = alc880_lg_loopbacks, | ||
3057 | #endif | ||
2919 | }, | 3058 | }, |
2920 | [ALC880_LG_LW] = { | 3059 | [ALC880_LG_LW] = { |
2921 | .mixers = { alc880_lg_lw_mixer }, | 3060 | .mixers = { alc880_lg_lw_mixer }, |
@@ -3399,6 +3538,10 @@ static int patch_alc880(struct hda_codec *codec) | |||
3399 | codec->patch_ops = alc_patch_ops; | 3538 | codec->patch_ops = alc_patch_ops; |
3400 | if (board_config == ALC880_AUTO) | 3539 | if (board_config == ALC880_AUTO) |
3401 | spec->init_hook = alc880_auto_init; | 3540 | spec->init_hook = alc880_auto_init; |
3541 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
3542 | if (!spec->loopback.amplist) | ||
3543 | spec->loopback.amplist = alc880_loopbacks; | ||
3544 | #endif | ||
3402 | 3545 | ||
3403 | return 0; | 3546 | return 0; |
3404 | } | 3547 | } |
@@ -3747,12 +3890,12 @@ static struct hda_verb alc260_init_verbs[] = { | |||
3747 | /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & | 3890 | /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & |
3748 | * Line In 2 = 0x03 | 3891 | * Line In 2 = 0x03 |
3749 | */ | 3892 | */ |
3750 | /* mute CD */ | 3893 | /* mute analog inputs */ |
3751 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 3894 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
3752 | /* mute Line In */ | 3895 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
3753 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 3896 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
3754 | /* mute Mic */ | 3897 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
3755 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 3898 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
3756 | /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ | 3899 | /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ |
3757 | /* mute Front out path */ | 3900 | /* mute Front out path */ |
3758 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | 3901 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
@@ -3797,12 +3940,12 @@ static struct hda_verb alc260_hp_init_verbs[] = { | |||
3797 | /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & | 3940 | /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & |
3798 | * Line In 2 = 0x03 | 3941 | * Line In 2 = 0x03 |
3799 | */ | 3942 | */ |
3800 | /* unmute CD */ | 3943 | /* mute analog inputs */ |
3801 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, | 3944 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
3802 | /* unmute Line In */ | 3945 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
3803 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, | 3946 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
3804 | /* unmute Mic */ | 3947 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
3805 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 3948 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
3806 | /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ | 3949 | /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ |
3807 | /* Unmute Front out path */ | 3950 | /* Unmute Front out path */ |
3808 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 3951 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, |
@@ -3847,12 +3990,12 @@ static struct hda_verb alc260_hp_3013_init_verbs[] = { | |||
3847 | /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & | 3990 | /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & |
3848 | * Line In 2 = 0x03 | 3991 | * Line In 2 = 0x03 |
3849 | */ | 3992 | */ |
3850 | /* unmute CD */ | 3993 | /* mute analog inputs */ |
3851 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, | 3994 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
3852 | /* unmute Line In */ | 3995 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
3853 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, | 3996 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
3854 | /* unmute Mic */ | 3997 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
3855 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 3998 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
3856 | /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ | 3999 | /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ |
3857 | /* Unmute Front out path */ | 4000 | /* Unmute Front out path */ |
3858 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 4001 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, |
@@ -4069,13 +4212,17 @@ static void alc260_replacer_672v_automute(struct hda_codec *codec) | |||
4069 | present = snd_hda_codec_read(codec, 0x0f, 0, | 4212 | present = snd_hda_codec_read(codec, 0x0f, 0, |
4070 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 4213 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
4071 | if (present) { | 4214 | if (present) { |
4072 | snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 1); | 4215 | snd_hda_codec_write_cache(codec, 0x01, 0, |
4073 | snd_hda_codec_write(codec, 0x0f, 0, | 4216 | AC_VERB_SET_GPIO_DATA, 1); |
4074 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP); | 4217 | snd_hda_codec_write_cache(codec, 0x0f, 0, |
4218 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
4219 | PIN_HP); | ||
4075 | } else { | 4220 | } else { |
4076 | snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 0); | 4221 | snd_hda_codec_write_cache(codec, 0x01, 0, |
4077 | snd_hda_codec_write(codec, 0x0f, 0, | 4222 | AC_VERB_SET_GPIO_DATA, 0); |
4078 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); | 4223 | snd_hda_codec_write_cache(codec, 0x0f, 0, |
4224 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
4225 | PIN_OUT); | ||
4079 | } | 4226 | } |
4080 | } | 4227 | } |
4081 | 4228 | ||
@@ -4470,11 +4617,12 @@ static struct hda_verb alc260_volume_init_verbs[] = { | |||
4470 | * front panel mic (mic 2) | 4617 | * front panel mic (mic 2) |
4471 | */ | 4618 | */ |
4472 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | 4619 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ |
4473 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 4620 | /* mute analog inputs */ |
4474 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 4621 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
4475 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 4622 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
4476 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 4623 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
4477 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 4624 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
4625 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
4478 | 4626 | ||
4479 | /* | 4627 | /* |
4480 | * Set up output mixers (0x08 - 0x0a) | 4628 | * Set up output mixers (0x08 - 0x0a) |
@@ -4551,6 +4699,17 @@ static void alc260_auto_init(struct hda_codec *codec) | |||
4551 | alc260_auto_init_analog_input(codec); | 4699 | alc260_auto_init_analog_input(codec); |
4552 | } | 4700 | } |
4553 | 4701 | ||
4702 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
4703 | static struct hda_amp_list alc260_loopbacks[] = { | ||
4704 | { 0x07, HDA_INPUT, 0 }, | ||
4705 | { 0x07, HDA_INPUT, 1 }, | ||
4706 | { 0x07, HDA_INPUT, 2 }, | ||
4707 | { 0x07, HDA_INPUT, 3 }, | ||
4708 | { 0x07, HDA_INPUT, 4 }, | ||
4709 | { } /* end */ | ||
4710 | }; | ||
4711 | #endif | ||
4712 | |||
4554 | /* | 4713 | /* |
4555 | * ALC260 configurations | 4714 | * ALC260 configurations |
4556 | */ | 4715 | */ |
@@ -4750,6 +4909,10 @@ static int patch_alc260(struct hda_codec *codec) | |||
4750 | codec->patch_ops = alc_patch_ops; | 4909 | codec->patch_ops = alc_patch_ops; |
4751 | if (board_config == ALC260_AUTO) | 4910 | if (board_config == ALC260_AUTO) |
4752 | spec->init_hook = alc260_auto_init; | 4911 | spec->init_hook = alc260_auto_init; |
4912 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
4913 | if (!spec->loopback.amplist) | ||
4914 | spec->loopback.amplist = alc260_loopbacks; | ||
4915 | #endif | ||
4753 | 4916 | ||
4754 | return 0; | 4917 | return 0; |
4755 | } | 4918 | } |
@@ -4812,12 +4975,13 @@ static int alc882_mux_enum_put(struct snd_kcontrol *kcontrol, | |||
4812 | idx = ucontrol->value.enumerated.item[0]; | 4975 | idx = ucontrol->value.enumerated.item[0]; |
4813 | if (idx >= imux->num_items) | 4976 | if (idx >= imux->num_items) |
4814 | idx = imux->num_items - 1; | 4977 | idx = imux->num_items - 1; |
4815 | if (*cur_val == idx && !codec->in_resume) | 4978 | if (*cur_val == idx) |
4816 | return 0; | 4979 | return 0; |
4817 | for (i = 0; i < imux->num_items; i++) { | 4980 | for (i = 0; i < imux->num_items; i++) { |
4818 | unsigned int v = (i == idx) ? 0x7000 : 0x7080; | 4981 | unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE; |
4819 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, | 4982 | snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, |
4820 | v | (imux->items[i].index << 8)); | 4983 | imux->items[i].index, |
4984 | HDA_AMP_MUTE, v); | ||
4821 | } | 4985 | } |
4822 | *cur_val = idx; | 4986 | *cur_val = idx; |
4823 | return 1; | 4987 | return 1; |
@@ -4879,6 +5043,38 @@ static struct hda_channel_mode alc882_sixstack_modes[2] = { | |||
4879 | { 8, alc882_sixstack_ch8_init }, | 5043 | { 8, alc882_sixstack_ch8_init }, |
4880 | }; | 5044 | }; |
4881 | 5045 | ||
5046 | /* | ||
5047 | * macbook pro ALC885 can switch LineIn to LineOut without loosing Mic | ||
5048 | */ | ||
5049 | |||
5050 | /* | ||
5051 | * 2ch mode | ||
5052 | */ | ||
5053 | static struct hda_verb alc885_mbp_ch2_init[] = { | ||
5054 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | ||
5055 | { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
5056 | { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
5057 | { } /* end */ | ||
5058 | }; | ||
5059 | |||
5060 | /* | ||
5061 | * 6ch mode | ||
5062 | */ | ||
5063 | static struct hda_verb alc885_mbp_ch6_init[] = { | ||
5064 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
5065 | { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
5066 | { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 }, | ||
5067 | { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
5068 | { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
5069 | { } /* end */ | ||
5070 | }; | ||
5071 | |||
5072 | static struct hda_channel_mode alc885_mbp_6ch_modes[2] = { | ||
5073 | { 2, alc885_mbp_ch2_init }, | ||
5074 | { 6, alc885_mbp_ch6_init }, | ||
5075 | }; | ||
5076 | |||
5077 | |||
4882 | /* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17 | 5078 | /* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17 |
4883 | * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b | 5079 | * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b |
4884 | */ | 5080 | */ |
@@ -4909,6 +5105,19 @@ static struct snd_kcontrol_new alc882_base_mixer[] = { | |||
4909 | { } /* end */ | 5105 | { } /* end */ |
4910 | }; | 5106 | }; |
4911 | 5107 | ||
5108 | static struct snd_kcontrol_new alc885_mbp3_mixer[] = { | ||
5109 | HDA_CODEC_VOLUME("Master Volume", 0x0c, 0x00, HDA_OUTPUT), | ||
5110 | HDA_BIND_MUTE ("Master Switch", 0x0c, 0x02, HDA_INPUT), | ||
5111 | HDA_CODEC_MUTE ("Speaker Switch", 0x14, 0x00, HDA_OUTPUT), | ||
5112 | HDA_CODEC_VOLUME("Line Out Volume", 0x0d,0x00, HDA_OUTPUT), | ||
5113 | HDA_CODEC_VOLUME("Line In Playback Volume", 0x0b, 0x02, HDA_INPUT), | ||
5114 | HDA_CODEC_MUTE ("Line In Playback Switch", 0x0b, 0x02, HDA_INPUT), | ||
5115 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT), | ||
5116 | HDA_CODEC_MUTE ("Mic Playback Switch", 0x0b, 0x00, HDA_INPUT), | ||
5117 | HDA_CODEC_VOLUME("Line In Boost", 0x1a, 0x00, HDA_INPUT), | ||
5118 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x00, HDA_INPUT), | ||
5119 | { } /* end */ | ||
5120 | }; | ||
4912 | static struct snd_kcontrol_new alc882_w2jc_mixer[] = { | 5121 | static struct snd_kcontrol_new alc882_w2jc_mixer[] = { |
4913 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | 5122 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), |
4914 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | 5123 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), |
@@ -4934,8 +5143,10 @@ static struct snd_kcontrol_new alc882_targa_mixer[] = { | |||
4934 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | 5143 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), |
4935 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 5144 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
4936 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 5145 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
5146 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | ||
4937 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 5147 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
4938 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 5148 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
5149 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | ||
4939 | { } /* end */ | 5150 | { } /* end */ |
4940 | }; | 5151 | }; |
4941 | 5152 | ||
@@ -4955,6 +5166,23 @@ static struct snd_kcontrol_new alc882_asus_a7j_mixer[] = { | |||
4955 | HDA_CODEC_MUTE("Mobile Line Playback Switch", 0x0b, 0x03, HDA_INPUT), | 5166 | HDA_CODEC_MUTE("Mobile Line Playback Switch", 0x0b, 0x03, HDA_INPUT), |
4956 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 5167 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
4957 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 5168 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
5169 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | ||
5170 | { } /* end */ | ||
5171 | }; | ||
5172 | |||
5173 | static struct snd_kcontrol_new alc882_asus_a7m_mixer[] = { | ||
5174 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
5175 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | ||
5176 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), | ||
5177 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
5178 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
5179 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | ||
5180 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | ||
5181 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
5182 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | ||
5183 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
5184 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
5185 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
4958 | { } /* end */ | 5186 | { } /* end */ |
4959 | }; | 5187 | }; |
4960 | 5188 | ||
@@ -5119,6 +5347,66 @@ static struct hda_verb alc882_macpro_init_verbs[] = { | |||
5119 | { } | 5347 | { } |
5120 | }; | 5348 | }; |
5121 | 5349 | ||
5350 | /* Macbook Pro rev3 */ | ||
5351 | static struct hda_verb alc885_mbp3_init_verbs[] = { | ||
5352 | /* Front mixer: unmute input/output amp left and right (volume = 0) */ | ||
5353 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
5354 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
5355 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
5356 | /* Rear mixer */ | ||
5357 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
5358 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
5359 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
5360 | /* Front Pin: output 0 (0x0c) */ | ||
5361 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
5362 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
5363 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
5364 | /* HP Pin: output 0 (0x0d) */ | ||
5365 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4}, | ||
5366 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
5367 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
5368 | {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, | ||
5369 | /* Mic (rear) pin: input vref at 80% */ | ||
5370 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
5371 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
5372 | /* Front Mic pin: input vref at 80% */ | ||
5373 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
5374 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
5375 | /* Line In pin: use output 1 when in LineOut mode */ | ||
5376 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
5377 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
5378 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
5379 | |||
5380 | /* FIXME: use matrix-type input source selection */ | ||
5381 | /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ | ||
5382 | /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ | ||
5383 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
5384 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
5385 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
5386 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
5387 | /* Input mixer2 */ | ||
5388 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
5389 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
5390 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
5391 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
5392 | /* Input mixer3 */ | ||
5393 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
5394 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
5395 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
5396 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
5397 | /* ADC1: mute amp left and right */ | ||
5398 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
5399 | {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
5400 | /* ADC2: mute amp left and right */ | ||
5401 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
5402 | {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
5403 | /* ADC3: mute amp left and right */ | ||
5404 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
5405 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
5406 | |||
5407 | { } | ||
5408 | }; | ||
5409 | |||
5122 | /* iMac 24 mixer. */ | 5410 | /* iMac 24 mixer. */ |
5123 | static struct snd_kcontrol_new alc885_imac24_mixer[] = { | 5411 | static struct snd_kcontrol_new alc885_imac24_mixer[] = { |
5124 | HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x00, HDA_OUTPUT), | 5412 | HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x00, HDA_OUTPUT), |
@@ -5154,14 +5442,10 @@ static void alc885_imac24_automute(struct hda_codec *codec) | |||
5154 | 5442 | ||
5155 | present = snd_hda_codec_read(codec, 0x14, 0, | 5443 | present = snd_hda_codec_read(codec, 0x14, 0, |
5156 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 5444 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
5157 | snd_hda_codec_amp_update(codec, 0x18, 0, HDA_OUTPUT, 0, | 5445 | snd_hda_codec_amp_stereo(codec, 0x18, HDA_OUTPUT, 0, |
5158 | 0x80, present ? 0x80 : 0); | 5446 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); |
5159 | snd_hda_codec_amp_update(codec, 0x18, 1, HDA_OUTPUT, 0, | 5447 | snd_hda_codec_amp_stereo(codec, 0x1a, HDA_OUTPUT, 0, |
5160 | 0x80, present ? 0x80 : 0); | 5448 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); |
5161 | snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_OUTPUT, 0, | ||
5162 | 0x80, present ? 0x80 : 0); | ||
5163 | snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_OUTPUT, 0, | ||
5164 | 0x80, present ? 0x80 : 0); | ||
5165 | } | 5449 | } |
5166 | 5450 | ||
5167 | /* Processes unsolicited events. */ | 5451 | /* Processes unsolicited events. */ |
@@ -5173,6 +5457,27 @@ static void alc885_imac24_unsol_event(struct hda_codec *codec, | |||
5173 | alc885_imac24_automute(codec); | 5457 | alc885_imac24_automute(codec); |
5174 | } | 5458 | } |
5175 | 5459 | ||
5460 | static void alc885_mbp3_automute(struct hda_codec *codec) | ||
5461 | { | ||
5462 | unsigned int present; | ||
5463 | |||
5464 | present = snd_hda_codec_read(codec, 0x15, 0, | ||
5465 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
5466 | snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, | ||
5467 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); | ||
5468 | snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, | ||
5469 | HDA_AMP_MUTE, present ? 0 : HDA_AMP_MUTE); | ||
5470 | |||
5471 | } | ||
5472 | static void alc885_mbp3_unsol_event(struct hda_codec *codec, | ||
5473 | unsigned int res) | ||
5474 | { | ||
5475 | /* Headphone insertion or removal. */ | ||
5476 | if ((res >> 26) == ALC880_HP_EVENT) | ||
5477 | alc885_mbp3_automute(codec); | ||
5478 | } | ||
5479 | |||
5480 | |||
5176 | static struct hda_verb alc882_targa_verbs[] = { | 5481 | static struct hda_verb alc882_targa_verbs[] = { |
5177 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 5482 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
5178 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 5483 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
@@ -5198,11 +5503,10 @@ static void alc882_targa_automute(struct hda_codec *codec) | |||
5198 | 5503 | ||
5199 | present = snd_hda_codec_read(codec, 0x14, 0, | 5504 | present = snd_hda_codec_read(codec, 0x14, 0, |
5200 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 5505 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
5201 | snd_hda_codec_amp_update(codec, 0x1b, 0, HDA_OUTPUT, 0, | 5506 | snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0, |
5202 | 0x80, present ? 0x80 : 0); | 5507 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); |
5203 | snd_hda_codec_amp_update(codec, 0x1b, 1, HDA_OUTPUT, 0, | 5508 | snd_hda_codec_write_cache(codec, 1, 0, AC_VERB_SET_GPIO_DATA, |
5204 | 0x80, present ? 0x80 : 0); | 5509 | present ? 1 : 3); |
5205 | snd_hda_codec_write(codec, 1, 0, AC_VERB_SET_GPIO_DATA, present ? 1 : 3); | ||
5206 | } | 5510 | } |
5207 | 5511 | ||
5208 | static void alc882_targa_unsol_event(struct hda_codec *codec, unsigned int res) | 5512 | static void alc882_targa_unsol_event(struct hda_codec *codec, unsigned int res) |
@@ -5233,6 +5537,24 @@ static struct hda_verb alc882_asus_a7j_verbs[] = { | |||
5233 | { } /* end */ | 5537 | { } /* end */ |
5234 | }; | 5538 | }; |
5235 | 5539 | ||
5540 | static struct hda_verb alc882_asus_a7m_verbs[] = { | ||
5541 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
5542 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
5543 | |||
5544 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
5545 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
5546 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
5547 | |||
5548 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */ | ||
5549 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ | ||
5550 | {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */ | ||
5551 | |||
5552 | {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */ | ||
5553 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */ | ||
5554 | {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ | ||
5555 | { } /* end */ | ||
5556 | }; | ||
5557 | |||
5236 | static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted) | 5558 | static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted) |
5237 | { | 5559 | { |
5238 | unsigned int gpiostate, gpiomask, gpiodir; | 5560 | unsigned int gpiostate, gpiomask, gpiodir; |
@@ -5265,6 +5587,20 @@ static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted) | |||
5265 | AC_VERB_SET_GPIO_DATA, gpiostate); | 5587 | AC_VERB_SET_GPIO_DATA, gpiostate); |
5266 | } | 5588 | } |
5267 | 5589 | ||
5590 | /* set up GPIO at initialization */ | ||
5591 | static void alc885_macpro_init_hook(struct hda_codec *codec) | ||
5592 | { | ||
5593 | alc882_gpio_mute(codec, 0, 0); | ||
5594 | alc882_gpio_mute(codec, 1, 0); | ||
5595 | } | ||
5596 | |||
5597 | /* set up GPIO and update auto-muting at initialization */ | ||
5598 | static void alc885_imac24_init_hook(struct hda_codec *codec) | ||
5599 | { | ||
5600 | alc885_macpro_init_hook(codec); | ||
5601 | alc885_imac24_automute(codec); | ||
5602 | } | ||
5603 | |||
5268 | /* | 5604 | /* |
5269 | * generic initialization of ADC, input mixers and output mixers | 5605 | * generic initialization of ADC, input mixers and output mixers |
5270 | */ | 5606 | */ |
@@ -5279,17 +5615,17 @@ static struct hda_verb alc882_auto_init_verbs[] = { | |||
5279 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | 5615 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, |
5280 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 5616 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
5281 | 5617 | ||
5282 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | 5618 | /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback |
5283 | * mixer widget | 5619 | * mixer widget |
5284 | * Note: PASD motherboards uses the Line In 2 as the input for | 5620 | * Note: PASD motherboards uses the Line In 2 as the input for |
5285 | * front panel mic (mic 2) | 5621 | * front panel mic (mic 2) |
5286 | */ | 5622 | */ |
5287 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | 5623 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ |
5288 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 5624 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
5289 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 5625 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
5290 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 5626 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
5291 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 5627 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
5292 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 5628 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
5293 | 5629 | ||
5294 | /* | 5630 | /* |
5295 | * Set up output mixers (0x0c - 0x0f) | 5631 | * Set up output mixers (0x0c - 0x0f) |
@@ -5378,6 +5714,10 @@ static struct snd_kcontrol_new alc882_capture_mixer[] = { | |||
5378 | { } /* end */ | 5714 | { } /* end */ |
5379 | }; | 5715 | }; |
5380 | 5716 | ||
5717 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
5718 | #define alc882_loopbacks alc880_loopbacks | ||
5719 | #endif | ||
5720 | |||
5381 | /* pcm configuration: identiacal with ALC880 */ | 5721 | /* pcm configuration: identiacal with ALC880 */ |
5382 | #define alc882_pcm_analog_playback alc880_pcm_analog_playback | 5722 | #define alc882_pcm_analog_playback alc880_pcm_analog_playback |
5383 | #define alc882_pcm_analog_capture alc880_pcm_analog_capture | 5723 | #define alc882_pcm_analog_capture alc880_pcm_analog_capture |
@@ -5392,7 +5732,11 @@ static const char *alc882_models[ALC882_MODEL_LAST] = { | |||
5392 | [ALC882_6ST_DIG] = "6stack-dig", | 5732 | [ALC882_6ST_DIG] = "6stack-dig", |
5393 | [ALC882_ARIMA] = "arima", | 5733 | [ALC882_ARIMA] = "arima", |
5394 | [ALC882_W2JC] = "w2jc", | 5734 | [ALC882_W2JC] = "w2jc", |
5735 | [ALC882_TARGA] = "targa", | ||
5736 | [ALC882_ASUS_A7J] = "asus-a7j", | ||
5737 | [ALC882_ASUS_A7M] = "asus-a7m", | ||
5395 | [ALC885_MACPRO] = "macpro", | 5738 | [ALC885_MACPRO] = "macpro", |
5739 | [ALC885_MBP3] = "mbp3", | ||
5396 | [ALC885_IMAC24] = "imac24", | 5740 | [ALC885_IMAC24] = "imac24", |
5397 | [ALC882_AUTO] = "auto", | 5741 | [ALC882_AUTO] = "auto", |
5398 | }; | 5742 | }; |
@@ -5404,6 +5748,8 @@ static struct snd_pci_quirk alc882_cfg_tbl[] = { | |||
5404 | SND_PCI_QUIRK(0x1462, 0x28fb, "Targa T8", ALC882_TARGA), /* MSI-1049 T8 */ | 5748 | SND_PCI_QUIRK(0x1462, 0x28fb, "Targa T8", ALC882_TARGA), /* MSI-1049 T8 */ |
5405 | SND_PCI_QUIRK(0x161f, 0x2054, "Arima W820", ALC882_ARIMA), | 5749 | SND_PCI_QUIRK(0x161f, 0x2054, "Arima W820", ALC882_ARIMA), |
5406 | SND_PCI_QUIRK(0x1043, 0x060d, "Asus A7J", ALC882_ASUS_A7J), | 5750 | SND_PCI_QUIRK(0x1043, 0x060d, "Asus A7J", ALC882_ASUS_A7J), |
5751 | SND_PCI_QUIRK(0x1043, 0x1243, "Asus A7J", ALC882_ASUS_A7J), | ||
5752 | SND_PCI_QUIRK(0x1043, 0x13c2, "Asus A7M", ALC882_ASUS_A7M), | ||
5407 | SND_PCI_QUIRK(0x1043, 0x817f, "Asus P5LD2", ALC882_6ST_DIG), | 5753 | SND_PCI_QUIRK(0x1043, 0x817f, "Asus P5LD2", ALC882_6ST_DIG), |
5408 | SND_PCI_QUIRK(0x1043, 0x81d8, "Asus P5WD", ALC882_6ST_DIG), | 5754 | SND_PCI_QUIRK(0x1043, 0x81d8, "Asus P5WD", ALC882_6ST_DIG), |
5409 | SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_W2JC), | 5755 | SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_W2JC), |
@@ -5455,6 +5801,20 @@ static struct alc_config_preset alc882_presets[] = { | |||
5455 | .input_mux = &alc882_capture_source, | 5801 | .input_mux = &alc882_capture_source, |
5456 | .dig_out_nid = ALC882_DIGOUT_NID, | 5802 | .dig_out_nid = ALC882_DIGOUT_NID, |
5457 | }, | 5803 | }, |
5804 | [ALC885_MBP3] = { | ||
5805 | .mixers = { alc885_mbp3_mixer, alc882_chmode_mixer }, | ||
5806 | .init_verbs = { alc885_mbp3_init_verbs, | ||
5807 | alc880_gpio1_init_verbs }, | ||
5808 | .num_dacs = ARRAY_SIZE(alc882_dac_nids), | ||
5809 | .dac_nids = alc882_dac_nids, | ||
5810 | .channel_mode = alc885_mbp_6ch_modes, | ||
5811 | .num_channel_mode = ARRAY_SIZE(alc885_mbp_6ch_modes), | ||
5812 | .input_mux = &alc882_capture_source, | ||
5813 | .dig_out_nid = ALC882_DIGOUT_NID, | ||
5814 | .dig_in_nid = ALC882_DIGIN_NID, | ||
5815 | .unsol_event = alc885_mbp3_unsol_event, | ||
5816 | .init_hook = alc885_mbp3_automute, | ||
5817 | }, | ||
5458 | [ALC885_MACPRO] = { | 5818 | [ALC885_MACPRO] = { |
5459 | .mixers = { alc882_macpro_mixer }, | 5819 | .mixers = { alc882_macpro_mixer }, |
5460 | .init_verbs = { alc882_macpro_init_verbs }, | 5820 | .init_verbs = { alc882_macpro_init_verbs }, |
@@ -5465,6 +5825,7 @@ static struct alc_config_preset alc882_presets[] = { | |||
5465 | .num_channel_mode = ARRAY_SIZE(alc882_ch_modes), | 5825 | .num_channel_mode = ARRAY_SIZE(alc882_ch_modes), |
5466 | .channel_mode = alc882_ch_modes, | 5826 | .channel_mode = alc882_ch_modes, |
5467 | .input_mux = &alc882_capture_source, | 5827 | .input_mux = &alc882_capture_source, |
5828 | .init_hook = alc885_macpro_init_hook, | ||
5468 | }, | 5829 | }, |
5469 | [ALC885_IMAC24] = { | 5830 | [ALC885_IMAC24] = { |
5470 | .mixers = { alc885_imac24_mixer }, | 5831 | .mixers = { alc885_imac24_mixer }, |
@@ -5477,7 +5838,7 @@ static struct alc_config_preset alc882_presets[] = { | |||
5477 | .channel_mode = alc882_ch_modes, | 5838 | .channel_mode = alc882_ch_modes, |
5478 | .input_mux = &alc882_capture_source, | 5839 | .input_mux = &alc882_capture_source, |
5479 | .unsol_event = alc885_imac24_unsol_event, | 5840 | .unsol_event = alc885_imac24_unsol_event, |
5480 | .init_hook = alc885_imac24_automute, | 5841 | .init_hook = alc885_imac24_init_hook, |
5481 | }, | 5842 | }, |
5482 | [ALC882_TARGA] = { | 5843 | [ALC882_TARGA] = { |
5483 | .mixers = { alc882_targa_mixer, alc882_chmode_mixer, | 5844 | .mixers = { alc882_targa_mixer, alc882_chmode_mixer, |
@@ -5509,6 +5870,19 @@ static struct alc_config_preset alc882_presets[] = { | |||
5509 | .need_dac_fix = 1, | 5870 | .need_dac_fix = 1, |
5510 | .input_mux = &alc882_capture_source, | 5871 | .input_mux = &alc882_capture_source, |
5511 | }, | 5872 | }, |
5873 | [ALC882_ASUS_A7M] = { | ||
5874 | .mixers = { alc882_asus_a7m_mixer, alc882_chmode_mixer }, | ||
5875 | .init_verbs = { alc882_init_verbs, alc882_eapd_verbs, | ||
5876 | alc880_gpio1_init_verbs, | ||
5877 | alc882_asus_a7m_verbs }, | ||
5878 | .num_dacs = ARRAY_SIZE(alc882_dac_nids), | ||
5879 | .dac_nids = alc882_dac_nids, | ||
5880 | .dig_out_nid = ALC882_DIGOUT_NID, | ||
5881 | .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), | ||
5882 | .channel_mode = alc880_threestack_modes, | ||
5883 | .need_dac_fix = 1, | ||
5884 | .input_mux = &alc882_capture_source, | ||
5885 | }, | ||
5512 | }; | 5886 | }; |
5513 | 5887 | ||
5514 | 5888 | ||
@@ -5608,6 +5982,32 @@ static void alc882_auto_init_analog_input(struct hda_codec *codec) | |||
5608 | } | 5982 | } |
5609 | } | 5983 | } |
5610 | 5984 | ||
5985 | /* add mic boosts if needed */ | ||
5986 | static int alc_auto_add_mic_boost(struct hda_codec *codec) | ||
5987 | { | ||
5988 | struct alc_spec *spec = codec->spec; | ||
5989 | int err; | ||
5990 | hda_nid_t nid; | ||
5991 | |||
5992 | nid = spec->autocfg.input_pins[AUTO_PIN_MIC]; | ||
5993 | if (nid) { | ||
5994 | err = add_control(spec, ALC_CTL_WIDGET_VOL, | ||
5995 | "Mic Boost", | ||
5996 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT)); | ||
5997 | if (err < 0) | ||
5998 | return err; | ||
5999 | } | ||
6000 | nid = spec->autocfg.input_pins[AUTO_PIN_FRONT_MIC]; | ||
6001 | if (nid) { | ||
6002 | err = add_control(spec, ALC_CTL_WIDGET_VOL, | ||
6003 | "Front Mic Boost", | ||
6004 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT)); | ||
6005 | if (err < 0) | ||
6006 | return err; | ||
6007 | } | ||
6008 | return 0; | ||
6009 | } | ||
6010 | |||
5611 | /* almost identical with ALC880 parser... */ | 6011 | /* almost identical with ALC880 parser... */ |
5612 | static int alc882_parse_auto_config(struct hda_codec *codec) | 6012 | static int alc882_parse_auto_config(struct hda_codec *codec) |
5613 | { | 6013 | { |
@@ -5616,10 +6016,17 @@ static int alc882_parse_auto_config(struct hda_codec *codec) | |||
5616 | 6016 | ||
5617 | if (err < 0) | 6017 | if (err < 0) |
5618 | return err; | 6018 | return err; |
5619 | else if (err > 0) | 6019 | else if (!err) |
5620 | /* hack - override the init verbs */ | 6020 | return 0; /* no config found */ |
5621 | spec->init_verbs[0] = alc882_auto_init_verbs; | 6021 | |
5622 | return err; | 6022 | err = alc_auto_add_mic_boost(codec); |
6023 | if (err < 0) | ||
6024 | return err; | ||
6025 | |||
6026 | /* hack - override the init verbs */ | ||
6027 | spec->init_verbs[0] = alc882_auto_init_verbs; | ||
6028 | |||
6029 | return 1; /* config found */ | ||
5623 | } | 6030 | } |
5624 | 6031 | ||
5625 | /* additional initialization for auto-configuration model */ | 6032 | /* additional initialization for auto-configuration model */ |
@@ -5654,6 +6061,9 @@ static int patch_alc882(struct hda_codec *codec) | |||
5654 | case 0x106b1000: /* iMac 24 */ | 6061 | case 0x106b1000: /* iMac 24 */ |
5655 | board_config = ALC885_IMAC24; | 6062 | board_config = ALC885_IMAC24; |
5656 | break; | 6063 | break; |
6064 | case 0x106b2c00: /* Macbook Pro rev3 */ | ||
6065 | board_config = ALC885_MBP3; | ||
6066 | break; | ||
5657 | default: | 6067 | default: |
5658 | printk(KERN_INFO "hda_codec: Unknown model for ALC882, " | 6068 | printk(KERN_INFO "hda_codec: Unknown model for ALC882, " |
5659 | "trying auto-probe from BIOS...\n"); | 6069 | "trying auto-probe from BIOS...\n"); |
@@ -5680,11 +6090,6 @@ static int patch_alc882(struct hda_codec *codec) | |||
5680 | if (board_config != ALC882_AUTO) | 6090 | if (board_config != ALC882_AUTO) |
5681 | setup_preset(spec, &alc882_presets[board_config]); | 6091 | setup_preset(spec, &alc882_presets[board_config]); |
5682 | 6092 | ||
5683 | if (board_config == ALC885_MACPRO || board_config == ALC885_IMAC24) { | ||
5684 | alc882_gpio_mute(codec, 0, 0); | ||
5685 | alc882_gpio_mute(codec, 1, 0); | ||
5686 | } | ||
5687 | |||
5688 | spec->stream_name_analog = "ALC882 Analog"; | 6093 | spec->stream_name_analog = "ALC882 Analog"; |
5689 | spec->stream_analog_playback = &alc882_pcm_analog_playback; | 6094 | spec->stream_analog_playback = &alc882_pcm_analog_playback; |
5690 | spec->stream_analog_capture = &alc882_pcm_analog_capture; | 6095 | spec->stream_analog_capture = &alc882_pcm_analog_capture; |
@@ -5715,6 +6120,10 @@ static int patch_alc882(struct hda_codec *codec) | |||
5715 | codec->patch_ops = alc_patch_ops; | 6120 | codec->patch_ops = alc_patch_ops; |
5716 | if (board_config == ALC882_AUTO) | 6121 | if (board_config == ALC882_AUTO) |
5717 | spec->init_hook = alc882_auto_init; | 6122 | spec->init_hook = alc882_auto_init; |
6123 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
6124 | if (!spec->loopback.amplist) | ||
6125 | spec->loopback.amplist = alc882_loopbacks; | ||
6126 | #endif | ||
5718 | 6127 | ||
5719 | return 0; | 6128 | return 0; |
5720 | } | 6129 | } |
@@ -5792,12 +6201,13 @@ static int alc883_mux_enum_put(struct snd_kcontrol *kcontrol, | |||
5792 | idx = ucontrol->value.enumerated.item[0]; | 6201 | idx = ucontrol->value.enumerated.item[0]; |
5793 | if (idx >= imux->num_items) | 6202 | if (idx >= imux->num_items) |
5794 | idx = imux->num_items - 1; | 6203 | idx = imux->num_items - 1; |
5795 | if (*cur_val == idx && !codec->in_resume) | 6204 | if (*cur_val == idx) |
5796 | return 0; | 6205 | return 0; |
5797 | for (i = 0; i < imux->num_items; i++) { | 6206 | for (i = 0; i < imux->num_items; i++) { |
5798 | unsigned int v = (i == idx) ? 0x7000 : 0x7080; | 6207 | unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE; |
5799 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, | 6208 | snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, |
5800 | v | (imux->items[i].index << 8)); | 6209 | imux->items[i].index, |
6210 | HDA_AMP_MUTE, v); | ||
5801 | } | 6211 | } |
5802 | *cur_val = idx; | 6212 | *cur_val = idx; |
5803 | return 1; | 6213 | return 1; |
@@ -5822,6 +6232,18 @@ static struct hda_verb alc883_3ST_ch2_init[] = { | |||
5822 | }; | 6232 | }; |
5823 | 6233 | ||
5824 | /* | 6234 | /* |
6235 | * 4ch mode | ||
6236 | */ | ||
6237 | static struct hda_verb alc883_3ST_ch4_init[] = { | ||
6238 | { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, | ||
6239 | { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, | ||
6240 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
6241 | { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, | ||
6242 | { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 }, | ||
6243 | { } /* end */ | ||
6244 | }; | ||
6245 | |||
6246 | /* | ||
5825 | * 6ch mode | 6247 | * 6ch mode |
5826 | */ | 6248 | */ |
5827 | static struct hda_verb alc883_3ST_ch6_init[] = { | 6249 | static struct hda_verb alc883_3ST_ch6_init[] = { |
@@ -5834,8 +6256,9 @@ static struct hda_verb alc883_3ST_ch6_init[] = { | |||
5834 | { } /* end */ | 6256 | { } /* end */ |
5835 | }; | 6257 | }; |
5836 | 6258 | ||
5837 | static struct hda_channel_mode alc883_3ST_6ch_modes[2] = { | 6259 | static struct hda_channel_mode alc883_3ST_6ch_modes[3] = { |
5838 | { 2, alc883_3ST_ch2_init }, | 6260 | { 2, alc883_3ST_ch2_init }, |
6261 | { 4, alc883_3ST_ch4_init }, | ||
5839 | { 6, alc883_3ST_ch6_init }, | 6262 | { 6, alc883_3ST_ch6_init }, |
5840 | }; | 6263 | }; |
5841 | 6264 | ||
@@ -6235,6 +6658,31 @@ static struct snd_kcontrol_new alc888_3st_hp_mixer[] = { | |||
6235 | { } /* end */ | 6658 | { } /* end */ |
6236 | }; | 6659 | }; |
6237 | 6660 | ||
6661 | static struct snd_kcontrol_new alc883_acer_aspire_mixer[] = { | ||
6662 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
6663 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | ||
6664 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT), | ||
6665 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | ||
6666 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | ||
6667 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
6668 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | ||
6669 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
6670 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
6671 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
6672 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), | ||
6673 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), | ||
6674 | { | ||
6675 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
6676 | /* .name = "Capture Source", */ | ||
6677 | .name = "Input Source", | ||
6678 | .count = 2, | ||
6679 | .info = alc883_mux_enum_info, | ||
6680 | .get = alc883_mux_enum_get, | ||
6681 | .put = alc883_mux_enum_put, | ||
6682 | }, | ||
6683 | { } /* end */ | ||
6684 | }; | ||
6685 | |||
6238 | static struct snd_kcontrol_new alc883_chmode_mixer[] = { | 6686 | static struct snd_kcontrol_new alc883_chmode_mixer[] = { |
6239 | { | 6687 | { |
6240 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 6688 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -6270,11 +6718,12 @@ static struct hda_verb alc883_init_verbs[] = { | |||
6270 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | 6718 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
6271 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | 6719 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
6272 | 6720 | ||
6273 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 6721 | /* mute analog input loopbacks */ |
6274 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 6722 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
6275 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 6723 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
6276 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 6724 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
6277 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 6725 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
6726 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
6278 | 6727 | ||
6279 | /* Front Pin: output 0 (0x0c) */ | 6728 | /* Front Pin: output 0 (0x0c) */ |
6280 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | 6729 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
@@ -6366,6 +6815,19 @@ static struct hda_verb alc888_lenovo_ms7195_verbs[] = { | |||
6366 | { } /* end */ | 6815 | { } /* end */ |
6367 | }; | 6816 | }; |
6368 | 6817 | ||
6818 | static struct hda_verb alc883_haier_w66_verbs[] = { | ||
6819 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
6820 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
6821 | |||
6822 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
6823 | |||
6824 | {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
6825 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
6826 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, | ||
6827 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
6828 | { } /* end */ | ||
6829 | }; | ||
6830 | |||
6369 | static struct hda_verb alc888_6st_hp_verbs[] = { | 6831 | static struct hda_verb alc888_6st_hp_verbs[] = { |
6370 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front: output 0 (0x0c) */ | 6832 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front: output 0 (0x0c) */ |
6371 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x02}, /* Rear : output 2 (0x0e) */ | 6833 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x02}, /* Rear : output 2 (0x0e) */ |
@@ -6409,15 +6871,10 @@ static void alc888_lenovo_ms7195_front_automute(struct hda_codec *codec) | |||
6409 | 6871 | ||
6410 | present = snd_hda_codec_read(codec, 0x1b, 0, | 6872 | present = snd_hda_codec_read(codec, 0x1b, 0, |
6411 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 6873 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
6412 | snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, | 6874 | snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, |
6413 | 0x80, present ? 0x80 : 0); | 6875 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); |
6414 | snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, | 6876 | snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, |
6415 | 0x80, present ? 0x80 : 0); | 6877 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); |
6416 | snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, | ||
6417 | 0x80, present ? 0x80 : 0); | ||
6418 | snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, | ||
6419 | 0x80, present ? 0x80 : 0); | ||
6420 | |||
6421 | } | 6878 | } |
6422 | 6879 | ||
6423 | /* toggle RCA according to the front-jack state */ | 6880 | /* toggle RCA according to the front-jack state */ |
@@ -6427,12 +6884,10 @@ static void alc888_lenovo_ms7195_rca_automute(struct hda_codec *codec) | |||
6427 | 6884 | ||
6428 | present = snd_hda_codec_read(codec, 0x14, 0, | 6885 | present = snd_hda_codec_read(codec, 0x14, 0, |
6429 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 6886 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
6430 | snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, | 6887 | snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, |
6431 | 0x80, present ? 0x80 : 0); | 6888 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); |
6432 | snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, | ||
6433 | 0x80, present ? 0x80 : 0); | ||
6434 | |||
6435 | } | 6889 | } |
6890 | |||
6436 | static void alc883_lenovo_ms7195_unsol_event(struct hda_codec *codec, | 6891 | static void alc883_lenovo_ms7195_unsol_event(struct hda_codec *codec, |
6437 | unsigned int res) | 6892 | unsigned int res) |
6438 | { | 6893 | { |
@@ -6459,10 +6914,8 @@ static void alc883_medion_md2_automute(struct hda_codec *codec) | |||
6459 | 6914 | ||
6460 | present = snd_hda_codec_read(codec, 0x14, 0, | 6915 | present = snd_hda_codec_read(codec, 0x14, 0, |
6461 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 6916 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
6462 | snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, | 6917 | snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, |
6463 | 0x80, present ? 0x80 : 0); | 6918 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); |
6464 | snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, | ||
6465 | 0x80, present ? 0x80 : 0); | ||
6466 | } | 6919 | } |
6467 | 6920 | ||
6468 | static void alc883_medion_md2_unsol_event(struct hda_codec *codec, | 6921 | static void alc883_medion_md2_unsol_event(struct hda_codec *codec, |
@@ -6480,13 +6933,11 @@ static void alc883_tagra_automute(struct hda_codec *codec) | |||
6480 | 6933 | ||
6481 | present = snd_hda_codec_read(codec, 0x14, 0, | 6934 | present = snd_hda_codec_read(codec, 0x14, 0, |
6482 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 6935 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
6483 | bits = present ? 0x80 : 0; | 6936 | bits = present ? HDA_AMP_MUTE : 0; |
6484 | snd_hda_codec_amp_update(codec, 0x1b, 0, HDA_OUTPUT, 0, | 6937 | snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0, |
6485 | 0x80, bits); | 6938 | HDA_AMP_MUTE, bits); |
6486 | snd_hda_codec_amp_update(codec, 0x1b, 1, HDA_OUTPUT, 0, | 6939 | snd_hda_codec_write_cache(codec, 1, 0, AC_VERB_SET_GPIO_DATA, |
6487 | 0x80, bits); | 6940 | present ? 1 : 3); |
6488 | snd_hda_codec_write(codec, 1, 0, AC_VERB_SET_GPIO_DATA, | ||
6489 | present ? 1 : 3); | ||
6490 | } | 6941 | } |
6491 | 6942 | ||
6492 | static void alc883_tagra_unsol_event(struct hda_codec *codec, unsigned int res) | 6943 | static void alc883_tagra_unsol_event(struct hda_codec *codec, unsigned int res) |
@@ -6495,6 +6946,25 @@ static void alc883_tagra_unsol_event(struct hda_codec *codec, unsigned int res) | |||
6495 | alc883_tagra_automute(codec); | 6946 | alc883_tagra_automute(codec); |
6496 | } | 6947 | } |
6497 | 6948 | ||
6949 | static void alc883_haier_w66_automute(struct hda_codec *codec) | ||
6950 | { | ||
6951 | unsigned int present; | ||
6952 | unsigned char bits; | ||
6953 | |||
6954 | present = snd_hda_codec_read(codec, 0x1b, 0, | ||
6955 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
6956 | bits = present ? 0x80 : 0; | ||
6957 | snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, | ||
6958 | 0x80, bits); | ||
6959 | } | ||
6960 | |||
6961 | static void alc883_haier_w66_unsol_event(struct hda_codec *codec, | ||
6962 | unsigned int res) | ||
6963 | { | ||
6964 | if ((res >> 26) == ALC880_HP_EVENT) | ||
6965 | alc883_haier_w66_automute(codec); | ||
6966 | } | ||
6967 | |||
6498 | static void alc883_lenovo_101e_ispeaker_automute(struct hda_codec *codec) | 6968 | static void alc883_lenovo_101e_ispeaker_automute(struct hda_codec *codec) |
6499 | { | 6969 | { |
6500 | unsigned int present; | 6970 | unsigned int present; |
@@ -6502,11 +6972,9 @@ static void alc883_lenovo_101e_ispeaker_automute(struct hda_codec *codec) | |||
6502 | 6972 | ||
6503 | present = snd_hda_codec_read(codec, 0x14, 0, | 6973 | present = snd_hda_codec_read(codec, 0x14, 0, |
6504 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 6974 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
6505 | bits = present ? 0x80 : 0; | 6975 | bits = present ? HDA_AMP_MUTE : 0; |
6506 | snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, | 6976 | snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, |
6507 | 0x80, bits); | 6977 | HDA_AMP_MUTE, bits); |
6508 | snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, | ||
6509 | 0x80, bits); | ||
6510 | } | 6978 | } |
6511 | 6979 | ||
6512 | static void alc883_lenovo_101e_all_automute(struct hda_codec *codec) | 6980 | static void alc883_lenovo_101e_all_automute(struct hda_codec *codec) |
@@ -6516,15 +6984,11 @@ static void alc883_lenovo_101e_all_automute(struct hda_codec *codec) | |||
6516 | 6984 | ||
6517 | present = snd_hda_codec_read(codec, 0x1b, 0, | 6985 | present = snd_hda_codec_read(codec, 0x1b, 0, |
6518 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 6986 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
6519 | bits = present ? 0x80 : 0; | 6987 | bits = present ? HDA_AMP_MUTE : 0; |
6520 | snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, | 6988 | snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, |
6521 | 0x80, bits); | 6989 | HDA_AMP_MUTE, bits); |
6522 | snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, | 6990 | snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, |
6523 | 0x80, bits); | 6991 | HDA_AMP_MUTE, bits); |
6524 | snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, | ||
6525 | 0x80, bits); | ||
6526 | snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, | ||
6527 | 0x80, bits); | ||
6528 | } | 6992 | } |
6529 | 6993 | ||
6530 | static void alc883_lenovo_101e_unsol_event(struct hda_codec *codec, | 6994 | static void alc883_lenovo_101e_unsol_event(struct hda_codec *codec, |
@@ -6536,6 +7000,44 @@ static void alc883_lenovo_101e_unsol_event(struct hda_codec *codec, | |||
6536 | alc883_lenovo_101e_ispeaker_automute(codec); | 7000 | alc883_lenovo_101e_ispeaker_automute(codec); |
6537 | } | 7001 | } |
6538 | 7002 | ||
7003 | /* toggle speaker-output according to the hp-jack state */ | ||
7004 | static void alc883_acer_aspire_automute(struct hda_codec *codec) | ||
7005 | { | ||
7006 | unsigned int present; | ||
7007 | |||
7008 | present = snd_hda_codec_read(codec, 0x14, 0, | ||
7009 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
7010 | snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, | ||
7011 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); | ||
7012 | snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0, | ||
7013 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); | ||
7014 | } | ||
7015 | |||
7016 | static void alc883_acer_aspire_unsol_event(struct hda_codec *codec, | ||
7017 | unsigned int res) | ||
7018 | { | ||
7019 | if ((res >> 26) == ALC880_HP_EVENT) | ||
7020 | alc883_acer_aspire_automute(codec); | ||
7021 | } | ||
7022 | |||
7023 | static struct hda_verb alc883_acer_eapd_verbs[] = { | ||
7024 | /* HP Pin: output 0 (0x0c) */ | ||
7025 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
7026 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
7027 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
7028 | /* Front Pin: output 0 (0x0c) */ | ||
7029 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
7030 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
7031 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
7032 | {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
7033 | /* eanable EAPD on medion laptop */ | ||
7034 | {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, | ||
7035 | {0x20, AC_VERB_SET_PROC_COEF, 0x3050}, | ||
7036 | /* enable unsolicited event */ | ||
7037 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, | ||
7038 | { } | ||
7039 | }; | ||
7040 | |||
6539 | /* | 7041 | /* |
6540 | * generic initialization of ADC, input mixers and output mixers | 7042 | * generic initialization of ADC, input mixers and output mixers |
6541 | */ | 7043 | */ |
@@ -6548,17 +7050,17 @@ static struct hda_verb alc883_auto_init_verbs[] = { | |||
6548 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | 7050 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, |
6549 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 7051 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
6550 | 7052 | ||
6551 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | 7053 | /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback |
6552 | * mixer widget | 7054 | * mixer widget |
6553 | * Note: PASD motherboards uses the Line In 2 as the input for | 7055 | * Note: PASD motherboards uses the Line In 2 as the input for |
6554 | * front panel mic (mic 2) | 7056 | * front panel mic (mic 2) |
6555 | */ | 7057 | */ |
6556 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | 7058 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ |
6557 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 7059 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
6558 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 7060 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
6559 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 7061 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
6560 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 7062 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
6561 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 7063 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
6562 | 7064 | ||
6563 | /* | 7065 | /* |
6564 | * Set up output mixers (0x0c - 0x0f) | 7066 | * Set up output mixers (0x0c - 0x0f) |
@@ -6621,6 +7123,10 @@ static struct snd_kcontrol_new alc883_capture_mixer[] = { | |||
6621 | { } /* end */ | 7123 | { } /* end */ |
6622 | }; | 7124 | }; |
6623 | 7125 | ||
7126 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
7127 | #define alc883_loopbacks alc880_loopbacks | ||
7128 | #endif | ||
7129 | |||
6624 | /* pcm configuration: identiacal with ALC880 */ | 7130 | /* pcm configuration: identiacal with ALC880 */ |
6625 | #define alc883_pcm_analog_playback alc880_pcm_analog_playback | 7131 | #define alc883_pcm_analog_playback alc880_pcm_analog_playback |
6626 | #define alc883_pcm_analog_capture alc880_pcm_analog_capture | 7132 | #define alc883_pcm_analog_capture alc880_pcm_analog_capture |
@@ -6638,12 +7144,14 @@ static const char *alc883_models[ALC883_MODEL_LAST] = { | |||
6638 | [ALC883_TARGA_DIG] = "targa-dig", | 7144 | [ALC883_TARGA_DIG] = "targa-dig", |
6639 | [ALC883_TARGA_2ch_DIG] = "targa-2ch-dig", | 7145 | [ALC883_TARGA_2ch_DIG] = "targa-2ch-dig", |
6640 | [ALC883_ACER] = "acer", | 7146 | [ALC883_ACER] = "acer", |
7147 | [ALC883_ACER_ASPIRE] = "acer-aspire", | ||
6641 | [ALC883_MEDION] = "medion", | 7148 | [ALC883_MEDION] = "medion", |
6642 | [ALC883_MEDION_MD2] = "medion-md2", | 7149 | [ALC883_MEDION_MD2] = "medion-md2", |
6643 | [ALC883_LAPTOP_EAPD] = "laptop-eapd", | 7150 | [ALC883_LAPTOP_EAPD] = "laptop-eapd", |
6644 | [ALC883_LENOVO_101E_2ch] = "lenovo-101e", | 7151 | [ALC883_LENOVO_101E_2ch] = "lenovo-101e", |
6645 | [ALC883_LENOVO_NB0763] = "lenovo-nb0763", | 7152 | [ALC883_LENOVO_NB0763] = "lenovo-nb0763", |
6646 | [ALC888_LENOVO_MS7195_DIG] = "lenovo-ms7195-dig", | 7153 | [ALC888_LENOVO_MS7195_DIG] = "lenovo-ms7195-dig", |
7154 | [ALC883_HAIER_W66] = "haier-w66", | ||
6647 | [ALC888_6ST_HP] = "6stack-hp", | 7155 | [ALC888_6ST_HP] = "6stack-hp", |
6648 | [ALC888_3ST_HP] = "3stack-hp", | 7156 | [ALC888_3ST_HP] = "3stack-hp", |
6649 | [ALC883_AUTO] = "auto", | 7157 | [ALC883_AUTO] = "auto", |
@@ -6669,10 +7177,14 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { | |||
6669 | SND_PCI_QUIRK(0x1462, 0x3fcc, "MSI", ALC883_TARGA_DIG), | 7177 | SND_PCI_QUIRK(0x1462, 0x3fcc, "MSI", ALC883_TARGA_DIG), |
6670 | SND_PCI_QUIRK(0x1462, 0x3fc1, "MSI", ALC883_TARGA_DIG), | 7178 | SND_PCI_QUIRK(0x1462, 0x3fc1, "MSI", ALC883_TARGA_DIG), |
6671 | SND_PCI_QUIRK(0x1462, 0x3fc3, "MSI", ALC883_TARGA_DIG), | 7179 | SND_PCI_QUIRK(0x1462, 0x3fc3, "MSI", ALC883_TARGA_DIG), |
7180 | SND_PCI_QUIRK(0x1462, 0x3fdf, "MSI", ALC883_TARGA_DIG), | ||
6672 | SND_PCI_QUIRK(0x1462, 0x4314, "MSI", ALC883_TARGA_DIG), | 7181 | SND_PCI_QUIRK(0x1462, 0x4314, "MSI", ALC883_TARGA_DIG), |
6673 | SND_PCI_QUIRK(0x1462, 0x4319, "MSI", ALC883_TARGA_DIG), | 7182 | SND_PCI_QUIRK(0x1462, 0x4319, "MSI", ALC883_TARGA_DIG), |
6674 | SND_PCI_QUIRK(0x1462, 0x4324, "MSI", ALC883_TARGA_DIG), | 7183 | SND_PCI_QUIRK(0x1462, 0x4324, "MSI", ALC883_TARGA_DIG), |
6675 | SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG), | 7184 | SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG), |
7185 | SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_ACER_ASPIRE), | ||
7186 | SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_ACER_ASPIRE), | ||
7187 | SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_ACER_ASPIRE), | ||
6676 | SND_PCI_QUIRK(0x1025, 0, "Acer laptop", ALC883_ACER), | 7188 | SND_PCI_QUIRK(0x1025, 0, "Acer laptop", ALC883_ACER), |
6677 | SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch), | 7189 | SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch), |
6678 | SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION), | 7190 | SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION), |
@@ -6685,6 +7197,10 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { | |||
6685 | SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP), | 7197 | SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP), |
6686 | SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP), | 7198 | SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP), |
6687 | SND_PCI_QUIRK(0x17c0, 0x4071, "MEDION MD2", ALC883_MEDION_MD2), | 7199 | SND_PCI_QUIRK(0x17c0, 0x4071, "MEDION MD2", ALC883_MEDION_MD2), |
7200 | SND_PCI_QUIRK(0x1991, 0x5625, "Haier W66", ALC883_HAIER_W66), | ||
7201 | SND_PCI_QUIRK(0x17aa, 0x3bfc, "Lenovo NB0763", ALC883_LENOVO_NB0763), | ||
7202 | SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG), | ||
7203 | SND_PCI_QUIRK(0x147b, 0x1083, "Abit IP35-PRO", ALC883_6ST_DIG), | ||
6688 | {} | 7204 | {} |
6689 | }; | 7205 | }; |
6690 | 7206 | ||
@@ -6771,8 +7287,7 @@ static struct alc_config_preset alc883_presets[] = { | |||
6771 | .init_hook = alc883_tagra_automute, | 7287 | .init_hook = alc883_tagra_automute, |
6772 | }, | 7288 | }, |
6773 | [ALC883_ACER] = { | 7289 | [ALC883_ACER] = { |
6774 | .mixers = { alc883_base_mixer, | 7290 | .mixers = { alc883_base_mixer }, |
6775 | alc883_chmode_mixer }, | ||
6776 | /* On TravelMate laptops, GPIO 0 enables the internal speaker | 7291 | /* On TravelMate laptops, GPIO 0 enables the internal speaker |
6777 | * and the headphone jack. Turn this on and rely on the | 7292 | * and the headphone jack. Turn this on and rely on the |
6778 | * standard mute methods whenever the user wants to turn | 7293 | * standard mute methods whenever the user wants to turn |
@@ -6787,6 +7302,20 @@ static struct alc_config_preset alc883_presets[] = { | |||
6787 | .channel_mode = alc883_3ST_2ch_modes, | 7302 | .channel_mode = alc883_3ST_2ch_modes, |
6788 | .input_mux = &alc883_capture_source, | 7303 | .input_mux = &alc883_capture_source, |
6789 | }, | 7304 | }, |
7305 | [ALC883_ACER_ASPIRE] = { | ||
7306 | .mixers = { alc883_acer_aspire_mixer }, | ||
7307 | .init_verbs = { alc883_init_verbs, alc883_acer_eapd_verbs }, | ||
7308 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), | ||
7309 | .dac_nids = alc883_dac_nids, | ||
7310 | .dig_out_nid = ALC883_DIGOUT_NID, | ||
7311 | .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), | ||
7312 | .adc_nids = alc883_adc_nids, | ||
7313 | .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), | ||
7314 | .channel_mode = alc883_3ST_2ch_modes, | ||
7315 | .input_mux = &alc883_capture_source, | ||
7316 | .unsol_event = alc883_acer_aspire_unsol_event, | ||
7317 | .init_hook = alc883_acer_aspire_automute, | ||
7318 | }, | ||
6790 | [ALC883_MEDION] = { | 7319 | [ALC883_MEDION] = { |
6791 | .mixers = { alc883_fivestack_mixer, | 7320 | .mixers = { alc883_fivestack_mixer, |
6792 | alc883_chmode_mixer }, | 7321 | alc883_chmode_mixer }, |
@@ -6815,8 +7344,7 @@ static struct alc_config_preset alc883_presets[] = { | |||
6815 | .init_hook = alc883_medion_md2_automute, | 7344 | .init_hook = alc883_medion_md2_automute, |
6816 | }, | 7345 | }, |
6817 | [ALC883_LAPTOP_EAPD] = { | 7346 | [ALC883_LAPTOP_EAPD] = { |
6818 | .mixers = { alc883_base_mixer, | 7347 | .mixers = { alc883_base_mixer }, |
6819 | alc883_chmode_mixer }, | ||
6820 | .init_verbs = { alc883_init_verbs, alc882_eapd_verbs }, | 7348 | .init_verbs = { alc883_init_verbs, alc882_eapd_verbs }, |
6821 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), | 7349 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), |
6822 | .dac_nids = alc883_dac_nids, | 7350 | .dac_nids = alc883_dac_nids, |
@@ -6867,6 +7395,20 @@ static struct alc_config_preset alc883_presets[] = { | |||
6867 | .input_mux = &alc883_capture_source, | 7395 | .input_mux = &alc883_capture_source, |
6868 | .unsol_event = alc883_lenovo_ms7195_unsol_event, | 7396 | .unsol_event = alc883_lenovo_ms7195_unsol_event, |
6869 | .init_hook = alc888_lenovo_ms7195_front_automute, | 7397 | .init_hook = alc888_lenovo_ms7195_front_automute, |
7398 | }, | ||
7399 | [ALC883_HAIER_W66] = { | ||
7400 | .mixers = { alc883_tagra_2ch_mixer}, | ||
7401 | .init_verbs = { alc883_init_verbs, alc883_haier_w66_verbs}, | ||
7402 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), | ||
7403 | .dac_nids = alc883_dac_nids, | ||
7404 | .dig_out_nid = ALC883_DIGOUT_NID, | ||
7405 | .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), | ||
7406 | .adc_nids = alc883_adc_nids, | ||
7407 | .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), | ||
7408 | .channel_mode = alc883_3ST_2ch_modes, | ||
7409 | .input_mux = &alc883_capture_source, | ||
7410 | .unsol_event = alc883_haier_w66_unsol_event, | ||
7411 | .init_hook = alc883_haier_w66_automute, | ||
6870 | }, | 7412 | }, |
6871 | [ALC888_6ST_HP] = { | 7413 | [ALC888_6ST_HP] = { |
6872 | .mixers = { alc888_6st_hp_mixer, alc883_chmode_mixer }, | 7414 | .mixers = { alc888_6st_hp_mixer, alc883_chmode_mixer }, |
@@ -6977,12 +7519,19 @@ static int alc883_parse_auto_config(struct hda_codec *codec) | |||
6977 | 7519 | ||
6978 | if (err < 0) | 7520 | if (err < 0) |
6979 | return err; | 7521 | return err; |
6980 | else if (err > 0) | 7522 | else if (!err) |
6981 | /* hack - override the init verbs */ | 7523 | return 0; /* no config found */ |
6982 | spec->init_verbs[0] = alc883_auto_init_verbs; | 7524 | |
7525 | err = alc_auto_add_mic_boost(codec); | ||
7526 | if (err < 0) | ||
7527 | return err; | ||
7528 | |||
7529 | /* hack - override the init verbs */ | ||
7530 | spec->init_verbs[0] = alc883_auto_init_verbs; | ||
6983 | spec->mixers[spec->num_mixers] = alc883_capture_mixer; | 7531 | spec->mixers[spec->num_mixers] = alc883_capture_mixer; |
6984 | spec->num_mixers++; | 7532 | spec->num_mixers++; |
6985 | return err; | 7533 | |
7534 | return 1; /* config found */ | ||
6986 | } | 7535 | } |
6987 | 7536 | ||
6988 | /* additional initialization for auto-configuration model */ | 7537 | /* additional initialization for auto-configuration model */ |
@@ -7046,6 +7595,10 @@ static int patch_alc883(struct hda_codec *codec) | |||
7046 | codec->patch_ops = alc_patch_ops; | 7595 | codec->patch_ops = alc_patch_ops; |
7047 | if (board_config == ALC883_AUTO) | 7596 | if (board_config == ALC883_AUTO) |
7048 | spec->init_hook = alc883_auto_init; | 7597 | spec->init_hook = alc883_auto_init; |
7598 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
7599 | if (!spec->loopback.amplist) | ||
7600 | spec->loopback.amplist = alc883_loopbacks; | ||
7601 | #endif | ||
7049 | 7602 | ||
7050 | return 0; | 7603 | return 0; |
7051 | } | 7604 | } |
@@ -7156,9 +7709,46 @@ static struct snd_kcontrol_new alc262_HP_BPC_WildWest_option_mixer[] = { | |||
7156 | { } /* end */ | 7709 | { } /* end */ |
7157 | }; | 7710 | }; |
7158 | 7711 | ||
7712 | /* bind hp and internal speaker mute (with plug check) */ | ||
7713 | static int alc262_sony_master_sw_put(struct snd_kcontrol *kcontrol, | ||
7714 | struct snd_ctl_elem_value *ucontrol) | ||
7715 | { | ||
7716 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
7717 | long *valp = ucontrol->value.integer.value; | ||
7718 | int change; | ||
7719 | |||
7720 | /* change hp mute */ | ||
7721 | change = snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, | ||
7722 | HDA_AMP_MUTE, | ||
7723 | valp[0] ? 0 : HDA_AMP_MUTE); | ||
7724 | change |= snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, | ||
7725 | HDA_AMP_MUTE, | ||
7726 | valp[1] ? 0 : HDA_AMP_MUTE); | ||
7727 | if (change) { | ||
7728 | /* change speaker according to HP jack state */ | ||
7729 | struct alc_spec *spec = codec->spec; | ||
7730 | unsigned int mute; | ||
7731 | if (spec->jack_present) | ||
7732 | mute = HDA_AMP_MUTE; | ||
7733 | else | ||
7734 | mute = snd_hda_codec_amp_read(codec, 0x15, 0, | ||
7735 | HDA_OUTPUT, 0); | ||
7736 | snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, | ||
7737 | HDA_AMP_MUTE, mute); | ||
7738 | } | ||
7739 | return change; | ||
7740 | } | ||
7741 | |||
7159 | static struct snd_kcontrol_new alc262_sony_mixer[] = { | 7742 | static struct snd_kcontrol_new alc262_sony_mixer[] = { |
7160 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | 7743 | HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT), |
7161 | HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT), | 7744 | { |
7745 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
7746 | .name = "Master Playback Switch", | ||
7747 | .info = snd_hda_mixer_amp_switch_info, | ||
7748 | .get = snd_hda_mixer_amp_switch_get, | ||
7749 | .put = alc262_sony_master_sw_put, | ||
7750 | .private_value = HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT), | ||
7751 | }, | ||
7162 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 7752 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
7163 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 7753 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
7164 | HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), | 7754 | HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), |
@@ -7194,17 +7784,17 @@ static struct hda_verb alc262_init_verbs[] = { | |||
7194 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | 7784 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, |
7195 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 7785 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
7196 | 7786 | ||
7197 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | 7787 | /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback |
7198 | * mixer widget | 7788 | * mixer widget |
7199 | * Note: PASD motherboards uses the Line In 2 as the input for | 7789 | * Note: PASD motherboards uses the Line In 2 as the input for |
7200 | * front panel mic (mic 2) | 7790 | * front panel mic (mic 2) |
7201 | */ | 7791 | */ |
7202 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | 7792 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ |
7203 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 7793 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
7204 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 7794 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
7205 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 7795 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
7206 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 7796 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
7207 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 7797 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
7208 | 7798 | ||
7209 | /* | 7799 | /* |
7210 | * Set up output mixers (0x0c - 0x0e) | 7800 | * Set up output mixers (0x0c - 0x0e) |
@@ -7285,34 +7875,26 @@ static struct hda_verb alc262_sony_unsol_verbs[] = { | |||
7285 | }; | 7875 | }; |
7286 | 7876 | ||
7287 | /* mute/unmute internal speaker according to the hp jack and mute state */ | 7877 | /* mute/unmute internal speaker according to the hp jack and mute state */ |
7288 | static void alc262_hippo_automute(struct hda_codec *codec, int force) | 7878 | static void alc262_hippo_automute(struct hda_codec *codec) |
7289 | { | 7879 | { |
7290 | struct alc_spec *spec = codec->spec; | 7880 | struct alc_spec *spec = codec->spec; |
7291 | unsigned int mute; | 7881 | unsigned int mute; |
7882 | unsigned int present; | ||
7292 | 7883 | ||
7293 | if (force || !spec->sense_updated) { | 7884 | /* need to execute and sync at first */ |
7294 | unsigned int present; | 7885 | snd_hda_codec_read(codec, 0x15, 0, AC_VERB_SET_PIN_SENSE, 0); |
7295 | /* need to execute and sync at first */ | 7886 | present = snd_hda_codec_read(codec, 0x15, 0, |
7296 | snd_hda_codec_read(codec, 0x15, 0, AC_VERB_SET_PIN_SENSE, 0); | 7887 | AC_VERB_GET_PIN_SENSE, 0); |
7297 | present = snd_hda_codec_read(codec, 0x15, 0, | 7888 | spec->jack_present = (present & 0x80000000) != 0; |
7298 | AC_VERB_GET_PIN_SENSE, 0); | ||
7299 | spec->jack_present = (present & 0x80000000) != 0; | ||
7300 | spec->sense_updated = 1; | ||
7301 | } | ||
7302 | if (spec->jack_present) { | 7889 | if (spec->jack_present) { |
7303 | /* mute internal speaker */ | 7890 | /* mute internal speaker */ |
7304 | snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, | 7891 | snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, |
7305 | 0x80, 0x80); | 7892 | HDA_AMP_MUTE, HDA_AMP_MUTE); |
7306 | snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, | ||
7307 | 0x80, 0x80); | ||
7308 | } else { | 7893 | } else { |
7309 | /* unmute internal speaker if necessary */ | 7894 | /* unmute internal speaker if necessary */ |
7310 | mute = snd_hda_codec_amp_read(codec, 0x15, 0, HDA_OUTPUT, 0); | 7895 | mute = snd_hda_codec_amp_read(codec, 0x15, 0, HDA_OUTPUT, 0); |
7311 | snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, | 7896 | snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, |
7312 | 0x80, mute & 0x80); | 7897 | HDA_AMP_MUTE, mute); |
7313 | mute = snd_hda_codec_amp_read(codec, 0x15, 1, HDA_OUTPUT, 0); | ||
7314 | snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, | ||
7315 | 0x80, mute & 0x80); | ||
7316 | } | 7898 | } |
7317 | } | 7899 | } |
7318 | 7900 | ||
@@ -7322,37 +7904,27 @@ static void alc262_hippo_unsol_event(struct hda_codec *codec, | |||
7322 | { | 7904 | { |
7323 | if ((res >> 26) != ALC880_HP_EVENT) | 7905 | if ((res >> 26) != ALC880_HP_EVENT) |
7324 | return; | 7906 | return; |
7325 | alc262_hippo_automute(codec, 1); | 7907 | alc262_hippo_automute(codec); |
7326 | } | 7908 | } |
7327 | 7909 | ||
7328 | static void alc262_hippo1_automute(struct hda_codec *codec, int force) | 7910 | static void alc262_hippo1_automute(struct hda_codec *codec) |
7329 | { | 7911 | { |
7330 | struct alc_spec *spec = codec->spec; | ||
7331 | unsigned int mute; | 7912 | unsigned int mute; |
7913 | unsigned int present; | ||
7332 | 7914 | ||
7333 | if (force || !spec->sense_updated) { | 7915 | snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_SET_PIN_SENSE, 0); |
7334 | unsigned int present; | 7916 | present = snd_hda_codec_read(codec, 0x1b, 0, |
7335 | /* need to execute and sync at first */ | 7917 | AC_VERB_GET_PIN_SENSE, 0); |
7336 | snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_SET_PIN_SENSE, 0); | 7918 | present = (present & 0x80000000) != 0; |
7337 | present = snd_hda_codec_read(codec, 0x1b, 0, | 7919 | if (present) { |
7338 | AC_VERB_GET_PIN_SENSE, 0); | ||
7339 | spec->jack_present = (present & 0x80000000) != 0; | ||
7340 | spec->sense_updated = 1; | ||
7341 | } | ||
7342 | if (spec->jack_present) { | ||
7343 | /* mute internal speaker */ | 7920 | /* mute internal speaker */ |
7344 | snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, | 7921 | snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, |
7345 | 0x80, 0x80); | 7922 | HDA_AMP_MUTE, HDA_AMP_MUTE); |
7346 | snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, | ||
7347 | 0x80, 0x80); | ||
7348 | } else { | 7923 | } else { |
7349 | /* unmute internal speaker if necessary */ | 7924 | /* unmute internal speaker if necessary */ |
7350 | mute = snd_hda_codec_amp_read(codec, 0x1b, 0, HDA_OUTPUT, 0); | 7925 | mute = snd_hda_codec_amp_read(codec, 0x1b, 0, HDA_OUTPUT, 0); |
7351 | snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, | 7926 | snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, |
7352 | 0x80, mute & 0x80); | 7927 | HDA_AMP_MUTE, mute); |
7353 | mute = snd_hda_codec_amp_read(codec, 0x1b, 1, HDA_OUTPUT, 0); | ||
7354 | snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, | ||
7355 | 0x80, mute & 0x80); | ||
7356 | } | 7928 | } |
7357 | } | 7929 | } |
7358 | 7930 | ||
@@ -7362,7 +7934,7 @@ static void alc262_hippo1_unsol_event(struct hda_codec *codec, | |||
7362 | { | 7934 | { |
7363 | if ((res >> 26) != ALC880_HP_EVENT) | 7935 | if ((res >> 26) != ALC880_HP_EVENT) |
7364 | return; | 7936 | return; |
7365 | alc262_hippo1_automute(codec, 1); | 7937 | alc262_hippo1_automute(codec); |
7366 | } | 7938 | } |
7367 | 7939 | ||
7368 | /* | 7940 | /* |
@@ -7379,9 +7951,10 @@ static struct hda_verb alc262_fujitsu_unsol_verbs[] = { | |||
7379 | }; | 7951 | }; |
7380 | 7952 | ||
7381 | static struct hda_input_mux alc262_fujitsu_capture_source = { | 7953 | static struct hda_input_mux alc262_fujitsu_capture_source = { |
7382 | .num_items = 2, | 7954 | .num_items = 3, |
7383 | .items = { | 7955 | .items = { |
7384 | { "Mic", 0x0 }, | 7956 | { "Mic", 0x0 }, |
7957 | { "Int Mic", 0x1 }, | ||
7385 | { "CD", 0x4 }, | 7958 | { "CD", 0x4 }, |
7386 | }, | 7959 | }, |
7387 | }; | 7960 | }; |
@@ -7390,13 +7963,23 @@ static struct hda_input_mux alc262_HP_capture_source = { | |||
7390 | .num_items = 5, | 7963 | .num_items = 5, |
7391 | .items = { | 7964 | .items = { |
7392 | { "Mic", 0x0 }, | 7965 | { "Mic", 0x0 }, |
7393 | { "Front Mic", 0x3 }, | 7966 | { "Front Mic", 0x1 }, |
7394 | { "Line", 0x2 }, | 7967 | { "Line", 0x2 }, |
7395 | { "CD", 0x4 }, | 7968 | { "CD", 0x4 }, |
7396 | { "AUX IN", 0x6 }, | 7969 | { "AUX IN", 0x6 }, |
7397 | }, | 7970 | }, |
7398 | }; | 7971 | }; |
7399 | 7972 | ||
7973 | static struct hda_input_mux alc262_HP_D7000_capture_source = { | ||
7974 | .num_items = 4, | ||
7975 | .items = { | ||
7976 | { "Mic", 0x0 }, | ||
7977 | { "Front Mic", 0x2 }, | ||
7978 | { "Line", 0x1 }, | ||
7979 | { "CD", 0x4 }, | ||
7980 | }, | ||
7981 | }; | ||
7982 | |||
7400 | /* mute/unmute internal speaker according to the hp jack and mute state */ | 7983 | /* mute/unmute internal speaker according to the hp jack and mute state */ |
7401 | static void alc262_fujitsu_automute(struct hda_codec *codec, int force) | 7984 | static void alc262_fujitsu_automute(struct hda_codec *codec, int force) |
7402 | { | 7985 | { |
@@ -7414,18 +7997,13 @@ static void alc262_fujitsu_automute(struct hda_codec *codec, int force) | |||
7414 | } | 7997 | } |
7415 | if (spec->jack_present) { | 7998 | if (spec->jack_present) { |
7416 | /* mute internal speaker */ | 7999 | /* mute internal speaker */ |
7417 | snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, | 8000 | snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, |
7418 | 0x80, 0x80); | 8001 | HDA_AMP_MUTE, HDA_AMP_MUTE); |
7419 | snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, | ||
7420 | 0x80, 0x80); | ||
7421 | } else { | 8002 | } else { |
7422 | /* unmute internal speaker if necessary */ | 8003 | /* unmute internal speaker if necessary */ |
7423 | mute = snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0); | 8004 | mute = snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0); |
7424 | snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, | 8005 | snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, |
7425 | 0x80, mute & 0x80); | 8006 | HDA_AMP_MUTE, mute); |
7426 | mute = snd_hda_codec_amp_read(codec, 0x14, 1, HDA_OUTPUT, 0); | ||
7427 | snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, | ||
7428 | 0x80, mute & 0x80); | ||
7429 | } | 8007 | } |
7430 | } | 8008 | } |
7431 | 8009 | ||
@@ -7439,23 +8017,14 @@ static void alc262_fujitsu_unsol_event(struct hda_codec *codec, | |||
7439 | } | 8017 | } |
7440 | 8018 | ||
7441 | /* bind volumes of both NID 0x0c and 0x0d */ | 8019 | /* bind volumes of both NID 0x0c and 0x0d */ |
7442 | static int alc262_fujitsu_master_vol_put(struct snd_kcontrol *kcontrol, | 8020 | static struct hda_bind_ctls alc262_fujitsu_bind_master_vol = { |
7443 | struct snd_ctl_elem_value *ucontrol) | 8021 | .ops = &snd_hda_bind_vol, |
7444 | { | 8022 | .values = { |
7445 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 8023 | HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT), |
7446 | long *valp = ucontrol->value.integer.value; | 8024 | HDA_COMPOSE_AMP_VAL(0x0d, 3, 0, HDA_OUTPUT), |
7447 | int change; | 8025 | 0 |
7448 | 8026 | }, | |
7449 | change = snd_hda_codec_amp_update(codec, 0x0c, 0, HDA_OUTPUT, 0, | 8027 | }; |
7450 | 0x7f, valp[0] & 0x7f); | ||
7451 | change |= snd_hda_codec_amp_update(codec, 0x0c, 1, HDA_OUTPUT, 0, | ||
7452 | 0x7f, valp[1] & 0x7f); | ||
7453 | snd_hda_codec_amp_update(codec, 0x0d, 0, HDA_OUTPUT, 0, | ||
7454 | 0x7f, valp[0] & 0x7f); | ||
7455 | snd_hda_codec_amp_update(codec, 0x0d, 1, HDA_OUTPUT, 0, | ||
7456 | 0x7f, valp[1] & 0x7f); | ||
7457 | return change; | ||
7458 | } | ||
7459 | 8028 | ||
7460 | /* bind hp and internal speaker mute (with plug check) */ | 8029 | /* bind hp and internal speaker mute (with plug check) */ |
7461 | static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol, | 8030 | static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol, |
@@ -7466,24 +8035,18 @@ static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol, | |||
7466 | int change; | 8035 | int change; |
7467 | 8036 | ||
7468 | change = snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, | 8037 | change = snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, |
7469 | 0x80, valp[0] ? 0 : 0x80); | 8038 | HDA_AMP_MUTE, |
8039 | valp[0] ? 0 : HDA_AMP_MUTE); | ||
7470 | change |= snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, | 8040 | change |= snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, |
7471 | 0x80, valp[1] ? 0 : 0x80); | 8041 | HDA_AMP_MUTE, |
7472 | if (change || codec->in_resume) | 8042 | valp[1] ? 0 : HDA_AMP_MUTE); |
7473 | alc262_fujitsu_automute(codec, codec->in_resume); | 8043 | if (change) |
8044 | alc262_fujitsu_automute(codec, 0); | ||
7474 | return change; | 8045 | return change; |
7475 | } | 8046 | } |
7476 | 8047 | ||
7477 | static struct snd_kcontrol_new alc262_fujitsu_mixer[] = { | 8048 | static struct snd_kcontrol_new alc262_fujitsu_mixer[] = { |
7478 | { | 8049 | HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol), |
7479 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
7480 | .name = "Master Playback Volume", | ||
7481 | .info = snd_hda_mixer_amp_volume_info, | ||
7482 | .get = snd_hda_mixer_amp_volume_get, | ||
7483 | .put = alc262_fujitsu_master_vol_put, | ||
7484 | .tlv = { .c = snd_hda_mixer_amp_tlv }, | ||
7485 | .private_value = HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT), | ||
7486 | }, | ||
7487 | { | 8050 | { |
7488 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 8051 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
7489 | .name = "Master Playback Switch", | 8052 | .name = "Master Playback Switch", |
@@ -7497,6 +8060,9 @@ static struct snd_kcontrol_new alc262_fujitsu_mixer[] = { | |||
7497 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 8060 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), |
7498 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 8061 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
7499 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 8062 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
8063 | HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT), | ||
8064 | HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | ||
8065 | HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | ||
7500 | { } /* end */ | 8066 | { } /* end */ |
7501 | }; | 8067 | }; |
7502 | 8068 | ||
@@ -7611,17 +8177,17 @@ static struct hda_verb alc262_volume_init_verbs[] = { | |||
7611 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | 8177 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, |
7612 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 8178 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
7613 | 8179 | ||
7614 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | 8180 | /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback |
7615 | * mixer widget | 8181 | * mixer widget |
7616 | * Note: PASD motherboards uses the Line In 2 as the input for | 8182 | * Note: PASD motherboards uses the Line In 2 as the input for |
7617 | * front panel mic (mic 2) | 8183 | * front panel mic (mic 2) |
7618 | */ | 8184 | */ |
7619 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | 8185 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ |
7620 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 8186 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
7621 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 8187 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
7622 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 8188 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
7623 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 8189 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
7624 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 8190 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
7625 | 8191 | ||
7626 | /* | 8192 | /* |
7627 | * Set up output mixers (0x0c - 0x0f) | 8193 | * Set up output mixers (0x0c - 0x0f) |
@@ -7672,19 +8238,19 @@ static struct hda_verb alc262_HP_BPC_init_verbs[] = { | |||
7672 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | 8238 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, |
7673 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 8239 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
7674 | 8240 | ||
7675 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | 8241 | /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback |
7676 | * mixer widget | 8242 | * mixer widget |
7677 | * Note: PASD motherboards uses the Line In 2 as the input for | 8243 | * Note: PASD motherboards uses the Line In 2 as the input for |
7678 | * front panel mic (mic 2) | 8244 | * front panel mic (mic 2) |
7679 | */ | 8245 | */ |
7680 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | 8246 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ |
7681 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 8247 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
7682 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 8248 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
7683 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 8249 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
7684 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 8250 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
7685 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 8251 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
7686 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)}, | 8252 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, |
7687 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(6)}, | 8253 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, |
7688 | 8254 | ||
7689 | /* | 8255 | /* |
7690 | * Set up output mixers (0x0c - 0x0e) | 8256 | * Set up output mixers (0x0c - 0x0e) |
@@ -7759,20 +8325,20 @@ static struct hda_verb alc262_HP_BPC_WildWest_init_verbs[] = { | |||
7759 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | 8325 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, |
7760 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 8326 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
7761 | 8327 | ||
7762 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | 8328 | /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback |
7763 | * mixer widget | 8329 | * mixer widget |
7764 | * Note: PASD motherboards uses the Line In 2 as the input for front | 8330 | * Note: PASD motherboards uses the Line In 2 as the input for front |
7765 | * panel mic (mic 2) | 8331 | * panel mic (mic 2) |
7766 | */ | 8332 | */ |
7767 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | 8333 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ |
7768 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 8334 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
7769 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 8335 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
7770 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 8336 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
7771 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 8337 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
7772 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 8338 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
7773 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)}, | 8339 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, |
7774 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(6)}, | 8340 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, |
7775 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(7)}, | 8341 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, |
7776 | /* | 8342 | /* |
7777 | * Set up output mixers (0x0c - 0x0e) | 8343 | * Set up output mixers (0x0c - 0x0e) |
7778 | */ | 8344 | */ |
@@ -7842,6 +8408,10 @@ static struct hda_verb alc262_HP_BPC_WildWest_init_verbs[] = { | |||
7842 | { } | 8408 | { } |
7843 | }; | 8409 | }; |
7844 | 8410 | ||
8411 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
8412 | #define alc262_loopbacks alc880_loopbacks | ||
8413 | #endif | ||
8414 | |||
7845 | /* pcm configuration: identiacal with ALC880 */ | 8415 | /* pcm configuration: identiacal with ALC880 */ |
7846 | #define alc262_pcm_analog_playback alc880_pcm_analog_playback | 8416 | #define alc262_pcm_analog_playback alc880_pcm_analog_playback |
7847 | #define alc262_pcm_analog_capture alc880_pcm_analog_capture | 8417 | #define alc262_pcm_analog_capture alc880_pcm_analog_capture |
@@ -7884,6 +8454,10 @@ static int alc262_parse_auto_config(struct hda_codec *codec) | |||
7884 | spec->num_mux_defs = 1; | 8454 | spec->num_mux_defs = 1; |
7885 | spec->input_mux = &spec->private_imux; | 8455 | spec->input_mux = &spec->private_imux; |
7886 | 8456 | ||
8457 | err = alc_auto_add_mic_boost(codec); | ||
8458 | if (err < 0) | ||
8459 | return err; | ||
8460 | |||
7887 | return 1; | 8461 | return 1; |
7888 | } | 8462 | } |
7889 | 8463 | ||
@@ -7939,6 +8513,7 @@ static struct snd_pci_quirk alc262_cfg_tbl[] = { | |||
7939 | SND_PCI_QUIRK(0x17ff, 0x058f, "Benq Hippo", ALC262_HIPPO_1), | 8513 | SND_PCI_QUIRK(0x17ff, 0x058f, "Benq Hippo", ALC262_HIPPO_1), |
7940 | SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8), | 8514 | SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8), |
7941 | SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_BENQ_T31), | 8515 | SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_BENQ_T31), |
8516 | SND_PCI_QUIRK(0x104d, 0x820f, "Sony ASSAMD", ALC262_SONY_ASSAMD), | ||
7942 | SND_PCI_QUIRK(0x104d, 0x9015, "Sony 0x9015", ALC262_SONY_ASSAMD), | 8517 | SND_PCI_QUIRK(0x104d, 0x9015, "Sony 0x9015", ALC262_SONY_ASSAMD), |
7943 | SND_PCI_QUIRK(0x104d, 0x900e, "Sony ASSAMD", ALC262_SONY_ASSAMD), | 8518 | SND_PCI_QUIRK(0x104d, 0x900e, "Sony ASSAMD", ALC262_SONY_ASSAMD), |
7944 | SND_PCI_QUIRK(0x104d, 0x1f00, "Sony ASSAMD", ALC262_SONY_ASSAMD), | 8519 | SND_PCI_QUIRK(0x104d, 0x1f00, "Sony ASSAMD", ALC262_SONY_ASSAMD), |
@@ -7967,6 +8542,7 @@ static struct alc_config_preset alc262_presets[] = { | |||
7967 | .channel_mode = alc262_modes, | 8542 | .channel_mode = alc262_modes, |
7968 | .input_mux = &alc262_capture_source, | 8543 | .input_mux = &alc262_capture_source, |
7969 | .unsol_event = alc262_hippo_unsol_event, | 8544 | .unsol_event = alc262_hippo_unsol_event, |
8545 | .init_hook = alc262_hippo_automute, | ||
7970 | }, | 8546 | }, |
7971 | [ALC262_HIPPO_1] = { | 8547 | [ALC262_HIPPO_1] = { |
7972 | .mixers = { alc262_hippo1_mixer }, | 8548 | .mixers = { alc262_hippo1_mixer }, |
@@ -7979,10 +8555,12 @@ static struct alc_config_preset alc262_presets[] = { | |||
7979 | .channel_mode = alc262_modes, | 8555 | .channel_mode = alc262_modes, |
7980 | .input_mux = &alc262_capture_source, | 8556 | .input_mux = &alc262_capture_source, |
7981 | .unsol_event = alc262_hippo1_unsol_event, | 8557 | .unsol_event = alc262_hippo1_unsol_event, |
8558 | .init_hook = alc262_hippo1_automute, | ||
7982 | }, | 8559 | }, |
7983 | [ALC262_FUJITSU] = { | 8560 | [ALC262_FUJITSU] = { |
7984 | .mixers = { alc262_fujitsu_mixer }, | 8561 | .mixers = { alc262_fujitsu_mixer }, |
7985 | .init_verbs = { alc262_init_verbs, alc262_fujitsu_unsol_verbs }, | 8562 | .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs, |
8563 | alc262_fujitsu_unsol_verbs }, | ||
7986 | .num_dacs = ARRAY_SIZE(alc262_dac_nids), | 8564 | .num_dacs = ARRAY_SIZE(alc262_dac_nids), |
7987 | .dac_nids = alc262_dac_nids, | 8565 | .dac_nids = alc262_dac_nids, |
7988 | .hp_nid = 0x03, | 8566 | .hp_nid = 0x03, |
@@ -8010,7 +8588,7 @@ static struct alc_config_preset alc262_presets[] = { | |||
8010 | .hp_nid = 0x03, | 8588 | .hp_nid = 0x03, |
8011 | .num_channel_mode = ARRAY_SIZE(alc262_modes), | 8589 | .num_channel_mode = ARRAY_SIZE(alc262_modes), |
8012 | .channel_mode = alc262_modes, | 8590 | .channel_mode = alc262_modes, |
8013 | .input_mux = &alc262_HP_capture_source, | 8591 | .input_mux = &alc262_HP_D7000_capture_source, |
8014 | }, | 8592 | }, |
8015 | [ALC262_HP_BPC_D7000_WL] = { | 8593 | [ALC262_HP_BPC_D7000_WL] = { |
8016 | .mixers = { alc262_HP_BPC_WildWest_mixer, | 8594 | .mixers = { alc262_HP_BPC_WildWest_mixer, |
@@ -8021,7 +8599,7 @@ static struct alc_config_preset alc262_presets[] = { | |||
8021 | .hp_nid = 0x03, | 8599 | .hp_nid = 0x03, |
8022 | .num_channel_mode = ARRAY_SIZE(alc262_modes), | 8600 | .num_channel_mode = ARRAY_SIZE(alc262_modes), |
8023 | .channel_mode = alc262_modes, | 8601 | .channel_mode = alc262_modes, |
8024 | .input_mux = &alc262_HP_capture_source, | 8602 | .input_mux = &alc262_HP_D7000_capture_source, |
8025 | }, | 8603 | }, |
8026 | [ALC262_BENQ_ED8] = { | 8604 | [ALC262_BENQ_ED8] = { |
8027 | .mixers = { alc262_base_mixer }, | 8605 | .mixers = { alc262_base_mixer }, |
@@ -8043,6 +8621,7 @@ static struct alc_config_preset alc262_presets[] = { | |||
8043 | .channel_mode = alc262_modes, | 8621 | .channel_mode = alc262_modes, |
8044 | .input_mux = &alc262_capture_source, | 8622 | .input_mux = &alc262_capture_source, |
8045 | .unsol_event = alc262_hippo_unsol_event, | 8623 | .unsol_event = alc262_hippo_unsol_event, |
8624 | .init_hook = alc262_hippo_automute, | ||
8046 | }, | 8625 | }, |
8047 | [ALC262_BENQ_T31] = { | 8626 | [ALC262_BENQ_T31] = { |
8048 | .mixers = { alc262_benq_t31_mixer }, | 8627 | .mixers = { alc262_benq_t31_mixer }, |
@@ -8054,6 +8633,7 @@ static struct alc_config_preset alc262_presets[] = { | |||
8054 | .channel_mode = alc262_modes, | 8633 | .channel_mode = alc262_modes, |
8055 | .input_mux = &alc262_capture_source, | 8634 | .input_mux = &alc262_capture_source, |
8056 | .unsol_event = alc262_hippo_unsol_event, | 8635 | .unsol_event = alc262_hippo_unsol_event, |
8636 | .init_hook = alc262_hippo_automute, | ||
8057 | }, | 8637 | }, |
8058 | }; | 8638 | }; |
8059 | 8639 | ||
@@ -8139,6 +8719,10 @@ static int patch_alc262(struct hda_codec *codec) | |||
8139 | codec->patch_ops = alc_patch_ops; | 8719 | codec->patch_ops = alc_patch_ops; |
8140 | if (board_config == ALC262_AUTO) | 8720 | if (board_config == ALC262_AUTO) |
8141 | spec->init_hook = alc262_auto_init; | 8721 | spec->init_hook = alc262_auto_init; |
8722 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
8723 | if (!spec->loopback.amplist) | ||
8724 | spec->loopback.amplist = alc262_loopbacks; | ||
8725 | #endif | ||
8142 | 8726 | ||
8143 | return 0; | 8727 | return 0; |
8144 | } | 8728 | } |
@@ -8170,9 +8754,125 @@ static struct snd_kcontrol_new alc268_base_mixer[] = { | |||
8170 | HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), | 8754 | HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), |
8171 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT), | 8755 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT), |
8172 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), | 8756 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), |
8757 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | ||
8758 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | ||
8759 | HDA_CODEC_VOLUME("Line In Boost", 0x1a, 0, HDA_INPUT), | ||
8760 | { } | ||
8761 | }; | ||
8762 | |||
8763 | static struct hda_verb alc268_eapd_verbs[] = { | ||
8764 | {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2}, | ||
8765 | {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2}, | ||
8766 | { } | ||
8767 | }; | ||
8768 | |||
8769 | /* Toshiba specific */ | ||
8770 | #define alc268_toshiba_automute alc262_hippo_automute | ||
8771 | |||
8772 | static struct hda_verb alc268_toshiba_verbs[] = { | ||
8773 | {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, | ||
8774 | { } /* end */ | ||
8775 | }; | ||
8776 | |||
8777 | /* Acer specific */ | ||
8778 | /* bind volumes of both NID 0x02 and 0x03 */ | ||
8779 | static struct hda_bind_ctls alc268_acer_bind_master_vol = { | ||
8780 | .ops = &snd_hda_bind_vol, | ||
8781 | .values = { | ||
8782 | HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT), | ||
8783 | HDA_COMPOSE_AMP_VAL(0x03, 3, 0, HDA_OUTPUT), | ||
8784 | 0 | ||
8785 | }, | ||
8786 | }; | ||
8787 | |||
8788 | /* mute/unmute internal speaker according to the hp jack and mute state */ | ||
8789 | static void alc268_acer_automute(struct hda_codec *codec, int force) | ||
8790 | { | ||
8791 | struct alc_spec *spec = codec->spec; | ||
8792 | unsigned int mute; | ||
8793 | |||
8794 | if (force || !spec->sense_updated) { | ||
8795 | unsigned int present; | ||
8796 | present = snd_hda_codec_read(codec, 0x14, 0, | ||
8797 | AC_VERB_GET_PIN_SENSE, 0); | ||
8798 | spec->jack_present = (present & 0x80000000) != 0; | ||
8799 | spec->sense_updated = 1; | ||
8800 | } | ||
8801 | if (spec->jack_present) | ||
8802 | mute = HDA_AMP_MUTE; /* mute internal speaker */ | ||
8803 | else /* unmute internal speaker if necessary */ | ||
8804 | mute = snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0); | ||
8805 | snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, | ||
8806 | HDA_AMP_MUTE, mute); | ||
8807 | } | ||
8808 | |||
8809 | |||
8810 | /* bind hp and internal speaker mute (with plug check) */ | ||
8811 | static int alc268_acer_master_sw_put(struct snd_kcontrol *kcontrol, | ||
8812 | struct snd_ctl_elem_value *ucontrol) | ||
8813 | { | ||
8814 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
8815 | long *valp = ucontrol->value.integer.value; | ||
8816 | int change; | ||
8817 | |||
8818 | change = snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, | ||
8819 | HDA_AMP_MUTE, | ||
8820 | valp[0] ? 0 : HDA_AMP_MUTE); | ||
8821 | change |= snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, | ||
8822 | HDA_AMP_MUTE, | ||
8823 | valp[1] ? 0 : HDA_AMP_MUTE); | ||
8824 | if (change) | ||
8825 | alc268_acer_automute(codec, 0); | ||
8826 | return change; | ||
8827 | } | ||
8828 | |||
8829 | static struct snd_kcontrol_new alc268_acer_mixer[] = { | ||
8830 | /* output mixer control */ | ||
8831 | HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol), | ||
8832 | { | ||
8833 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
8834 | .name = "Master Playback Switch", | ||
8835 | .info = snd_hda_mixer_amp_switch_info, | ||
8836 | .get = snd_hda_mixer_amp_switch_get, | ||
8837 | .put = alc268_acer_master_sw_put, | ||
8838 | .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT), | ||
8839 | }, | ||
8840 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | ||
8841 | HDA_CODEC_VOLUME("Internal Mic Boost", 0x19, 0, HDA_INPUT), | ||
8842 | HDA_CODEC_VOLUME("Line In Boost", 0x1a, 0, HDA_INPUT), | ||
8173 | { } | 8843 | { } |
8174 | }; | 8844 | }; |
8175 | 8845 | ||
8846 | static struct hda_verb alc268_acer_verbs[] = { | ||
8847 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
8848 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
8849 | |||
8850 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, | ||
8851 | { } | ||
8852 | }; | ||
8853 | |||
8854 | /* unsolicited event for HP jack sensing */ | ||
8855 | static void alc268_toshiba_unsol_event(struct hda_codec *codec, | ||
8856 | unsigned int res) | ||
8857 | { | ||
8858 | if ((res >> 26) != ALC880_HP_EVENT) | ||
8859 | return; | ||
8860 | alc268_toshiba_automute(codec); | ||
8861 | } | ||
8862 | |||
8863 | static void alc268_acer_unsol_event(struct hda_codec *codec, | ||
8864 | unsigned int res) | ||
8865 | { | ||
8866 | if ((res >> 26) != ALC880_HP_EVENT) | ||
8867 | return; | ||
8868 | alc268_acer_automute(codec, 1); | ||
8869 | } | ||
8870 | |||
8871 | static void alc268_acer_init_hook(struct hda_codec *codec) | ||
8872 | { | ||
8873 | alc268_acer_automute(codec, 1); | ||
8874 | } | ||
8875 | |||
8176 | /* | 8876 | /* |
8177 | * generic initialization of ADC, input mixers and output mixers | 8877 | * generic initialization of ADC, input mixers and output mixers |
8178 | */ | 8878 | */ |
@@ -8282,14 +8982,16 @@ static int alc268_mux_enum_put(struct snd_kcontrol *kcontrol, | |||
8282 | idx = ucontrol->value.enumerated.item[0]; | 8982 | idx = ucontrol->value.enumerated.item[0]; |
8283 | if (idx >= imux->num_items) | 8983 | if (idx >= imux->num_items) |
8284 | idx = imux->num_items - 1; | 8984 | idx = imux->num_items - 1; |
8285 | if (*cur_val == idx && !codec->in_resume) | 8985 | if (*cur_val == idx) |
8286 | return 0; | 8986 | return 0; |
8287 | for (i = 0; i < imux->num_items; i++) { | 8987 | for (i = 0; i < imux->num_items; i++) { |
8288 | unsigned int v = (i == idx) ? 0x7000 : 0x7080; | 8988 | unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE; |
8289 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, | 8989 | snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, |
8290 | v | (imux->items[i].index << 8)); | 8990 | imux->items[i].index, |
8291 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, | 8991 | HDA_AMP_MUTE, v); |
8292 | idx ); | 8992 | snd_hda_codec_write_cache(codec, nid, 0, |
8993 | AC_VERB_SET_CONNECT_SEL, | ||
8994 | idx ); | ||
8293 | } | 8995 | } |
8294 | *cur_val = idx; | 8996 | *cur_val = idx; |
8295 | return 1; | 8997 | return 1; |
@@ -8530,6 +9232,10 @@ static int alc268_parse_auto_config(struct hda_codec *codec) | |||
8530 | spec->num_mux_defs = 1; | 9232 | spec->num_mux_defs = 1; |
8531 | spec->input_mux = &spec->private_imux; | 9233 | spec->input_mux = &spec->private_imux; |
8532 | 9234 | ||
9235 | err = alc_auto_add_mic_boost(codec); | ||
9236 | if (err < 0) | ||
9237 | return err; | ||
9238 | |||
8533 | return 1; | 9239 | return 1; |
8534 | } | 9240 | } |
8535 | 9241 | ||
@@ -8551,11 +9257,19 @@ static void alc268_auto_init(struct hda_codec *codec) | |||
8551 | */ | 9257 | */ |
8552 | static const char *alc268_models[ALC268_MODEL_LAST] = { | 9258 | static const char *alc268_models[ALC268_MODEL_LAST] = { |
8553 | [ALC268_3ST] = "3stack", | 9259 | [ALC268_3ST] = "3stack", |
9260 | [ALC268_TOSHIBA] = "toshiba", | ||
9261 | [ALC268_ACER] = "acer", | ||
8554 | [ALC268_AUTO] = "auto", | 9262 | [ALC268_AUTO] = "auto", |
8555 | }; | 9263 | }; |
8556 | 9264 | ||
8557 | static struct snd_pci_quirk alc268_cfg_tbl[] = { | 9265 | static struct snd_pci_quirk alc268_cfg_tbl[] = { |
8558 | SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC268_3ST), | 9266 | SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC268_3ST), |
9267 | SND_PCI_QUIRK(0x1179, 0xff10, "TOSHIBA A205", ALC268_TOSHIBA), | ||
9268 | SND_PCI_QUIRK(0x1179, 0xff50, "TOSHIBA A305", ALC268_TOSHIBA), | ||
9269 | SND_PCI_QUIRK(0x103c, 0x30cc, "TOSHIBA", ALC268_TOSHIBA), | ||
9270 | SND_PCI_QUIRK(0x1025, 0x0126, "Acer", ALC268_ACER), | ||
9271 | SND_PCI_QUIRK(0x1025, 0x0130, "Acer Extensa 5210", ALC268_ACER), | ||
9272 | SND_PCI_QUIRK(0x152d, 0x0763, "Diverse (CPR2000)", ALC268_ACER), | ||
8559 | {} | 9273 | {} |
8560 | }; | 9274 | }; |
8561 | 9275 | ||
@@ -8573,6 +9287,37 @@ static struct alc_config_preset alc268_presets[] = { | |||
8573 | .channel_mode = alc268_modes, | 9287 | .channel_mode = alc268_modes, |
8574 | .input_mux = &alc268_capture_source, | 9288 | .input_mux = &alc268_capture_source, |
8575 | }, | 9289 | }, |
9290 | [ALC268_TOSHIBA] = { | ||
9291 | .mixers = { alc268_base_mixer, alc268_capture_alt_mixer }, | ||
9292 | .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, | ||
9293 | alc268_toshiba_verbs }, | ||
9294 | .num_dacs = ARRAY_SIZE(alc268_dac_nids), | ||
9295 | .dac_nids = alc268_dac_nids, | ||
9296 | .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt), | ||
9297 | .adc_nids = alc268_adc_nids_alt, | ||
9298 | .hp_nid = 0x03, | ||
9299 | .num_channel_mode = ARRAY_SIZE(alc268_modes), | ||
9300 | .channel_mode = alc268_modes, | ||
9301 | .input_mux = &alc268_capture_source, | ||
9302 | .input_mux = &alc268_capture_source, | ||
9303 | .unsol_event = alc268_toshiba_unsol_event, | ||
9304 | .init_hook = alc268_toshiba_automute, | ||
9305 | }, | ||
9306 | [ALC268_ACER] = { | ||
9307 | .mixers = { alc268_acer_mixer, alc268_capture_alt_mixer }, | ||
9308 | .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, | ||
9309 | alc268_acer_verbs }, | ||
9310 | .num_dacs = ARRAY_SIZE(alc268_dac_nids), | ||
9311 | .dac_nids = alc268_dac_nids, | ||
9312 | .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt), | ||
9313 | .adc_nids = alc268_adc_nids_alt, | ||
9314 | .hp_nid = 0x02, | ||
9315 | .num_channel_mode = ARRAY_SIZE(alc268_modes), | ||
9316 | .channel_mode = alc268_modes, | ||
9317 | .input_mux = &alc268_capture_source, | ||
9318 | .unsol_event = alc268_acer_unsol_event, | ||
9319 | .init_hook = alc268_acer_init_hook, | ||
9320 | }, | ||
8576 | }; | 9321 | }; |
8577 | 9322 | ||
8578 | static int patch_alc268(struct hda_codec *codec) | 9323 | static int patch_alc268(struct hda_codec *codec) |
@@ -9279,14 +10024,10 @@ static void alc861_toshiba_automute(struct hda_codec *codec) | |||
9279 | 10024 | ||
9280 | present = snd_hda_codec_read(codec, 0x0f, 0, | 10025 | present = snd_hda_codec_read(codec, 0x0f, 0, |
9281 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 10026 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
9282 | snd_hda_codec_amp_update(codec, 0x16, 0, HDA_INPUT, 0, | 10027 | snd_hda_codec_amp_stereo(codec, 0x16, HDA_INPUT, 0, |
9283 | 0x80, present ? 0x80 : 0); | 10028 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); |
9284 | snd_hda_codec_amp_update(codec, 0x16, 1, HDA_INPUT, 0, | 10029 | snd_hda_codec_amp_stereo(codec, 0x1a, HDA_INPUT, 3, |
9285 | 0x80, present ? 0x80 : 0); | 10030 | HDA_AMP_MUTE, present ? 0 : HDA_AMP_MUTE); |
9286 | snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_INPUT, 3, | ||
9287 | 0x80, present ? 0 : 0x80); | ||
9288 | snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_INPUT, 3, | ||
9289 | 0x80, present ? 0 : 0x80); | ||
9290 | } | 10031 | } |
9291 | 10032 | ||
9292 | static void alc861_toshiba_unsol_event(struct hda_codec *codec, | 10033 | static void alc861_toshiba_unsol_event(struct hda_codec *codec, |
@@ -9599,6 +10340,16 @@ static void alc861_auto_init(struct hda_codec *codec) | |||
9599 | alc861_auto_init_analog_input(codec); | 10340 | alc861_auto_init_analog_input(codec); |
9600 | } | 10341 | } |
9601 | 10342 | ||
10343 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
10344 | static struct hda_amp_list alc861_loopbacks[] = { | ||
10345 | { 0x15, HDA_INPUT, 0 }, | ||
10346 | { 0x15, HDA_INPUT, 1 }, | ||
10347 | { 0x15, HDA_INPUT, 2 }, | ||
10348 | { 0x15, HDA_INPUT, 3 }, | ||
10349 | { } /* end */ | ||
10350 | }; | ||
10351 | #endif | ||
10352 | |||
9602 | 10353 | ||
9603 | /* | 10354 | /* |
9604 | * configuration and preset | 10355 | * configuration and preset |
@@ -9796,6 +10547,10 @@ static int patch_alc861(struct hda_codec *codec) | |||
9796 | codec->patch_ops = alc_patch_ops; | 10547 | codec->patch_ops = alc_patch_ops; |
9797 | if (board_config == ALC861_AUTO) | 10548 | if (board_config == ALC861_AUTO) |
9798 | spec->init_hook = alc861_auto_init; | 10549 | spec->init_hook = alc861_auto_init; |
10550 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
10551 | if (!spec->loopback.amplist) | ||
10552 | spec->loopback.amplist = alc861_loopbacks; | ||
10553 | #endif | ||
9799 | 10554 | ||
9800 | return 0; | 10555 | return 0; |
9801 | } | 10556 | } |
@@ -9852,6 +10607,14 @@ static struct hda_input_mux alc861vd_dallas_capture_source = { | |||
9852 | }, | 10607 | }, |
9853 | }; | 10608 | }; |
9854 | 10609 | ||
10610 | static struct hda_input_mux alc861vd_hp_capture_source = { | ||
10611 | .num_items = 2, | ||
10612 | .items = { | ||
10613 | { "Front Mic", 0x0 }, | ||
10614 | { "ATAPI Mic", 0x1 }, | ||
10615 | }, | ||
10616 | }; | ||
10617 | |||
9855 | #define alc861vd_mux_enum_info alc_mux_enum_info | 10618 | #define alc861vd_mux_enum_info alc_mux_enum_info |
9856 | #define alc861vd_mux_enum_get alc_mux_enum_get | 10619 | #define alc861vd_mux_enum_get alc_mux_enum_get |
9857 | 10620 | ||
@@ -9870,12 +10633,13 @@ static int alc861vd_mux_enum_put(struct snd_kcontrol *kcontrol, | |||
9870 | idx = ucontrol->value.enumerated.item[0]; | 10633 | idx = ucontrol->value.enumerated.item[0]; |
9871 | if (idx >= imux->num_items) | 10634 | if (idx >= imux->num_items) |
9872 | idx = imux->num_items - 1; | 10635 | idx = imux->num_items - 1; |
9873 | if (*cur_val == idx && !codec->in_resume) | 10636 | if (*cur_val == idx) |
9874 | return 0; | 10637 | return 0; |
9875 | for (i = 0; i < imux->num_items; i++) { | 10638 | for (i = 0; i < imux->num_items; i++) { |
9876 | unsigned int v = (i == idx) ? 0x7000 : 0x7080; | 10639 | unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE; |
9877 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, | 10640 | snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, |
9878 | v | (imux->items[i].index << 8)); | 10641 | imux->items[i].index, |
10642 | HDA_AMP_MUTE, v); | ||
9879 | } | 10643 | } |
9880 | *cur_val = idx; | 10644 | *cur_val = idx; |
9881 | return 1; | 10645 | return 1; |
@@ -10049,17 +10813,22 @@ static struct snd_kcontrol_new alc861vd_dallas_mixer[] = { | |||
10049 | HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 10813 | HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
10050 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x05, HDA_INPUT), | 10814 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x05, HDA_INPUT), |
10051 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x05, HDA_INPUT), | 10815 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x05, HDA_INPUT), |
10052 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), | 10816 | { } /* end */ |
10053 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), | 10817 | }; |
10054 | { | 10818 | |
10055 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 10819 | /* Pin assignment: Speaker=0x14, Line-out = 0x15, |
10056 | /* .name = "Capture Source", */ | 10820 | * Front Mic=0x18, ATAPI Mic = 0x19, |
10057 | .name = "Input Source", | 10821 | */ |
10058 | .count = 1, | 10822 | static struct snd_kcontrol_new alc861vd_hp_mixer[] = { |
10059 | .info = alc882_mux_enum_info, | 10823 | HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT), |
10060 | .get = alc882_mux_enum_get, | 10824 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), |
10061 | .put = alc882_mux_enum_put, | 10825 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT), |
10062 | }, | 10826 | HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT), |
10827 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
10828 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
10829 | HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | ||
10830 | HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | ||
10831 | |||
10063 | { } /* end */ | 10832 | { } /* end */ |
10064 | }; | 10833 | }; |
10065 | 10834 | ||
@@ -10077,11 +10846,11 @@ static struct hda_verb alc861vd_volume_init_verbs[] = { | |||
10077 | * the analog-loopback mixer widget | 10846 | * the analog-loopback mixer widget |
10078 | */ | 10847 | */ |
10079 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | 10848 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ |
10080 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 10849 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
10081 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 10850 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
10082 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 10851 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
10083 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 10852 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
10084 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 10853 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
10085 | 10854 | ||
10086 | /* Capture mixer: unmute Mic, F-Mic, Line, CD inputs */ | 10855 | /* Capture mixer: unmute Mic, F-Mic, Line, CD inputs */ |
10087 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 10856 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
@@ -10210,11 +10979,9 @@ static void alc861vd_lenovo_hp_automute(struct hda_codec *codec) | |||
10210 | 10979 | ||
10211 | present = snd_hda_codec_read(codec, 0x1b, 0, | 10980 | present = snd_hda_codec_read(codec, 0x1b, 0, |
10212 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 10981 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
10213 | bits = present ? 0x80 : 0; | 10982 | bits = present ? HDA_AMP_MUTE : 0; |
10214 | snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, | 10983 | snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, |
10215 | 0x80, bits); | 10984 | HDA_AMP_MUTE, bits); |
10216 | snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, | ||
10217 | 0x80, bits); | ||
10218 | } | 10985 | } |
10219 | 10986 | ||
10220 | static void alc861vd_lenovo_mic_automute(struct hda_codec *codec) | 10987 | static void alc861vd_lenovo_mic_automute(struct hda_codec *codec) |
@@ -10224,11 +10991,9 @@ static void alc861vd_lenovo_mic_automute(struct hda_codec *codec) | |||
10224 | 10991 | ||
10225 | present = snd_hda_codec_read(codec, 0x18, 0, | 10992 | present = snd_hda_codec_read(codec, 0x18, 0, |
10226 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 10993 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
10227 | bits = present ? 0x80 : 0; | 10994 | bits = present ? HDA_AMP_MUTE : 0; |
10228 | snd_hda_codec_amp_update(codec, 0x0b, 0, HDA_INPUT, 1, | 10995 | snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, |
10229 | 0x80, bits); | 10996 | HDA_AMP_MUTE, bits); |
10230 | snd_hda_codec_amp_update(codec, 0x0b, 1, HDA_INPUT, 1, | ||
10231 | 0x80, bits); | ||
10232 | } | 10997 | } |
10233 | 10998 | ||
10234 | static void alc861vd_lenovo_automute(struct hda_codec *codec) | 10999 | static void alc861vd_lenovo_automute(struct hda_codec *codec) |
@@ -10302,10 +11067,8 @@ static void alc861vd_dallas_automute(struct hda_codec *codec) | |||
10302 | 11067 | ||
10303 | present = snd_hda_codec_read(codec, 0x15, 0, | 11068 | present = snd_hda_codec_read(codec, 0x15, 0, |
10304 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 11069 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
10305 | snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, | 11070 | snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, |
10306 | 0x80, present ? 0x80 : 0); | 11071 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); |
10307 | snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, | ||
10308 | 0x80, present ? 0x80 : 0); | ||
10309 | } | 11072 | } |
10310 | 11073 | ||
10311 | static void alc861vd_dallas_unsol_event(struct hda_codec *codec, unsigned int res) | 11074 | static void alc861vd_dallas_unsol_event(struct hda_codec *codec, unsigned int res) |
@@ -10314,6 +11077,10 @@ static void alc861vd_dallas_unsol_event(struct hda_codec *codec, unsigned int re | |||
10314 | alc861vd_dallas_automute(codec); | 11077 | alc861vd_dallas_automute(codec); |
10315 | } | 11078 | } |
10316 | 11079 | ||
11080 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
11081 | #define alc861vd_loopbacks alc880_loopbacks | ||
11082 | #endif | ||
11083 | |||
10317 | /* pcm configuration: identiacal with ALC880 */ | 11084 | /* pcm configuration: identiacal with ALC880 */ |
10318 | #define alc861vd_pcm_analog_playback alc880_pcm_analog_playback | 11085 | #define alc861vd_pcm_analog_playback alc880_pcm_analog_playback |
10319 | #define alc861vd_pcm_analog_capture alc880_pcm_analog_capture | 11086 | #define alc861vd_pcm_analog_capture alc880_pcm_analog_capture |
@@ -10325,12 +11092,13 @@ static void alc861vd_dallas_unsol_event(struct hda_codec *codec, unsigned int re | |||
10325 | */ | 11092 | */ |
10326 | static const char *alc861vd_models[ALC861VD_MODEL_LAST] = { | 11093 | static const char *alc861vd_models[ALC861VD_MODEL_LAST] = { |
10327 | [ALC660VD_3ST] = "3stack-660", | 11094 | [ALC660VD_3ST] = "3stack-660", |
10328 | [ALC660VD_3ST_DIG]= "3stack-660-digout", | 11095 | [ALC660VD_3ST_DIG] = "3stack-660-digout", |
10329 | [ALC861VD_3ST] = "3stack", | 11096 | [ALC861VD_3ST] = "3stack", |
10330 | [ALC861VD_3ST_DIG] = "3stack-digout", | 11097 | [ALC861VD_3ST_DIG] = "3stack-digout", |
10331 | [ALC861VD_6ST_DIG] = "6stack-digout", | 11098 | [ALC861VD_6ST_DIG] = "6stack-digout", |
10332 | [ALC861VD_LENOVO] = "lenovo", | 11099 | [ALC861VD_LENOVO] = "lenovo", |
10333 | [ALC861VD_DALLAS] = "dallas", | 11100 | [ALC861VD_DALLAS] = "dallas", |
11101 | [ALC861VD_HP] = "hp", | ||
10334 | [ALC861VD_AUTO] = "auto", | 11102 | [ALC861VD_AUTO] = "auto", |
10335 | }; | 11103 | }; |
10336 | 11104 | ||
@@ -10341,11 +11109,15 @@ static struct snd_pci_quirk alc861vd_cfg_tbl[] = { | |||
10341 | SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST), | 11109 | SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST), |
10342 | SND_PCI_QUIRK(0x1019, 0xa88d, "Realtek ALC660 demo", ALC660VD_3ST), | 11110 | SND_PCI_QUIRK(0x1019, 0xa88d, "Realtek ALC660 demo", ALC660VD_3ST), |
10343 | 11111 | ||
10344 | SND_PCI_QUIRK(0x1179, 0xff00, "DALLAS", ALC861VD_DALLAS), | 11112 | /*SND_PCI_QUIRK(0x1179, 0xff00, "DALLAS", ALC861VD_DALLAS),*/ /*lenovo*/ |
10345 | SND_PCI_QUIRK(0x1179, 0xff01, "DALLAS", ALC861VD_DALLAS), | 11113 | SND_PCI_QUIRK(0x1179, 0xff01, "DALLAS", ALC861VD_DALLAS), |
10346 | SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo 3000 C200", ALC861VD_LENOVO), | 11114 | SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo 3000 C200", ALC861VD_LENOVO), |
10347 | SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo", ALC861VD_LENOVO), | 11115 | SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo", ALC861VD_LENOVO), |
10348 | SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba A135", ALC861VD_LENOVO), | 11116 | SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba A135", ALC861VD_LENOVO), |
11117 | SND_PCI_QUIRK(0x1179, 0xff03, "Toshiba P205", ALC861VD_LENOVO), | ||
11118 | SND_PCI_QUIRK(0x1565, 0x820d, "Biostar NF61S SE", ALC861VD_6ST_DIG), | ||
11119 | SND_PCI_QUIRK(0x1849, 0x0862, "ASRock K8NF6G-VSTA", ALC861VD_6ST_DIG), | ||
11120 | SND_PCI_QUIRK(0x103c, 0x30bf, "HP TX1000", ALC861VD_HP), | ||
10349 | {} | 11121 | {} |
10350 | }; | 11122 | }; |
10351 | 11123 | ||
@@ -10435,7 +11207,21 @@ static struct alc_config_preset alc861vd_presets[] = { | |||
10435 | .input_mux = &alc861vd_dallas_capture_source, | 11207 | .input_mux = &alc861vd_dallas_capture_source, |
10436 | .unsol_event = alc861vd_dallas_unsol_event, | 11208 | .unsol_event = alc861vd_dallas_unsol_event, |
10437 | .init_hook = alc861vd_dallas_automute, | 11209 | .init_hook = alc861vd_dallas_automute, |
10438 | }, | 11210 | }, |
11211 | [ALC861VD_HP] = { | ||
11212 | .mixers = { alc861vd_hp_mixer }, | ||
11213 | .init_verbs = { alc861vd_dallas_verbs, alc861vd_eapd_verbs }, | ||
11214 | .num_dacs = ARRAY_SIZE(alc861vd_dac_nids), | ||
11215 | .dac_nids = alc861vd_dac_nids, | ||
11216 | .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids), | ||
11217 | .dig_out_nid = ALC861VD_DIGOUT_NID, | ||
11218 | .adc_nids = alc861vd_adc_nids, | ||
11219 | .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes), | ||
11220 | .channel_mode = alc861vd_3stack_2ch_modes, | ||
11221 | .input_mux = &alc861vd_hp_capture_source, | ||
11222 | .unsol_event = alc861vd_dallas_unsol_event, | ||
11223 | .init_hook = alc861vd_dallas_automute, | ||
11224 | }, | ||
10439 | }; | 11225 | }; |
10440 | 11226 | ||
10441 | /* | 11227 | /* |
@@ -10668,6 +11454,10 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec) | |||
10668 | spec->num_mux_defs = 1; | 11454 | spec->num_mux_defs = 1; |
10669 | spec->input_mux = &spec->private_imux; | 11455 | spec->input_mux = &spec->private_imux; |
10670 | 11456 | ||
11457 | err = alc_auto_add_mic_boost(codec); | ||
11458 | if (err < 0) | ||
11459 | return err; | ||
11460 | |||
10671 | return 1; | 11461 | return 1; |
10672 | } | 11462 | } |
10673 | 11463 | ||
@@ -10735,6 +11525,10 @@ static int patch_alc861vd(struct hda_codec *codec) | |||
10735 | 11525 | ||
10736 | if (board_config == ALC861VD_AUTO) | 11526 | if (board_config == ALC861VD_AUTO) |
10737 | spec->init_hook = alc861vd_auto_init; | 11527 | spec->init_hook = alc861vd_auto_init; |
11528 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
11529 | if (!spec->loopback.amplist) | ||
11530 | spec->loopback.amplist = alc861vd_loopbacks; | ||
11531 | #endif | ||
10738 | 11532 | ||
10739 | return 0; | 11533 | return 0; |
10740 | } | 11534 | } |
@@ -10782,6 +11576,15 @@ static struct hda_input_mux alc662_lenovo_101e_capture_source = { | |||
10782 | { "Line", 0x2 }, | 11576 | { "Line", 0x2 }, |
10783 | }, | 11577 | }, |
10784 | }; | 11578 | }; |
11579 | |||
11580 | static struct hda_input_mux alc662_eeepc_capture_source = { | ||
11581 | .num_items = 2, | ||
11582 | .items = { | ||
11583 | { "i-Mic", 0x1 }, | ||
11584 | { "e-Mic", 0x0 }, | ||
11585 | }, | ||
11586 | }; | ||
11587 | |||
10785 | #define alc662_mux_enum_info alc_mux_enum_info | 11588 | #define alc662_mux_enum_info alc_mux_enum_info |
10786 | #define alc662_mux_enum_get alc_mux_enum_get | 11589 | #define alc662_mux_enum_get alc_mux_enum_get |
10787 | 11590 | ||
@@ -10792,7 +11595,7 @@ static int alc662_mux_enum_put(struct snd_kcontrol *kcontrol, | |||
10792 | struct alc_spec *spec = codec->spec; | 11595 | struct alc_spec *spec = codec->spec; |
10793 | const struct hda_input_mux *imux = spec->input_mux; | 11596 | const struct hda_input_mux *imux = spec->input_mux; |
10794 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | 11597 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); |
10795 | static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 }; | 11598 | static hda_nid_t capture_mixers[2] = { 0x23, 0x22 }; |
10796 | hda_nid_t nid = capture_mixers[adc_idx]; | 11599 | hda_nid_t nid = capture_mixers[adc_idx]; |
10797 | unsigned int *cur_val = &spec->cur_mux[adc_idx]; | 11600 | unsigned int *cur_val = &spec->cur_mux[adc_idx]; |
10798 | unsigned int i, idx; | 11601 | unsigned int i, idx; |
@@ -10800,12 +11603,13 @@ static int alc662_mux_enum_put(struct snd_kcontrol *kcontrol, | |||
10800 | idx = ucontrol->value.enumerated.item[0]; | 11603 | idx = ucontrol->value.enumerated.item[0]; |
10801 | if (idx >= imux->num_items) | 11604 | if (idx >= imux->num_items) |
10802 | idx = imux->num_items - 1; | 11605 | idx = imux->num_items - 1; |
10803 | if (*cur_val == idx && !codec->in_resume) | 11606 | if (*cur_val == idx) |
10804 | return 0; | 11607 | return 0; |
10805 | for (i = 0; i < imux->num_items; i++) { | 11608 | for (i = 0; i < imux->num_items; i++) { |
10806 | unsigned int v = (i == idx) ? 0x7000 : 0x7080; | 11609 | unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE; |
10807 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, | 11610 | snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, |
10808 | v | (imux->items[i].index << 8)); | 11611 | imux->items[i].index, |
11612 | HDA_AMP_MUTE, v); | ||
10809 | } | 11613 | } |
10810 | *cur_val = idx; | 11614 | *cur_val = idx; |
10811 | return 1; | 11615 | return 1; |
@@ -10997,6 +11801,22 @@ static struct snd_kcontrol_new alc662_lenovo_101e_mixer[] = { | |||
10997 | { } /* end */ | 11801 | { } /* end */ |
10998 | }; | 11802 | }; |
10999 | 11803 | ||
11804 | static struct snd_kcontrol_new alc662_eeepc_p701_mixer[] = { | ||
11805 | HDA_CODEC_MUTE("iSpeaker Playback Switch", 0x14, 0x0, HDA_OUTPUT), | ||
11806 | |||
11807 | HDA_CODEC_VOLUME("LineOut Playback Volume", 0x02, 0x0, HDA_OUTPUT), | ||
11808 | HDA_CODEC_MUTE("LineOut Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | ||
11809 | |||
11810 | HDA_CODEC_VOLUME("e-Mic Boost", 0x18, 0, HDA_INPUT), | ||
11811 | HDA_CODEC_VOLUME("e-Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
11812 | HDA_CODEC_MUTE("e-Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
11813 | |||
11814 | HDA_CODEC_VOLUME("i-Mic Boost", 0x19, 0, HDA_INPUT), | ||
11815 | HDA_CODEC_VOLUME("i-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | ||
11816 | HDA_CODEC_MUTE("i-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | ||
11817 | { } /* end */ | ||
11818 | }; | ||
11819 | |||
11000 | static struct snd_kcontrol_new alc662_chmode_mixer[] = { | 11820 | static struct snd_kcontrol_new alc662_chmode_mixer[] = { |
11001 | { | 11821 | { |
11002 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 11822 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -11014,18 +11834,18 @@ static struct hda_verb alc662_init_verbs[] = { | |||
11014 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | 11834 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, |
11015 | /* Front mixer: unmute input/output amp left and right (volume = 0) */ | 11835 | /* Front mixer: unmute input/output amp left and right (volume = 0) */ |
11016 | 11836 | ||
11017 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 11837 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
11018 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 11838 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
11019 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 11839 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
11020 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 11840 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
11021 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 11841 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
11022 | 11842 | ||
11023 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 11843 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
11024 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 11844 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
11025 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 11845 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
11026 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 11846 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
11027 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 11847 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
11028 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 11848 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
11029 | 11849 | ||
11030 | /* Front Pin: output 0 (0x0c) */ | 11850 | /* Front Pin: output 0 (0x0c) */ |
11031 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | 11851 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
@@ -11062,13 +11882,24 @@ static struct hda_verb alc662_init_verbs[] = { | |||
11062 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 11882 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
11063 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 11883 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, |
11064 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 11884 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, |
11885 | |||
11886 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
11887 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
11888 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | ||
11889 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | ||
11065 | { } | 11890 | { } |
11066 | }; | 11891 | }; |
11067 | 11892 | ||
11068 | static struct hda_verb alc662_sue_init_verbs[] = { | 11893 | static struct hda_verb alc662_sue_init_verbs[] = { |
11069 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_FRONT_EVENT}, | 11894 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_FRONT_EVENT}, |
11070 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT}, | 11895 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT}, |
11071 | {} | 11896 | {} |
11897 | }; | ||
11898 | |||
11899 | static struct hda_verb alc662_eeepc_sue_init_verbs[] = { | ||
11900 | {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT}, | ||
11901 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, | ||
11902 | {} | ||
11072 | }; | 11903 | }; |
11073 | 11904 | ||
11074 | /* | 11905 | /* |
@@ -11087,11 +11918,11 @@ static struct hda_verb alc662_auto_init_verbs[] = { | |||
11087 | * panel mic (mic 2) | 11918 | * panel mic (mic 2) |
11088 | */ | 11919 | */ |
11089 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | 11920 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ |
11090 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 11921 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
11091 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 11922 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
11092 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 11923 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
11093 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 11924 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
11094 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 11925 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
11095 | 11926 | ||
11096 | /* | 11927 | /* |
11097 | * Set up output mixers (0x0c - 0x0f) | 11928 | * Set up output mixers (0x0c - 0x0f) |
@@ -11103,23 +11934,19 @@ static struct hda_verb alc662_auto_init_verbs[] = { | |||
11103 | 11934 | ||
11104 | /* set up input amps for analog loopback */ | 11935 | /* set up input amps for analog loopback */ |
11105 | /* Amp Indices: DAC = 0, mixer = 1 */ | 11936 | /* Amp Indices: DAC = 0, mixer = 1 */ |
11106 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 11937 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
11107 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 11938 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
11108 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 11939 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
11109 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 11940 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
11110 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 11941 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
11111 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 11942 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
11112 | 11943 | ||
11113 | 11944 | ||
11114 | /* FIXME: use matrix-type input source selection */ | 11945 | /* FIXME: use matrix-type input source selection */ |
11115 | /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ | 11946 | /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ |
11116 | /* Input mixer */ | 11947 | /* Input mixer */ |
11117 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 11948 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
11118 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 11949 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
11119 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | ||
11120 | /*{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},*/ | ||
11121 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | ||
11122 | |||
11123 | { } | 11950 | { } |
11124 | }; | 11951 | }; |
11125 | 11952 | ||
@@ -11150,11 +11977,9 @@ static void alc662_lenovo_101e_ispeaker_automute(struct hda_codec *codec) | |||
11150 | 11977 | ||
11151 | present = snd_hda_codec_read(codec, 0x14, 0, | 11978 | present = snd_hda_codec_read(codec, 0x14, 0, |
11152 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 11979 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
11153 | bits = present ? 0x80 : 0; | 11980 | bits = present ? HDA_AMP_MUTE : 0; |
11154 | snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, | 11981 | snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, |
11155 | 0x80, bits); | 11982 | HDA_AMP_MUTE, bits); |
11156 | snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, | ||
11157 | 0x80, bits); | ||
11158 | } | 11983 | } |
11159 | 11984 | ||
11160 | static void alc662_lenovo_101e_all_automute(struct hda_codec *codec) | 11985 | static void alc662_lenovo_101e_all_automute(struct hda_codec *codec) |
@@ -11164,15 +11989,11 @@ static void alc662_lenovo_101e_all_automute(struct hda_codec *codec) | |||
11164 | 11989 | ||
11165 | present = snd_hda_codec_read(codec, 0x1b, 0, | 11990 | present = snd_hda_codec_read(codec, 0x1b, 0, |
11166 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 11991 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
11167 | bits = present ? 0x80 : 0; | 11992 | bits = present ? HDA_AMP_MUTE : 0; |
11168 | snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, | 11993 | snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, |
11169 | 0x80, bits); | 11994 | HDA_AMP_MUTE, bits); |
11170 | snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, | 11995 | snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, |
11171 | 0x80, bits); | 11996 | HDA_AMP_MUTE, bits); |
11172 | snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, | ||
11173 | 0x80, bits); | ||
11174 | snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, | ||
11175 | 0x80, bits); | ||
11176 | } | 11997 | } |
11177 | 11998 | ||
11178 | static void alc662_lenovo_101e_unsol_event(struct hda_codec *codec, | 11999 | static void alc662_lenovo_101e_unsol_event(struct hda_codec *codec, |
@@ -11184,6 +12005,43 @@ static void alc662_lenovo_101e_unsol_event(struct hda_codec *codec, | |||
11184 | alc662_lenovo_101e_ispeaker_automute(codec); | 12005 | alc662_lenovo_101e_ispeaker_automute(codec); |
11185 | } | 12006 | } |
11186 | 12007 | ||
12008 | static void alc662_eeepc_mic_automute(struct hda_codec *codec) | ||
12009 | { | ||
12010 | unsigned int present; | ||
12011 | |||
12012 | present = snd_hda_codec_read(codec, 0x18, 0, | ||
12013 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
12014 | snd_hda_codec_write(codec, 0x22, 0, AC_VERB_SET_AMP_GAIN_MUTE, | ||
12015 | 0x7000 | (0x00 << 8) | (present ? 0 : 0x80)); | ||
12016 | snd_hda_codec_write(codec, 0x23, 0, AC_VERB_SET_AMP_GAIN_MUTE, | ||
12017 | 0x7000 | (0x00 << 8) | (present ? 0 : 0x80)); | ||
12018 | snd_hda_codec_write(codec, 0x22, 0, AC_VERB_SET_AMP_GAIN_MUTE, | ||
12019 | 0x7000 | (0x01 << 8) | (present ? 0x80 : 0)); | ||
12020 | snd_hda_codec_write(codec, 0x23, 0, AC_VERB_SET_AMP_GAIN_MUTE, | ||
12021 | 0x7000 | (0x01 << 8) | (present ? 0x80 : 0)); | ||
12022 | } | ||
12023 | |||
12024 | /* unsolicited event for HP jack sensing */ | ||
12025 | static void alc662_eeepc_unsol_event(struct hda_codec *codec, | ||
12026 | unsigned int res) | ||
12027 | { | ||
12028 | if ((res >> 26) == ALC880_HP_EVENT) | ||
12029 | alc262_hippo1_automute( codec ); | ||
12030 | |||
12031 | if ((res >> 26) == ALC880_MIC_EVENT) | ||
12032 | alc662_eeepc_mic_automute(codec); | ||
12033 | } | ||
12034 | |||
12035 | static void alc662_eeepc_inithook(struct hda_codec *codec) | ||
12036 | { | ||
12037 | alc262_hippo1_automute( codec ); | ||
12038 | alc662_eeepc_mic_automute(codec); | ||
12039 | } | ||
12040 | |||
12041 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
12042 | #define alc662_loopbacks alc880_loopbacks | ||
12043 | #endif | ||
12044 | |||
11187 | 12045 | ||
11188 | /* pcm configuration: identiacal with ALC880 */ | 12046 | /* pcm configuration: identiacal with ALC880 */ |
11189 | #define alc662_pcm_analog_playback alc880_pcm_analog_playback | 12047 | #define alc662_pcm_analog_playback alc880_pcm_analog_playback |
@@ -11205,12 +12063,13 @@ static const char *alc662_models[ALC662_MODEL_LAST] = { | |||
11205 | 12063 | ||
11206 | static struct snd_pci_quirk alc662_cfg_tbl[] = { | 12064 | static struct snd_pci_quirk alc662_cfg_tbl[] = { |
11207 | SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E), | 12065 | SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E), |
12066 | SND_PCI_QUIRK(0x1043, 0x82a1, "ASUS Eeepc", ALC662_ASUS_EEEPC_P701), | ||
11208 | {} | 12067 | {} |
11209 | }; | 12068 | }; |
11210 | 12069 | ||
11211 | static struct alc_config_preset alc662_presets[] = { | 12070 | static struct alc_config_preset alc662_presets[] = { |
11212 | [ALC662_3ST_2ch_DIG] = { | 12071 | [ALC662_3ST_2ch_DIG] = { |
11213 | .mixers = { alc662_3ST_2ch_mixer }, | 12072 | .mixers = { alc662_3ST_2ch_mixer, alc662_capture_mixer }, |
11214 | .init_verbs = { alc662_init_verbs }, | 12073 | .init_verbs = { alc662_init_verbs }, |
11215 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 12074 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
11216 | .dac_nids = alc662_dac_nids, | 12075 | .dac_nids = alc662_dac_nids, |
@@ -11223,7 +12082,8 @@ static struct alc_config_preset alc662_presets[] = { | |||
11223 | .input_mux = &alc662_capture_source, | 12082 | .input_mux = &alc662_capture_source, |
11224 | }, | 12083 | }, |
11225 | [ALC662_3ST_6ch_DIG] = { | 12084 | [ALC662_3ST_6ch_DIG] = { |
11226 | .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer }, | 12085 | .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer, |
12086 | alc662_capture_mixer }, | ||
11227 | .init_verbs = { alc662_init_verbs }, | 12087 | .init_verbs = { alc662_init_verbs }, |
11228 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 12088 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
11229 | .dac_nids = alc662_dac_nids, | 12089 | .dac_nids = alc662_dac_nids, |
@@ -11237,7 +12097,8 @@ static struct alc_config_preset alc662_presets[] = { | |||
11237 | .input_mux = &alc662_capture_source, | 12097 | .input_mux = &alc662_capture_source, |
11238 | }, | 12098 | }, |
11239 | [ALC662_3ST_6ch] = { | 12099 | [ALC662_3ST_6ch] = { |
11240 | .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer }, | 12100 | .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer, |
12101 | alc662_capture_mixer }, | ||
11241 | .init_verbs = { alc662_init_verbs }, | 12102 | .init_verbs = { alc662_init_verbs }, |
11242 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 12103 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
11243 | .dac_nids = alc662_dac_nids, | 12104 | .dac_nids = alc662_dac_nids, |
@@ -11249,7 +12110,8 @@ static struct alc_config_preset alc662_presets[] = { | |||
11249 | .input_mux = &alc662_capture_source, | 12110 | .input_mux = &alc662_capture_source, |
11250 | }, | 12111 | }, |
11251 | [ALC662_5ST_DIG] = { | 12112 | [ALC662_5ST_DIG] = { |
11252 | .mixers = { alc662_base_mixer, alc662_chmode_mixer }, | 12113 | .mixers = { alc662_base_mixer, alc662_chmode_mixer, |
12114 | alc662_capture_mixer }, | ||
11253 | .init_verbs = { alc662_init_verbs }, | 12115 | .init_verbs = { alc662_init_verbs }, |
11254 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 12116 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
11255 | .dac_nids = alc662_dac_nids, | 12117 | .dac_nids = alc662_dac_nids, |
@@ -11262,7 +12124,7 @@ static struct alc_config_preset alc662_presets[] = { | |||
11262 | .input_mux = &alc662_capture_source, | 12124 | .input_mux = &alc662_capture_source, |
11263 | }, | 12125 | }, |
11264 | [ALC662_LENOVO_101E] = { | 12126 | [ALC662_LENOVO_101E] = { |
11265 | .mixers = { alc662_lenovo_101e_mixer }, | 12127 | .mixers = { alc662_lenovo_101e_mixer, alc662_capture_mixer }, |
11266 | .init_verbs = { alc662_init_verbs, alc662_sue_init_verbs }, | 12128 | .init_verbs = { alc662_init_verbs, alc662_sue_init_verbs }, |
11267 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 12129 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
11268 | .dac_nids = alc662_dac_nids, | 12130 | .dac_nids = alc662_dac_nids, |
@@ -11274,6 +12136,20 @@ static struct alc_config_preset alc662_presets[] = { | |||
11274 | .unsol_event = alc662_lenovo_101e_unsol_event, | 12136 | .unsol_event = alc662_lenovo_101e_unsol_event, |
11275 | .init_hook = alc662_lenovo_101e_all_automute, | 12137 | .init_hook = alc662_lenovo_101e_all_automute, |
11276 | }, | 12138 | }, |
12139 | [ALC662_ASUS_EEEPC_P701] = { | ||
12140 | .mixers = { alc662_eeepc_p701_mixer, alc662_capture_mixer }, | ||
12141 | .init_verbs = { alc662_init_verbs, | ||
12142 | alc662_eeepc_sue_init_verbs }, | ||
12143 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | ||
12144 | .dac_nids = alc662_dac_nids, | ||
12145 | .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids), | ||
12146 | .adc_nids = alc662_adc_nids, | ||
12147 | .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes), | ||
12148 | .channel_mode = alc662_3ST_2ch_modes, | ||
12149 | .input_mux = &alc662_eeepc_capture_source, | ||
12150 | .unsol_event = alc662_eeepc_unsol_event, | ||
12151 | .init_hook = alc662_eeepc_inithook, | ||
12152 | }, | ||
11277 | 12153 | ||
11278 | }; | 12154 | }; |
11279 | 12155 | ||
@@ -11296,7 +12172,7 @@ static int alc662_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
11296 | for (i = 0; i < cfg->line_outs; i++) { | 12172 | for (i = 0; i < cfg->line_outs; i++) { |
11297 | if (!spec->multiout.dac_nids[i]) | 12173 | if (!spec->multiout.dac_nids[i]) |
11298 | continue; | 12174 | continue; |
11299 | nid = alc880_idx_to_mixer(i); | 12175 | nid = alc880_idx_to_dac(i); |
11300 | if (i == 2) { | 12176 | if (i == 2) { |
11301 | /* Center/LFE */ | 12177 | /* Center/LFE */ |
11302 | err = add_control(spec, ALC_CTL_WIDGET_VOL, | 12178 | err = add_control(spec, ALC_CTL_WIDGET_VOL, |
@@ -11586,6 +12462,10 @@ static int patch_alc662(struct hda_codec *codec) | |||
11586 | codec->patch_ops = alc_patch_ops; | 12462 | codec->patch_ops = alc_patch_ops; |
11587 | if (board_config == ALC662_AUTO) | 12463 | if (board_config == ALC662_AUTO) |
11588 | spec->init_hook = alc662_auto_init; | 12464 | spec->init_hook = alc662_auto_init; |
12465 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
12466 | if (!spec->loopback.amplist) | ||
12467 | spec->loopback.amplist = alc662_loopbacks; | ||
12468 | #endif | ||
11589 | 12469 | ||
11590 | return 0; | 12470 | return 0; |
11591 | } | 12471 | } |
diff --git a/sound/pci/hda/patch_si3054.c b/sound/pci/hda/patch_si3054.c index 6d2ecc38905c..2a4b9609aa5c 100644 --- a/sound/pci/hda/patch_si3054.c +++ b/sound/pci/hda/patch_si3054.c | |||
@@ -78,6 +78,8 @@ | |||
78 | /* si3054 codec registers (nodes) access macros */ | 78 | /* si3054 codec registers (nodes) access macros */ |
79 | #define GET_REG(codec,reg) (snd_hda_codec_read(codec,reg,0,SI3054_VERB_READ_NODE,0)) | 79 | #define GET_REG(codec,reg) (snd_hda_codec_read(codec,reg,0,SI3054_VERB_READ_NODE,0)) |
80 | #define SET_REG(codec,reg,val) (snd_hda_codec_write(codec,reg,0,SI3054_VERB_WRITE_NODE,val)) | 80 | #define SET_REG(codec,reg,val) (snd_hda_codec_write(codec,reg,0,SI3054_VERB_WRITE_NODE,val)) |
81 | #define SET_REG_CACHE(codec,reg,val) \ | ||
82 | snd_hda_codec_write_cache(codec,reg,0,SI3054_VERB_WRITE_NODE,val) | ||
81 | 83 | ||
82 | 84 | ||
83 | struct si3054_spec { | 85 | struct si3054_spec { |
@@ -94,15 +96,7 @@ struct si3054_spec { | |||
94 | #define PRIVATE_REG(val) ((val>>16)&0xffff) | 96 | #define PRIVATE_REG(val) ((val>>16)&0xffff) |
95 | #define PRIVATE_MASK(val) (val&0xffff) | 97 | #define PRIVATE_MASK(val) (val&0xffff) |
96 | 98 | ||
97 | static int si3054_switch_info(struct snd_kcontrol *kcontrol, | 99 | #define si3054_switch_info snd_ctl_boolean_mono_info |
98 | struct snd_ctl_elem_info *uinfo) | ||
99 | { | ||
100 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
101 | uinfo->count = 1; | ||
102 | uinfo->value.integer.min = 0; | ||
103 | uinfo->value.integer.max = 1; | ||
104 | return 0; | ||
105 | } | ||
106 | 100 | ||
107 | static int si3054_switch_get(struct snd_kcontrol *kcontrol, | 101 | static int si3054_switch_get(struct snd_kcontrol *kcontrol, |
108 | struct snd_ctl_elem_value *uvalue) | 102 | struct snd_ctl_elem_value *uvalue) |
@@ -121,9 +115,9 @@ static int si3054_switch_put(struct snd_kcontrol *kcontrol, | |||
121 | u16 reg = PRIVATE_REG(kcontrol->private_value); | 115 | u16 reg = PRIVATE_REG(kcontrol->private_value); |
122 | u16 mask = PRIVATE_MASK(kcontrol->private_value); | 116 | u16 mask = PRIVATE_MASK(kcontrol->private_value); |
123 | if (uvalue->value.integer.value[0]) | 117 | if (uvalue->value.integer.value[0]) |
124 | SET_REG(codec, reg, (GET_REG(codec, reg)) | mask); | 118 | SET_REG_CACHE(codec, reg, (GET_REG(codec, reg)) | mask); |
125 | else | 119 | else |
126 | SET_REG(codec, reg, (GET_REG(codec, reg)) & ~mask); | 120 | SET_REG_CACHE(codec, reg, (GET_REG(codec, reg)) & ~mask); |
127 | return 0; | 121 | return 0; |
128 | } | 122 | } |
129 | 123 | ||
@@ -275,10 +269,6 @@ static struct hda_codec_ops si3054_patch_ops = { | |||
275 | .build_pcms = si3054_build_pcms, | 269 | .build_pcms = si3054_build_pcms, |
276 | .init = si3054_init, | 270 | .init = si3054_init, |
277 | .free = si3054_free, | 271 | .free = si3054_free, |
278 | #ifdef CONFIG_PM | ||
279 | //.suspend = si3054_suspend, | ||
280 | .resume = si3054_init, | ||
281 | #endif | ||
282 | }; | 272 | }; |
283 | 273 | ||
284 | static int patch_si3054(struct hda_codec *codec) | 274 | static int patch_si3054(struct hda_codec *codec) |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 3f25de72966b..bf950195107c 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -39,12 +39,25 @@ | |||
39 | 39 | ||
40 | enum { | 40 | enum { |
41 | STAC_REF, | 41 | STAC_REF, |
42 | STAC_9200_DELL_D21, | ||
43 | STAC_9200_DELL_D22, | ||
44 | STAC_9200_DELL_D23, | ||
45 | STAC_9200_DELL_M21, | ||
46 | STAC_9200_DELL_M22, | ||
47 | STAC_9200_DELL_M23, | ||
48 | STAC_9200_DELL_M24, | ||
49 | STAC_9200_DELL_M25, | ||
50 | STAC_9200_DELL_M26, | ||
51 | STAC_9200_DELL_M27, | ||
52 | STAC_9200_GATEWAY, | ||
42 | STAC_9200_MODELS | 53 | STAC_9200_MODELS |
43 | }; | 54 | }; |
44 | 55 | ||
45 | enum { | 56 | enum { |
46 | STAC_9205_REF, | 57 | STAC_9205_REF, |
47 | STAC_M43xx, | 58 | STAC_9205_DELL_M42, |
59 | STAC_9205_DELL_M43, | ||
60 | STAC_9205_DELL_M44, | ||
48 | STAC_9205_MODELS | 61 | STAC_9205_MODELS |
49 | }; | 62 | }; |
50 | 63 | ||
@@ -60,19 +73,22 @@ enum { | |||
60 | STAC_D945_REF, | 73 | STAC_D945_REF, |
61 | STAC_D945GTP3, | 74 | STAC_D945GTP3, |
62 | STAC_D945GTP5, | 75 | STAC_D945GTP5, |
63 | STAC_922X_DELL, | ||
64 | STAC_INTEL_MAC_V1, | 76 | STAC_INTEL_MAC_V1, |
65 | STAC_INTEL_MAC_V2, | 77 | STAC_INTEL_MAC_V2, |
66 | STAC_INTEL_MAC_V3, | 78 | STAC_INTEL_MAC_V3, |
67 | STAC_INTEL_MAC_V4, | 79 | STAC_INTEL_MAC_V4, |
68 | STAC_INTEL_MAC_V5, | 80 | STAC_INTEL_MAC_V5, |
69 | /* for backward compitability */ | 81 | /* for backward compatibility */ |
70 | STAC_MACMINI, | 82 | STAC_MACMINI, |
71 | STAC_MACBOOK, | 83 | STAC_MACBOOK, |
72 | STAC_MACBOOK_PRO_V1, | 84 | STAC_MACBOOK_PRO_V1, |
73 | STAC_MACBOOK_PRO_V2, | 85 | STAC_MACBOOK_PRO_V2, |
74 | STAC_IMAC_INTEL, | 86 | STAC_IMAC_INTEL, |
75 | STAC_IMAC_INTEL_20, | 87 | STAC_IMAC_INTEL_20, |
88 | STAC_922X_DELL_D81, | ||
89 | STAC_922X_DELL_D82, | ||
90 | STAC_922X_DELL_M81, | ||
91 | STAC_922X_DELL_M82, | ||
76 | STAC_922X_MODELS | 92 | STAC_922X_MODELS |
77 | }; | 93 | }; |
78 | 94 | ||
@@ -80,6 +96,7 @@ enum { | |||
80 | STAC_D965_REF, | 96 | STAC_D965_REF, |
81 | STAC_D965_3ST, | 97 | STAC_D965_3ST, |
82 | STAC_D965_5ST, | 98 | STAC_D965_5ST, |
99 | STAC_DELL_3ST, | ||
83 | STAC_927X_MODELS | 100 | STAC_927X_MODELS |
84 | }; | 101 | }; |
85 | 102 | ||
@@ -95,6 +112,8 @@ struct sigmatel_spec { | |||
95 | unsigned int hp_detect: 1; | 112 | unsigned int hp_detect: 1; |
96 | unsigned int gpio_mute: 1; | 113 | unsigned int gpio_mute: 1; |
97 | 114 | ||
115 | unsigned int gpio_mask, gpio_data; | ||
116 | |||
98 | /* playback */ | 117 | /* playback */ |
99 | struct hda_multi_out multiout; | 118 | struct hda_multi_out multiout; |
100 | hda_nid_t dac_nids[5]; | 119 | hda_nid_t dac_nids[5]; |
@@ -127,6 +146,8 @@ struct sigmatel_spec { | |||
127 | 146 | ||
128 | /* i/o switches */ | 147 | /* i/o switches */ |
129 | unsigned int io_switch[2]; | 148 | unsigned int io_switch[2]; |
149 | unsigned int clfe_swap; | ||
150 | unsigned int aloopback; | ||
130 | 151 | ||
131 | struct hda_pcm pcm_rec[2]; /* PCM information */ | 152 | struct hda_pcm pcm_rec[2]; /* PCM information */ |
132 | 153 | ||
@@ -162,8 +183,9 @@ static hda_nid_t stac925x_dac_nids[1] = { | |||
162 | 0x02, | 183 | 0x02, |
163 | }; | 184 | }; |
164 | 185 | ||
165 | static hda_nid_t stac925x_dmic_nids[1] = { | 186 | #define STAC925X_NUM_DMICS 1 |
166 | 0x15, | 187 | static hda_nid_t stac925x_dmic_nids[STAC925X_NUM_DMICS + 1] = { |
188 | 0x15, 0 | ||
167 | }; | 189 | }; |
168 | 190 | ||
169 | static hda_nid_t stac922x_adc_nids[2] = { | 191 | static hda_nid_t stac922x_adc_nids[2] = { |
@@ -190,8 +212,9 @@ static hda_nid_t stac9205_mux_nids[2] = { | |||
190 | 0x19, 0x1a | 212 | 0x19, 0x1a |
191 | }; | 213 | }; |
192 | 214 | ||
193 | static hda_nid_t stac9205_dmic_nids[2] = { | 215 | #define STAC9205_NUM_DMICS 2 |
194 | 0x17, 0x18, | 216 | static hda_nid_t stac9205_dmic_nids[STAC9205_NUM_DMICS + 1] = { |
217 | 0x17, 0x18, 0 | ||
195 | }; | 218 | }; |
196 | 219 | ||
197 | static hda_nid_t stac9200_pin_nids[8] = { | 220 | static hda_nid_t stac9200_pin_nids[8] = { |
@@ -276,12 +299,97 @@ static int stac92xx_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
276 | spec->mux_nids[adc_idx], &spec->cur_mux[adc_idx]); | 299 | spec->mux_nids[adc_idx], &spec->cur_mux[adc_idx]); |
277 | } | 300 | } |
278 | 301 | ||
302 | #define stac92xx_aloopback_info snd_ctl_boolean_mono_info | ||
303 | |||
304 | static int stac92xx_aloopback_get(struct snd_kcontrol *kcontrol, | ||
305 | struct snd_ctl_elem_value *ucontrol) | ||
306 | { | ||
307 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
308 | struct sigmatel_spec *spec = codec->spec; | ||
309 | |||
310 | ucontrol->value.integer.value[0] = spec->aloopback; | ||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | static int stac92xx_aloopback_put(struct snd_kcontrol *kcontrol, | ||
315 | struct snd_ctl_elem_value *ucontrol) | ||
316 | { | ||
317 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
318 | struct sigmatel_spec *spec = codec->spec; | ||
319 | unsigned int dac_mode; | ||
320 | |||
321 | if (spec->aloopback == ucontrol->value.integer.value[0]) | ||
322 | return 0; | ||
323 | |||
324 | spec->aloopback = ucontrol->value.integer.value[0]; | ||
325 | |||
326 | |||
327 | dac_mode = snd_hda_codec_read(codec, codec->afg, 0, | ||
328 | kcontrol->private_value & 0xFFFF, 0x0); | ||
329 | |||
330 | if (spec->aloopback) { | ||
331 | snd_hda_power_up(codec); | ||
332 | dac_mode |= 0x40; | ||
333 | } else { | ||
334 | snd_hda_power_down(codec); | ||
335 | dac_mode &= ~0x40; | ||
336 | } | ||
337 | |||
338 | snd_hda_codec_write_cache(codec, codec->afg, 0, | ||
339 | kcontrol->private_value >> 16, dac_mode); | ||
340 | |||
341 | return 1; | ||
342 | } | ||
343 | |||
344 | static int stac92xx_volknob_info(struct snd_kcontrol *kcontrol, | ||
345 | struct snd_ctl_elem_info *uinfo) | ||
346 | { | ||
347 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
348 | uinfo->count = 1; | ||
349 | uinfo->value.integer.min = 0; | ||
350 | uinfo->value.integer.max = 127; | ||
351 | return 0; | ||
352 | } | ||
353 | |||
354 | static int stac92xx_volknob_get(struct snd_kcontrol *kcontrol, | ||
355 | struct snd_ctl_elem_value *ucontrol) | ||
356 | { | ||
357 | ucontrol->value.integer.value[0] = kcontrol->private_value & 0xff; | ||
358 | return 0; | ||
359 | } | ||
360 | |||
361 | static int stac92xx_volknob_put(struct snd_kcontrol *kcontrol, | ||
362 | struct snd_ctl_elem_value *ucontrol) | ||
363 | { | ||
364 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
365 | unsigned int val = kcontrol->private_value & 0xff; | ||
366 | |||
367 | if (val == ucontrol->value.integer.value[0]) | ||
368 | return 0; | ||
369 | |||
370 | val = ucontrol->value.integer.value[0]; | ||
371 | kcontrol->private_value &= ~0xff; | ||
372 | kcontrol->private_value |= val; | ||
373 | |||
374 | snd_hda_codec_write_cache(codec, kcontrol->private_value >> 16, 0, | ||
375 | AC_VERB_SET_VOLUME_KNOB_CONTROL, val | 0x80); | ||
376 | return 1; | ||
377 | } | ||
378 | |||
379 | |||
279 | static struct hda_verb stac9200_core_init[] = { | 380 | static struct hda_verb stac9200_core_init[] = { |
280 | /* set dac0mux for dac converter */ | 381 | /* set dac0mux for dac converter */ |
281 | { 0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, | 382 | { 0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, |
282 | {} | 383 | {} |
283 | }; | 384 | }; |
284 | 385 | ||
386 | static struct hda_verb stac9200_eapd_init[] = { | ||
387 | /* set dac0mux for dac converter */ | ||
388 | {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
389 | {0x08, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, | ||
390 | {} | ||
391 | }; | ||
392 | |||
285 | static struct hda_verb stac925x_core_init[] = { | 393 | static struct hda_verb stac925x_core_init[] = { |
286 | /* set dac0mux for dac converter */ | 394 | /* set dac0mux for dac converter */ |
287 | { 0x06, AC_VERB_SET_CONNECT_SEL, 0x00}, | 395 | { 0x06, AC_VERB_SET_CONNECT_SEL, 0x00}, |
@@ -316,17 +424,43 @@ static struct hda_verb stac9205_core_init[] = { | |||
316 | {} | 424 | {} |
317 | }; | 425 | }; |
318 | 426 | ||
427 | #define STAC_INPUT_SOURCE(cnt) \ | ||
428 | { \ | ||
429 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
430 | .name = "Input Source", \ | ||
431 | .count = cnt, \ | ||
432 | .info = stac92xx_mux_enum_info, \ | ||
433 | .get = stac92xx_mux_enum_get, \ | ||
434 | .put = stac92xx_mux_enum_put, \ | ||
435 | } | ||
436 | |||
437 | #define STAC_ANALOG_LOOPBACK(verb_read,verb_write) \ | ||
438 | { \ | ||
439 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
440 | .name = "Analog Loopback", \ | ||
441 | .count = 1, \ | ||
442 | .info = stac92xx_aloopback_info, \ | ||
443 | .get = stac92xx_aloopback_get, \ | ||
444 | .put = stac92xx_aloopback_put, \ | ||
445 | .private_value = verb_read | (verb_write << 16), \ | ||
446 | } | ||
447 | |||
448 | #define STAC_VOLKNOB(knob_nid) \ | ||
449 | { \ | ||
450 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
451 | .name = "Master Playback Volume", \ | ||
452 | .count = 1, \ | ||
453 | .info = stac92xx_volknob_info, \ | ||
454 | .get = stac92xx_volknob_get, \ | ||
455 | .put = stac92xx_volknob_put, \ | ||
456 | .private_value = 127 | (knob_nid << 16), \ | ||
457 | } | ||
458 | |||
459 | |||
319 | static struct snd_kcontrol_new stac9200_mixer[] = { | 460 | static struct snd_kcontrol_new stac9200_mixer[] = { |
320 | HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT), | 461 | HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT), |
321 | HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT), | 462 | HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT), |
322 | { | 463 | STAC_INPUT_SOURCE(1), |
323 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
324 | .name = "Input Source", | ||
325 | .count = 1, | ||
326 | .info = stac92xx_mux_enum_info, | ||
327 | .get = stac92xx_mux_enum_get, | ||
328 | .put = stac92xx_mux_enum_put, | ||
329 | }, | ||
330 | HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT), | 464 | HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT), |
331 | HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT), | 465 | HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT), |
332 | HDA_CODEC_VOLUME("Capture Mux Volume", 0x0c, 0, HDA_OUTPUT), | 466 | HDA_CODEC_VOLUME("Capture Mux Volume", 0x0c, 0, HDA_OUTPUT), |
@@ -334,86 +468,68 @@ static struct snd_kcontrol_new stac9200_mixer[] = { | |||
334 | }; | 468 | }; |
335 | 469 | ||
336 | static struct snd_kcontrol_new stac925x_mixer[] = { | 470 | static struct snd_kcontrol_new stac925x_mixer[] = { |
337 | { | 471 | STAC_INPUT_SOURCE(1), |
338 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
339 | .name = "Input Source", | ||
340 | .count = 1, | ||
341 | .info = stac92xx_mux_enum_info, | ||
342 | .get = stac92xx_mux_enum_get, | ||
343 | .put = stac92xx_mux_enum_put, | ||
344 | }, | ||
345 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_OUTPUT), | 472 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_OUTPUT), |
346 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_OUTPUT), | 473 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_OUTPUT), |
347 | HDA_CODEC_VOLUME("Capture Mux Volume", 0x0f, 0, HDA_OUTPUT), | 474 | HDA_CODEC_VOLUME("Capture Mux Volume", 0x0f, 0, HDA_OUTPUT), |
348 | { } /* end */ | 475 | { } /* end */ |
349 | }; | 476 | }; |
350 | 477 | ||
351 | /* This needs to be generated dynamically based on sequence */ | 478 | static struct snd_kcontrol_new stac9205_mixer[] = { |
352 | static struct snd_kcontrol_new stac922x_mixer[] = { | ||
353 | { | 479 | { |
354 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 480 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
355 | .name = "Input Source", | 481 | .name = "Digital Input Source", |
356 | .count = 1, | 482 | .count = 1, |
357 | .info = stac92xx_mux_enum_info, | 483 | .info = stac92xx_dmux_enum_info, |
358 | .get = stac92xx_mux_enum_get, | 484 | .get = stac92xx_dmux_enum_get, |
359 | .put = stac92xx_mux_enum_put, | 485 | .put = stac92xx_dmux_enum_put, |
360 | }, | 486 | }, |
361 | HDA_CODEC_VOLUME("Capture Volume", 0x17, 0x0, HDA_INPUT), | 487 | STAC_INPUT_SOURCE(2), |
362 | HDA_CODEC_MUTE("Capture Switch", 0x17, 0x0, HDA_INPUT), | 488 | STAC_ANALOG_LOOPBACK(0xFE0, 0x7E0), |
363 | HDA_CODEC_VOLUME("Mux Capture Volume", 0x12, 0x0, HDA_OUTPUT), | 489 | STAC_VOLKNOB(0x24), |
490 | |||
491 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1b, 0x0, HDA_INPUT), | ||
492 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1d, 0x0, HDA_OUTPUT), | ||
493 | HDA_CODEC_VOLUME_IDX("Mux Capture Volume", 0x0, 0x19, 0x0, HDA_OUTPUT), | ||
494 | |||
495 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x1c, 0x0, HDA_INPUT), | ||
496 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x1e, 0x0, HDA_OUTPUT), | ||
497 | HDA_CODEC_VOLUME_IDX("Mux Capture Volume", 0x1, 0x1A, 0x0, HDA_OUTPUT), | ||
498 | |||
364 | { } /* end */ | 499 | { } /* end */ |
365 | }; | 500 | }; |
366 | 501 | ||
367 | /* This needs to be generated dynamically based on sequence */ | 502 | /* This needs to be generated dynamically based on sequence */ |
368 | static struct snd_kcontrol_new stac9227_mixer[] = { | 503 | static struct snd_kcontrol_new stac922x_mixer[] = { |
369 | { | 504 | STAC_INPUT_SOURCE(2), |
370 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 505 | STAC_VOLKNOB(0x16), |
371 | .name = "Input Source", | 506 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x17, 0x0, HDA_INPUT), |
372 | .count = 1, | 507 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x17, 0x0, HDA_INPUT), |
373 | .info = stac92xx_mux_enum_info, | 508 | HDA_CODEC_VOLUME_IDX("Mux Capture Volume", 0x0, 0x12, 0x0, HDA_OUTPUT), |
374 | .get = stac92xx_mux_enum_get, | 509 | |
375 | .put = stac92xx_mux_enum_put, | 510 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x18, 0x0, HDA_INPUT), |
376 | }, | 511 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x18, 0x0, HDA_INPUT), |
377 | HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), | 512 | HDA_CODEC_VOLUME_IDX("Mux Capture Volume", 0x1, 0x13, 0x0, HDA_OUTPUT), |
378 | HDA_CODEC_MUTE("Capture Switch", 0x1b, 0x0, HDA_OUTPUT), | ||
379 | { } /* end */ | 513 | { } /* end */ |
380 | }; | 514 | }; |
381 | 515 | ||
516 | |||
382 | static struct snd_kcontrol_new stac927x_mixer[] = { | 517 | static struct snd_kcontrol_new stac927x_mixer[] = { |
383 | { | 518 | STAC_INPUT_SOURCE(3), |
384 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 519 | STAC_VOLKNOB(0x24), |
385 | .name = "Input Source", | 520 | STAC_ANALOG_LOOPBACK(0xFEB, 0x7EB), |
386 | .count = 1, | ||
387 | .info = stac92xx_mux_enum_info, | ||
388 | .get = stac92xx_mux_enum_get, | ||
389 | .put = stac92xx_mux_enum_put, | ||
390 | }, | ||
391 | HDA_CODEC_VOLUME("InMux Capture Volume", 0x15, 0x0, HDA_OUTPUT), | ||
392 | HDA_CODEC_VOLUME("InVol Capture Volume", 0x18, 0x0, HDA_INPUT), | ||
393 | HDA_CODEC_MUTE("ADCMux Capture Switch", 0x1b, 0x0, HDA_OUTPUT), | ||
394 | { } /* end */ | ||
395 | }; | ||
396 | 521 | ||
397 | static struct snd_kcontrol_new stac9205_mixer[] = { | 522 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x18, 0x0, HDA_INPUT), |
398 | { | 523 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1b, 0x0, HDA_OUTPUT), |
399 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 524 | HDA_CODEC_VOLUME_IDX("Mux Capture Volume", 0x0, 0x15, 0x0, HDA_OUTPUT), |
400 | .name = "Digital Input Source", | 525 | |
401 | .count = 1, | 526 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x19, 0x0, HDA_INPUT), |
402 | .info = stac92xx_dmux_enum_info, | 527 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x1c, 0x0, HDA_OUTPUT), |
403 | .get = stac92xx_dmux_enum_get, | 528 | HDA_CODEC_VOLUME_IDX("Mux Capture Volume", 0x1, 0x16, 0x0, HDA_OUTPUT), |
404 | .put = stac92xx_dmux_enum_put, | 529 | |
405 | }, | 530 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x2, 0x1A, 0x0, HDA_INPUT), |
406 | { | 531 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x2, 0x1d, 0x0, HDA_OUTPUT), |
407 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 532 | HDA_CODEC_VOLUME_IDX("Mux Capture Volume", 0x2, 0x17, 0x0, HDA_OUTPUT), |
408 | .name = "Input Source", | ||
409 | .count = 1, | ||
410 | .info = stac92xx_mux_enum_info, | ||
411 | .get = stac92xx_mux_enum_get, | ||
412 | .put = stac92xx_mux_enum_put, | ||
413 | }, | ||
414 | HDA_CODEC_VOLUME("InMux Capture Volume", 0x19, 0x0, HDA_OUTPUT), | ||
415 | HDA_CODEC_VOLUME("InVol Capture Volume", 0x1b, 0x0, HDA_INPUT), | ||
416 | HDA_CODEC_MUTE("ADCMux Capture Switch", 0x1d, 0x0, HDA_OUTPUT), | ||
417 | { } /* end */ | 533 | { } /* end */ |
418 | }; | 534 | }; |
419 | 535 | ||
@@ -451,12 +567,145 @@ static unsigned int ref9200_pin_configs[8] = { | |||
451 | 0x02a19020, 0x01a19021, 0x90100140, 0x01813122, | 567 | 0x02a19020, 0x01a19021, 0x90100140, 0x01813122, |
452 | }; | 568 | }; |
453 | 569 | ||
570 | /* | ||
571 | STAC 9200 pin configs for | ||
572 | 102801A8 | ||
573 | 102801DE | ||
574 | 102801E8 | ||
575 | */ | ||
576 | static unsigned int dell9200_d21_pin_configs[8] = { | ||
577 | 0x400001f0, 0x400001f1, 0x02214030, 0x01014010, | ||
578 | 0x02a19020, 0x01a19021, 0x90100140, 0x01813122, | ||
579 | }; | ||
580 | |||
581 | /* | ||
582 | STAC 9200 pin configs for | ||
583 | 102801C0 | ||
584 | 102801C1 | ||
585 | */ | ||
586 | static unsigned int dell9200_d22_pin_configs[8] = { | ||
587 | 0x400001f0, 0x400001f1, 0x0221401f, 0x01014010, | ||
588 | 0x01813020, 0x02a19021, 0x90100140, 0x400001f2, | ||
589 | }; | ||
590 | |||
591 | /* | ||
592 | STAC 9200 pin configs for | ||
593 | 102801C4 (Dell Dimension E310) | ||
594 | 102801C5 | ||
595 | 102801C7 | ||
596 | 102801D9 | ||
597 | 102801DA | ||
598 | 102801E3 | ||
599 | */ | ||
600 | static unsigned int dell9200_d23_pin_configs[8] = { | ||
601 | 0x400001f0, 0x400001f1, 0x0221401f, 0x01014010, | ||
602 | 0x01813020, 0x01a19021, 0x90100140, 0x400001f2, | ||
603 | }; | ||
604 | |||
605 | |||
606 | /* | ||
607 | STAC 9200-32 pin configs for | ||
608 | 102801B5 (Dell Inspiron 630m) | ||
609 | 102801D8 (Dell Inspiron 640m) | ||
610 | */ | ||
611 | static unsigned int dell9200_m21_pin_configs[8] = { | ||
612 | 0x40c003fa, 0x03441340, 0x0321121f, 0x90170310, | ||
613 | 0x408003fb, 0x03a11020, 0x401003fc, 0x403003fd, | ||
614 | }; | ||
615 | |||
616 | /* | ||
617 | STAC 9200-32 pin configs for | ||
618 | 102801C2 (Dell Latitude D620) | ||
619 | 102801C8 | ||
620 | 102801CC (Dell Latitude D820) | ||
621 | 102801D4 | ||
622 | 102801D6 | ||
623 | */ | ||
624 | static unsigned int dell9200_m22_pin_configs[8] = { | ||
625 | 0x40c003fa, 0x0144131f, 0x0321121f, 0x90170310, | ||
626 | 0x90a70321, 0x03a11020, 0x401003fb, 0x40f000fc, | ||
627 | }; | ||
628 | |||
629 | /* | ||
630 | STAC 9200-32 pin configs for | ||
631 | 102801CE (Dell XPS M1710) | ||
632 | 102801CF (Dell Precision M90) | ||
633 | */ | ||
634 | static unsigned int dell9200_m23_pin_configs[8] = { | ||
635 | 0x40c003fa, 0x01441340, 0x0421421f, 0x90170310, | ||
636 | 0x408003fb, 0x04a1102e, 0x90170311, 0x403003fc, | ||
637 | }; | ||
638 | |||
639 | /* | ||
640 | STAC 9200-32 pin configs for | ||
641 | 102801C9 | ||
642 | 102801CA | ||
643 | 102801CB (Dell Latitude 120L) | ||
644 | 102801D3 | ||
645 | */ | ||
646 | static unsigned int dell9200_m24_pin_configs[8] = { | ||
647 | 0x40c003fa, 0x404003fb, 0x0321121f, 0x90170310, | ||
648 | 0x408003fc, 0x03a11020, 0x401003fd, 0x403003fe, | ||
649 | }; | ||
650 | |||
651 | /* | ||
652 | STAC 9200-32 pin configs for | ||
653 | 102801BD (Dell Inspiron E1505n) | ||
654 | 102801EE | ||
655 | 102801EF | ||
656 | */ | ||
657 | static unsigned int dell9200_m25_pin_configs[8] = { | ||
658 | 0x40c003fa, 0x01441340, 0x0421121f, 0x90170310, | ||
659 | 0x408003fb, 0x04a11020, 0x401003fc, 0x403003fd, | ||
660 | }; | ||
661 | |||
662 | /* | ||
663 | STAC 9200-32 pin configs for | ||
664 | 102801F5 (Dell Inspiron 1501) | ||
665 | 102801F6 | ||
666 | */ | ||
667 | static unsigned int dell9200_m26_pin_configs[8] = { | ||
668 | 0x40c003fa, 0x404003fb, 0x0421121f, 0x90170310, | ||
669 | 0x408003fc, 0x04a11020, 0x401003fd, 0x403003fe, | ||
670 | }; | ||
671 | |||
672 | /* | ||
673 | STAC 9200-32 | ||
674 | 102801CD (Dell Inspiron E1705/9400) | ||
675 | */ | ||
676 | static unsigned int dell9200_m27_pin_configs[8] = { | ||
677 | 0x40c003fa, 0x01441340, 0x0421121f, 0x90170310, | ||
678 | 0x90170310, 0x04a11020, 0x90170310, 0x40f003fc, | ||
679 | }; | ||
680 | |||
681 | |||
454 | static unsigned int *stac9200_brd_tbl[STAC_9200_MODELS] = { | 682 | static unsigned int *stac9200_brd_tbl[STAC_9200_MODELS] = { |
455 | [STAC_REF] = ref9200_pin_configs, | 683 | [STAC_REF] = ref9200_pin_configs, |
684 | [STAC_9200_DELL_D21] = dell9200_d21_pin_configs, | ||
685 | [STAC_9200_DELL_D22] = dell9200_d22_pin_configs, | ||
686 | [STAC_9200_DELL_D23] = dell9200_d23_pin_configs, | ||
687 | [STAC_9200_DELL_M21] = dell9200_m21_pin_configs, | ||
688 | [STAC_9200_DELL_M22] = dell9200_m22_pin_configs, | ||
689 | [STAC_9200_DELL_M23] = dell9200_m23_pin_configs, | ||
690 | [STAC_9200_DELL_M24] = dell9200_m24_pin_configs, | ||
691 | [STAC_9200_DELL_M25] = dell9200_m25_pin_configs, | ||
692 | [STAC_9200_DELL_M26] = dell9200_m26_pin_configs, | ||
693 | [STAC_9200_DELL_M27] = dell9200_m27_pin_configs, | ||
456 | }; | 694 | }; |
457 | 695 | ||
458 | static const char *stac9200_models[STAC_9200_MODELS] = { | 696 | static const char *stac9200_models[STAC_9200_MODELS] = { |
459 | [STAC_REF] = "ref", | 697 | [STAC_REF] = "ref", |
698 | [STAC_9200_DELL_D21] = "dell-d21", | ||
699 | [STAC_9200_DELL_D22] = "dell-d22", | ||
700 | [STAC_9200_DELL_D23] = "dell-d23", | ||
701 | [STAC_9200_DELL_M21] = "dell-m21", | ||
702 | [STAC_9200_DELL_M22] = "dell-m22", | ||
703 | [STAC_9200_DELL_M23] = "dell-m23", | ||
704 | [STAC_9200_DELL_M24] = "dell-m24", | ||
705 | [STAC_9200_DELL_M25] = "dell-m25", | ||
706 | [STAC_9200_DELL_M26] = "dell-m26", | ||
707 | [STAC_9200_DELL_M27] = "dell-m27", | ||
708 | [STAC_9200_GATEWAY] = "gateway", | ||
460 | }; | 709 | }; |
461 | 710 | ||
462 | static struct snd_pci_quirk stac9200_cfg_tbl[] = { | 711 | static struct snd_pci_quirk stac9200_cfg_tbl[] = { |
@@ -464,30 +713,72 @@ static struct snd_pci_quirk stac9200_cfg_tbl[] = { | |||
464 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, | 713 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, |
465 | "DFI LanParty", STAC_REF), | 714 | "DFI LanParty", STAC_REF), |
466 | /* Dell laptops have BIOS problem */ | 715 | /* Dell laptops have BIOS problem */ |
716 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01a8, | ||
717 | "unknown Dell", STAC_9200_DELL_D21), | ||
467 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01b5, | 718 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01b5, |
468 | "Dell Inspiron 630m", STAC_REF), | 719 | "Dell Inspiron 630m", STAC_9200_DELL_M21), |
720 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01bd, | ||
721 | "Dell Inspiron E1505n", STAC_9200_DELL_M25), | ||
722 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c0, | ||
723 | "unknown Dell", STAC_9200_DELL_D22), | ||
724 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c1, | ||
725 | "unknown Dell", STAC_9200_DELL_D22), | ||
469 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c2, | 726 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c2, |
470 | "Dell Latitude D620", STAC_REF), | 727 | "Dell Latitude D620", STAC_9200_DELL_M22), |
728 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c5, | ||
729 | "unknown Dell", STAC_9200_DELL_D23), | ||
730 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c7, | ||
731 | "unknown Dell", STAC_9200_DELL_D23), | ||
732 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c8, | ||
733 | "unknown Dell", STAC_9200_DELL_M22), | ||
734 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c9, | ||
735 | "unknown Dell", STAC_9200_DELL_M24), | ||
736 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ca, | ||
737 | "unknown Dell", STAC_9200_DELL_M24), | ||
471 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cb, | 738 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cb, |
472 | "Dell Latitude 120L", STAC_REF), | 739 | "Dell Latitude 120L", STAC_9200_DELL_M24), |
473 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cc, | 740 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cc, |
474 | "Dell Latitude D820", STAC_REF), | 741 | "Dell Latitude D820", STAC_9200_DELL_M22), |
475 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cd, | 742 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cd, |
476 | "Dell Inspiron E1705/9400", STAC_REF), | 743 | "Dell Inspiron E1705/9400", STAC_9200_DELL_M27), |
477 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ce, | 744 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ce, |
478 | "Dell XPS M1710", STAC_REF), | 745 | "Dell XPS M1710", STAC_9200_DELL_M23), |
479 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cf, | 746 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cf, |
480 | "Dell Precision M90", STAC_REF), | 747 | "Dell Precision M90", STAC_9200_DELL_M23), |
748 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d3, | ||
749 | "unknown Dell", STAC_9200_DELL_M22), | ||
750 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d4, | ||
751 | "unknown Dell", STAC_9200_DELL_M22), | ||
481 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d6, | 752 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d6, |
482 | "unknown Dell", STAC_REF), | 753 | "unknown Dell", STAC_9200_DELL_M22), |
483 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d8, | 754 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d8, |
484 | "Dell Inspiron 640m", STAC_REF), | 755 | "Dell Inspiron 640m", STAC_9200_DELL_M21), |
756 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d9, | ||
757 | "unknown Dell", STAC_9200_DELL_D23), | ||
758 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01da, | ||
759 | "unknown Dell", STAC_9200_DELL_D23), | ||
760 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01de, | ||
761 | "unknown Dell", STAC_9200_DELL_D21), | ||
762 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01e3, | ||
763 | "unknown Dell", STAC_9200_DELL_D23), | ||
764 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01e8, | ||
765 | "unknown Dell", STAC_9200_DELL_D21), | ||
766 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ee, | ||
767 | "unknown Dell", STAC_9200_DELL_M25), | ||
768 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ef, | ||
769 | "unknown Dell", STAC_9200_DELL_M25), | ||
485 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f5, | 770 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f5, |
486 | "Dell Inspiron 1501", STAC_REF), | 771 | "Dell Inspiron 1501", STAC_9200_DELL_M26), |
487 | 772 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f6, | |
773 | "unknown Dell", STAC_9200_DELL_M26), | ||
488 | /* Panasonic */ | 774 | /* Panasonic */ |
489 | SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-74", STAC_REF), | 775 | SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-74", STAC_REF), |
490 | 776 | /* Gateway machines needs EAPD to be set on resume */ | |
777 | SND_PCI_QUIRK(0x107b, 0x0205, "Gateway S-7110M", STAC_9200_GATEWAY), | ||
778 | SND_PCI_QUIRK(0x107b, 0x0317, "Gateway MT3423, MX341*", | ||
779 | STAC_9200_GATEWAY), | ||
780 | SND_PCI_QUIRK(0x107b, 0x0318, "Gateway ML3019, MT3707", | ||
781 | STAC_9200_GATEWAY), | ||
491 | {} /* terminator */ | 782 | {} /* terminator */ |
492 | }; | 783 | }; |
493 | 784 | ||
@@ -543,6 +834,51 @@ static unsigned int ref922x_pin_configs[10] = { | |||
543 | 0x40000100, 0x40000100, | 834 | 0x40000100, 0x40000100, |
544 | }; | 835 | }; |
545 | 836 | ||
837 | /* | ||
838 | STAC 922X pin configs for | ||
839 | 102801A7 | ||
840 | 102801AB | ||
841 | 102801A9 | ||
842 | 102801D1 | ||
843 | 102801D2 | ||
844 | */ | ||
845 | static unsigned int dell_922x_d81_pin_configs[10] = { | ||
846 | 0x02214030, 0x01a19021, 0x01111012, 0x01114010, | ||
847 | 0x02a19020, 0x01117011, 0x400001f0, 0x400001f1, | ||
848 | 0x01813122, 0x400001f2, | ||
849 | }; | ||
850 | |||
851 | /* | ||
852 | STAC 922X pin configs for | ||
853 | 102801AC | ||
854 | 102801D0 | ||
855 | */ | ||
856 | static unsigned int dell_922x_d82_pin_configs[10] = { | ||
857 | 0x02214030, 0x01a19021, 0x01111012, 0x01114010, | ||
858 | 0x02a19020, 0x01117011, 0x01451140, 0x400001f0, | ||
859 | 0x01813122, 0x400001f1, | ||
860 | }; | ||
861 | |||
862 | /* | ||
863 | STAC 922X pin configs for | ||
864 | 102801BF | ||
865 | */ | ||
866 | static unsigned int dell_922x_m81_pin_configs[10] = { | ||
867 | 0x0321101f, 0x01112024, 0x01111222, 0x91174220, | ||
868 | 0x03a11050, 0x01116221, 0x90a70330, 0x01452340, | ||
869 | 0x40C003f1, 0x405003f0, | ||
870 | }; | ||
871 | |||
872 | /* | ||
873 | STAC 9221 A1 pin configs for | ||
874 | 102801D7 (Dell XPS M1210) | ||
875 | */ | ||
876 | static unsigned int dell_922x_m82_pin_configs[10] = { | ||
877 | 0x0221121f, 0x408103ff, 0x02111212, 0x90100310, | ||
878 | 0x408003f1, 0x02111211, 0x03451340, 0x40c003f2, | ||
879 | 0x508003f3, 0x405003f4, | ||
880 | }; | ||
881 | |||
546 | static unsigned int d945gtp3_pin_configs[10] = { | 882 | static unsigned int d945gtp3_pin_configs[10] = { |
547 | 0x0221401f, 0x01a19022, 0x01813021, 0x01014010, | 883 | 0x0221401f, 0x01a19022, 0x01813021, 0x01014010, |
548 | 0x40000100, 0x40000100, 0x40000100, 0x40000100, | 884 | 0x40000100, 0x40000100, 0x40000100, 0x40000100, |
@@ -585,48 +921,49 @@ static unsigned int intel_mac_v5_pin_configs[10] = { | |||
585 | 0x400000fc, 0x400000fb, | 921 | 0x400000fc, 0x400000fb, |
586 | }; | 922 | }; |
587 | 923 | ||
588 | static unsigned int stac922x_dell_pin_configs[10] = { | ||
589 | 0x0221121e, 0x408103ff, 0x02a1123e, 0x90100310, | ||
590 | 0x408003f1, 0x0221122f, 0x03451340, 0x40c003f2, | ||
591 | 0x50a003f3, 0x405003f4 | ||
592 | }; | ||
593 | 924 | ||
594 | static unsigned int *stac922x_brd_tbl[STAC_922X_MODELS] = { | 925 | static unsigned int *stac922x_brd_tbl[STAC_922X_MODELS] = { |
595 | [STAC_D945_REF] = ref922x_pin_configs, | 926 | [STAC_D945_REF] = ref922x_pin_configs, |
596 | [STAC_D945GTP3] = d945gtp3_pin_configs, | 927 | [STAC_D945GTP3] = d945gtp3_pin_configs, |
597 | [STAC_D945GTP5] = d945gtp5_pin_configs, | 928 | [STAC_D945GTP5] = d945gtp5_pin_configs, |
598 | [STAC_922X_DELL] = stac922x_dell_pin_configs, | ||
599 | [STAC_INTEL_MAC_V1] = intel_mac_v1_pin_configs, | 929 | [STAC_INTEL_MAC_V1] = intel_mac_v1_pin_configs, |
600 | [STAC_INTEL_MAC_V2] = intel_mac_v2_pin_configs, | 930 | [STAC_INTEL_MAC_V2] = intel_mac_v2_pin_configs, |
601 | [STAC_INTEL_MAC_V3] = intel_mac_v3_pin_configs, | 931 | [STAC_INTEL_MAC_V3] = intel_mac_v3_pin_configs, |
602 | [STAC_INTEL_MAC_V4] = intel_mac_v4_pin_configs, | 932 | [STAC_INTEL_MAC_V4] = intel_mac_v4_pin_configs, |
603 | [STAC_INTEL_MAC_V5] = intel_mac_v5_pin_configs, | 933 | [STAC_INTEL_MAC_V5] = intel_mac_v5_pin_configs, |
604 | /* for backward compitability */ | 934 | /* for backward compatibility */ |
605 | [STAC_MACMINI] = intel_mac_v3_pin_configs, | 935 | [STAC_MACMINI] = intel_mac_v3_pin_configs, |
606 | [STAC_MACBOOK] = intel_mac_v5_pin_configs, | 936 | [STAC_MACBOOK] = intel_mac_v5_pin_configs, |
607 | [STAC_MACBOOK_PRO_V1] = intel_mac_v3_pin_configs, | 937 | [STAC_MACBOOK_PRO_V1] = intel_mac_v3_pin_configs, |
608 | [STAC_MACBOOK_PRO_V2] = intel_mac_v3_pin_configs, | 938 | [STAC_MACBOOK_PRO_V2] = intel_mac_v3_pin_configs, |
609 | [STAC_IMAC_INTEL] = intel_mac_v2_pin_configs, | 939 | [STAC_IMAC_INTEL] = intel_mac_v2_pin_configs, |
610 | [STAC_IMAC_INTEL_20] = intel_mac_v3_pin_configs, | 940 | [STAC_IMAC_INTEL_20] = intel_mac_v3_pin_configs, |
941 | [STAC_922X_DELL_D81] = dell_922x_d81_pin_configs, | ||
942 | [STAC_922X_DELL_D82] = dell_922x_d82_pin_configs, | ||
943 | [STAC_922X_DELL_M81] = dell_922x_m81_pin_configs, | ||
944 | [STAC_922X_DELL_M82] = dell_922x_m82_pin_configs, | ||
611 | }; | 945 | }; |
612 | 946 | ||
613 | static const char *stac922x_models[STAC_922X_MODELS] = { | 947 | static const char *stac922x_models[STAC_922X_MODELS] = { |
614 | [STAC_D945_REF] = "ref", | 948 | [STAC_D945_REF] = "ref", |
615 | [STAC_D945GTP5] = "5stack", | 949 | [STAC_D945GTP5] = "5stack", |
616 | [STAC_D945GTP3] = "3stack", | 950 | [STAC_D945GTP3] = "3stack", |
617 | [STAC_922X_DELL] = "dell", | ||
618 | [STAC_INTEL_MAC_V1] = "intel-mac-v1", | 951 | [STAC_INTEL_MAC_V1] = "intel-mac-v1", |
619 | [STAC_INTEL_MAC_V2] = "intel-mac-v2", | 952 | [STAC_INTEL_MAC_V2] = "intel-mac-v2", |
620 | [STAC_INTEL_MAC_V3] = "intel-mac-v3", | 953 | [STAC_INTEL_MAC_V3] = "intel-mac-v3", |
621 | [STAC_INTEL_MAC_V4] = "intel-mac-v4", | 954 | [STAC_INTEL_MAC_V4] = "intel-mac-v4", |
622 | [STAC_INTEL_MAC_V5] = "intel-mac-v5", | 955 | [STAC_INTEL_MAC_V5] = "intel-mac-v5", |
623 | /* for backward compitability */ | 956 | /* for backward compatibility */ |
624 | [STAC_MACMINI] = "macmini", | 957 | [STAC_MACMINI] = "macmini", |
625 | [STAC_MACBOOK] = "macbook", | 958 | [STAC_MACBOOK] = "macbook", |
626 | [STAC_MACBOOK_PRO_V1] = "macbook-pro-v1", | 959 | [STAC_MACBOOK_PRO_V1] = "macbook-pro-v1", |
627 | [STAC_MACBOOK_PRO_V2] = "macbook-pro", | 960 | [STAC_MACBOOK_PRO_V2] = "macbook-pro", |
628 | [STAC_IMAC_INTEL] = "imac-intel", | 961 | [STAC_IMAC_INTEL] = "imac-intel", |
629 | [STAC_IMAC_INTEL_20] = "imac-intel-20", | 962 | [STAC_IMAC_INTEL_20] = "imac-intel-20", |
963 | [STAC_922X_DELL_D81] = "dell-d81", | ||
964 | [STAC_922X_DELL_D82] = "dell-d82", | ||
965 | [STAC_922X_DELL_M81] = "dell-m81", | ||
966 | [STAC_922X_DELL_M82] = "dell-m82", | ||
630 | }; | 967 | }; |
631 | 968 | ||
632 | static struct snd_pci_quirk stac922x_cfg_tbl[] = { | 969 | static struct snd_pci_quirk stac922x_cfg_tbl[] = { |
@@ -690,9 +1027,25 @@ static struct snd_pci_quirk stac922x_cfg_tbl[] = { | |||
690 | /* Apple Mac Mini (early 2006) */ | 1027 | /* Apple Mac Mini (early 2006) */ |
691 | SND_PCI_QUIRK(0x8384, 0x7680, | 1028 | SND_PCI_QUIRK(0x8384, 0x7680, |
692 | "Mac Mini", STAC_INTEL_MAC_V3), | 1029 | "Mac Mini", STAC_INTEL_MAC_V3), |
693 | /* Dell */ | 1030 | /* Dell systems */ |
694 | SND_PCI_QUIRK(0x1028, 0x01d7, "Dell XPS M1210", STAC_922X_DELL), | 1031 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01a7, |
695 | 1032 | "unknown Dell", STAC_922X_DELL_D81), | |
1033 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01a9, | ||
1034 | "unknown Dell", STAC_922X_DELL_D81), | ||
1035 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ab, | ||
1036 | "unknown Dell", STAC_922X_DELL_D81), | ||
1037 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ac, | ||
1038 | "unknown Dell", STAC_922X_DELL_D82), | ||
1039 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01bf, | ||
1040 | "unknown Dell", STAC_922X_DELL_M81), | ||
1041 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d0, | ||
1042 | "unknown Dell", STAC_922X_DELL_D82), | ||
1043 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d1, | ||
1044 | "unknown Dell", STAC_922X_DELL_D81), | ||
1045 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d2, | ||
1046 | "unknown Dell", STAC_922X_DELL_D81), | ||
1047 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d7, | ||
1048 | "Dell XPS M1210", STAC_922X_DELL_M82), | ||
696 | {} /* terminator */ | 1049 | {} /* terminator */ |
697 | }; | 1050 | }; |
698 | 1051 | ||
@@ -717,16 +1070,25 @@ static unsigned int d965_5st_pin_configs[14] = { | |||
717 | 0x40000100, 0x40000100 | 1070 | 0x40000100, 0x40000100 |
718 | }; | 1071 | }; |
719 | 1072 | ||
1073 | static unsigned int dell_3st_pin_configs[14] = { | ||
1074 | 0x02211230, 0x02a11220, 0x01a19040, 0x01114210, | ||
1075 | 0x01111212, 0x01116211, 0x01813050, 0x01112214, | ||
1076 | 0x403003fa, 0x40000100, 0x40000100, 0x404003fb, | ||
1077 | 0x40c003fc, 0x40000100 | ||
1078 | }; | ||
1079 | |||
720 | static unsigned int *stac927x_brd_tbl[STAC_927X_MODELS] = { | 1080 | static unsigned int *stac927x_brd_tbl[STAC_927X_MODELS] = { |
721 | [STAC_D965_REF] = ref927x_pin_configs, | 1081 | [STAC_D965_REF] = ref927x_pin_configs, |
722 | [STAC_D965_3ST] = d965_3st_pin_configs, | 1082 | [STAC_D965_3ST] = d965_3st_pin_configs, |
723 | [STAC_D965_5ST] = d965_5st_pin_configs, | 1083 | [STAC_D965_5ST] = d965_5st_pin_configs, |
1084 | [STAC_DELL_3ST] = dell_3st_pin_configs, | ||
724 | }; | 1085 | }; |
725 | 1086 | ||
726 | static const char *stac927x_models[STAC_927X_MODELS] = { | 1087 | static const char *stac927x_models[STAC_927X_MODELS] = { |
727 | [STAC_D965_REF] = "ref", | 1088 | [STAC_D965_REF] = "ref", |
728 | [STAC_D965_3ST] = "3stack", | 1089 | [STAC_D965_3ST] = "3stack", |
729 | [STAC_D965_5ST] = "5stack", | 1090 | [STAC_D965_5ST] = "5stack", |
1091 | [STAC_DELL_3ST] = "dell-3stack", | ||
730 | }; | 1092 | }; |
731 | 1093 | ||
732 | static struct snd_pci_quirk stac927x_cfg_tbl[] = { | 1094 | static struct snd_pci_quirk stac927x_cfg_tbl[] = { |
@@ -753,7 +1115,13 @@ static struct snd_pci_quirk stac927x_cfg_tbl[] = { | |||
753 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2003, "Intel D965", STAC_D965_3ST), | 1115 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2003, "Intel D965", STAC_D965_3ST), |
754 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2002, "Intel D965", STAC_D965_3ST), | 1116 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2002, "Intel D965", STAC_D965_3ST), |
755 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2001, "Intel D965", STAC_D965_3ST), | 1117 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2001, "Intel D965", STAC_D965_3ST), |
1118 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f3, "Dell Inspiron 1420", STAC_D965_3ST), | ||
1119 | /* Dell 3 stack systems */ | ||
1120 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01dd, "Dell Dimension E520", STAC_DELL_3ST), | ||
1121 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ed, "Dell ", STAC_DELL_3ST), | ||
1122 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f4, "Dell ", STAC_DELL_3ST), | ||
756 | /* 965 based 5 stack systems */ | 1123 | /* 965 based 5 stack systems */ |
1124 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0209, "Dell XPS 1330", STAC_D965_5ST), | ||
757 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2301, "Intel D965", STAC_D965_5ST), | 1125 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2301, "Intel D965", STAC_D965_5ST), |
758 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2302, "Intel D965", STAC_D965_5ST), | 1126 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2302, "Intel D965", STAC_D965_5ST), |
759 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2303, "Intel D965", STAC_D965_5ST), | 1127 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2303, "Intel D965", STAC_D965_5ST), |
@@ -772,23 +1140,97 @@ static unsigned int ref9205_pin_configs[12] = { | |||
772 | 0x90a000f0, 0x90a000f0, 0x01441030, 0x01c41030 | 1140 | 0x90a000f0, 0x90a000f0, 0x01441030, 0x01c41030 |
773 | }; | 1141 | }; |
774 | 1142 | ||
1143 | /* | ||
1144 | STAC 9205 pin configs for | ||
1145 | 102801F1 | ||
1146 | 102801F2 | ||
1147 | 102801FC | ||
1148 | 102801FD | ||
1149 | 10280204 | ||
1150 | 1028021F | ||
1151 | */ | ||
1152 | static unsigned int dell_9205_m42_pin_configs[12] = { | ||
1153 | 0x0321101F, 0x03A11020, 0x400003FA, 0x90170310, | ||
1154 | 0x400003FB, 0x400003FC, 0x400003FD, 0x40F000F9, | ||
1155 | 0x90A60330, 0x400003FF, 0x0144131F, 0x40C003FE, | ||
1156 | }; | ||
1157 | |||
1158 | /* | ||
1159 | STAC 9205 pin configs for | ||
1160 | 102801F9 | ||
1161 | 102801FA | ||
1162 | 102801FE | ||
1163 | 102801FF (Dell Precision M4300) | ||
1164 | 10280206 | ||
1165 | 10280200 | ||
1166 | 10280201 | ||
1167 | */ | ||
1168 | static unsigned int dell_9205_m43_pin_configs[12] = { | ||
1169 | 0x0321101f, 0x03a11020, 0x90a70330, 0x90170310, | ||
1170 | 0x400000fe, 0x400000ff, 0x400000fd, 0x40f000f9, | ||
1171 | 0x400000fa, 0x400000fc, 0x0144131f, 0x40c003f8, | ||
1172 | }; | ||
1173 | |||
1174 | static unsigned int dell_9205_m44_pin_configs[12] = { | ||
1175 | 0x0421101f, 0x04a11020, 0x400003fa, 0x90170310, | ||
1176 | 0x400003fb, 0x400003fc, 0x400003fd, 0x400003f9, | ||
1177 | 0x90a60330, 0x400003ff, 0x01441340, 0x40c003fe, | ||
1178 | }; | ||
1179 | |||
775 | static unsigned int *stac9205_brd_tbl[STAC_9205_MODELS] = { | 1180 | static unsigned int *stac9205_brd_tbl[STAC_9205_MODELS] = { |
776 | [STAC_REF] = ref9205_pin_configs, | 1181 | [STAC_9205_REF] = ref9205_pin_configs, |
777 | [STAC_M43xx] = NULL, | 1182 | [STAC_9205_DELL_M42] = dell_9205_m42_pin_configs, |
1183 | [STAC_9205_DELL_M43] = dell_9205_m43_pin_configs, | ||
1184 | [STAC_9205_DELL_M44] = dell_9205_m44_pin_configs, | ||
778 | }; | 1185 | }; |
779 | 1186 | ||
780 | static const char *stac9205_models[STAC_9205_MODELS] = { | 1187 | static const char *stac9205_models[STAC_9205_MODELS] = { |
781 | [STAC_9205_REF] = "ref", | 1188 | [STAC_9205_REF] = "ref", |
1189 | [STAC_9205_DELL_M42] = "dell-m42", | ||
1190 | [STAC_9205_DELL_M43] = "dell-m43", | ||
1191 | [STAC_9205_DELL_M44] = "dell-m44", | ||
782 | }; | 1192 | }; |
783 | 1193 | ||
784 | static struct snd_pci_quirk stac9205_cfg_tbl[] = { | 1194 | static struct snd_pci_quirk stac9205_cfg_tbl[] = { |
785 | /* SigmaTel reference board */ | 1195 | /* SigmaTel reference board */ |
786 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, | 1196 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, |
787 | "DFI LanParty", STAC_9205_REF), | 1197 | "DFI LanParty", STAC_9205_REF), |
788 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x01f8, | 1198 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f1, |
789 | "Dell Precision", STAC_M43xx), | 1199 | "unknown Dell", STAC_9205_DELL_M42), |
790 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x01ff, | 1200 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f2, |
791 | "Dell Precision", STAC_M43xx), | 1201 | "unknown Dell", STAC_9205_DELL_M42), |
1202 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f8, | ||
1203 | "Dell Precision", STAC_9205_DELL_M43), | ||
1204 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021c, | ||
1205 | "Dell Precision", STAC_9205_DELL_M43), | ||
1206 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f9, | ||
1207 | "Dell Precision", STAC_9205_DELL_M43), | ||
1208 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021b, | ||
1209 | "Dell Precision", STAC_9205_DELL_M43), | ||
1210 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fa, | ||
1211 | "Dell Precision", STAC_9205_DELL_M43), | ||
1212 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fc, | ||
1213 | "unknown Dell", STAC_9205_DELL_M42), | ||
1214 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fd, | ||
1215 | "unknown Dell", STAC_9205_DELL_M42), | ||
1216 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fe, | ||
1217 | "Dell Precision", STAC_9205_DELL_M43), | ||
1218 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ff, | ||
1219 | "Dell Precision M4300", STAC_9205_DELL_M43), | ||
1220 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0206, | ||
1221 | "Dell Precision", STAC_9205_DELL_M43), | ||
1222 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f1, | ||
1223 | "Dell Inspiron", STAC_9205_DELL_M44), | ||
1224 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f2, | ||
1225 | "Dell Inspiron", STAC_9205_DELL_M44), | ||
1226 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fc, | ||
1227 | "Dell Inspiron", STAC_9205_DELL_M44), | ||
1228 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fd, | ||
1229 | "Dell Inspiron", STAC_9205_DELL_M44), | ||
1230 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0204, | ||
1231 | "unknown Dell", STAC_9205_DELL_M42), | ||
1232 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021f, | ||
1233 | "Dell Inspiron", STAC_9205_DELL_M44), | ||
792 | {} /* terminator */ | 1234 | {} /* terminator */ |
793 | }; | 1235 | }; |
794 | 1236 | ||
@@ -854,20 +1296,20 @@ static void stac92xx_set_config_regs(struct hda_codec *codec) | |||
854 | spec->pin_configs[i]); | 1296 | spec->pin_configs[i]); |
855 | } | 1297 | } |
856 | 1298 | ||
857 | static void stac92xx_enable_gpio_mask(struct hda_codec *codec, | 1299 | static void stac92xx_enable_gpio_mask(struct hda_codec *codec) |
858 | int gpio_mask, int gpio_data) | ||
859 | { | 1300 | { |
1301 | struct sigmatel_spec *spec = codec->spec; | ||
860 | /* Configure GPIOx as output */ | 1302 | /* Configure GPIOx as output */ |
861 | snd_hda_codec_write(codec, codec->afg, 0, | 1303 | snd_hda_codec_write_cache(codec, codec->afg, 0, |
862 | AC_VERB_SET_GPIO_DIRECTION, gpio_mask); | 1304 | AC_VERB_SET_GPIO_DIRECTION, spec->gpio_mask); |
863 | /* Configure GPIOx as CMOS */ | 1305 | /* Configure GPIOx as CMOS */ |
864 | snd_hda_codec_write(codec, codec->afg, 0, 0x7e7, 0x00000000); | 1306 | snd_hda_codec_write_cache(codec, codec->afg, 0, 0x7e7, 0x00000000); |
865 | /* Assert GPIOx */ | 1307 | /* Assert GPIOx */ |
866 | snd_hda_codec_write(codec, codec->afg, 0, | 1308 | snd_hda_codec_write_cache(codec, codec->afg, 0, |
867 | AC_VERB_SET_GPIO_DATA, gpio_data); | 1309 | AC_VERB_SET_GPIO_DATA, spec->gpio_data); |
868 | /* Enable GPIOx */ | 1310 | /* Enable GPIOx */ |
869 | snd_hda_codec_write(codec, codec->afg, 0, | 1311 | snd_hda_codec_write_cache(codec, codec->afg, 0, |
870 | AC_VERB_SET_GPIO_MASK, gpio_mask); | 1312 | AC_VERB_SET_GPIO_MASK, spec->gpio_mask); |
871 | } | 1313 | } |
872 | 1314 | ||
873 | /* | 1315 | /* |
@@ -1000,10 +1442,9 @@ static struct hda_pcm_stream stac92xx_pcm_analog_alt_playback = { | |||
1000 | }; | 1442 | }; |
1001 | 1443 | ||
1002 | static struct hda_pcm_stream stac92xx_pcm_analog_capture = { | 1444 | static struct hda_pcm_stream stac92xx_pcm_analog_capture = { |
1003 | .substreams = 2, | ||
1004 | .channels_min = 2, | 1445 | .channels_min = 2, |
1005 | .channels_max = 2, | 1446 | .channels_max = 2, |
1006 | /* NID is set in stac92xx_build_pcms */ | 1447 | /* NID + .substreams is set in stac92xx_build_pcms */ |
1007 | .ops = { | 1448 | .ops = { |
1008 | .prepare = stac92xx_capture_pcm_prepare, | 1449 | .prepare = stac92xx_capture_pcm_prepare, |
1009 | .cleanup = stac92xx_capture_pcm_cleanup | 1450 | .cleanup = stac92xx_capture_pcm_cleanup |
@@ -1022,6 +1463,7 @@ static int stac92xx_build_pcms(struct hda_codec *codec) | |||
1022 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_analog_playback; | 1463 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_analog_playback; |
1023 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = stac92xx_pcm_analog_capture; | 1464 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = stac92xx_pcm_analog_capture; |
1024 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0]; | 1465 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0]; |
1466 | info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adcs; | ||
1025 | 1467 | ||
1026 | if (spec->alt_switch) { | 1468 | if (spec->alt_switch) { |
1027 | codec->num_pcms++; | 1469 | codec->num_pcms++; |
@@ -1066,17 +1508,11 @@ static unsigned int stac92xx_get_vref(struct hda_codec *codec, hda_nid_t nid) | |||
1066 | static void stac92xx_auto_set_pinctl(struct hda_codec *codec, hda_nid_t nid, int pin_type) | 1508 | static void stac92xx_auto_set_pinctl(struct hda_codec *codec, hda_nid_t nid, int pin_type) |
1067 | 1509 | ||
1068 | { | 1510 | { |
1069 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type); | 1511 | snd_hda_codec_write_cache(codec, nid, 0, |
1512 | AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type); | ||
1070 | } | 1513 | } |
1071 | 1514 | ||
1072 | static int stac92xx_io_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1515 | #define stac92xx_io_switch_info snd_ctl_boolean_mono_info |
1073 | { | ||
1074 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1075 | uinfo->count = 1; | ||
1076 | uinfo->value.integer.min = 0; | ||
1077 | uinfo->value.integer.max = 1; | ||
1078 | return 0; | ||
1079 | } | ||
1080 | 1516 | ||
1081 | static int stac92xx_io_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1517 | static int stac92xx_io_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1082 | { | 1518 | { |
@@ -1109,6 +1545,36 @@ static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
1109 | return 1; | 1545 | return 1; |
1110 | } | 1546 | } |
1111 | 1547 | ||
1548 | #define stac92xx_clfe_switch_info snd_ctl_boolean_mono_info | ||
1549 | |||
1550 | static int stac92xx_clfe_switch_get(struct snd_kcontrol *kcontrol, | ||
1551 | struct snd_ctl_elem_value *ucontrol) | ||
1552 | { | ||
1553 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1554 | struct sigmatel_spec *spec = codec->spec; | ||
1555 | |||
1556 | ucontrol->value.integer.value[0] = spec->clfe_swap; | ||
1557 | return 0; | ||
1558 | } | ||
1559 | |||
1560 | static int stac92xx_clfe_switch_put(struct snd_kcontrol *kcontrol, | ||
1561 | struct snd_ctl_elem_value *ucontrol) | ||
1562 | { | ||
1563 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1564 | struct sigmatel_spec *spec = codec->spec; | ||
1565 | hda_nid_t nid = kcontrol->private_value & 0xff; | ||
1566 | |||
1567 | if (spec->clfe_swap == ucontrol->value.integer.value[0]) | ||
1568 | return 0; | ||
1569 | |||
1570 | spec->clfe_swap = ucontrol->value.integer.value[0]; | ||
1571 | |||
1572 | snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE, | ||
1573 | spec->clfe_swap ? 0x4 : 0x0); | ||
1574 | |||
1575 | return 1; | ||
1576 | } | ||
1577 | |||
1112 | #define STAC_CODEC_IO_SWITCH(xname, xpval) \ | 1578 | #define STAC_CODEC_IO_SWITCH(xname, xpval) \ |
1113 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 1579 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
1114 | .name = xname, \ | 1580 | .name = xname, \ |
@@ -1119,17 +1585,28 @@ static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
1119 | .private_value = xpval, \ | 1585 | .private_value = xpval, \ |
1120 | } | 1586 | } |
1121 | 1587 | ||
1588 | #define STAC_CODEC_CLFE_SWITCH(xname, xpval) \ | ||
1589 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
1590 | .name = xname, \ | ||
1591 | .index = 0, \ | ||
1592 | .info = stac92xx_clfe_switch_info, \ | ||
1593 | .get = stac92xx_clfe_switch_get, \ | ||
1594 | .put = stac92xx_clfe_switch_put, \ | ||
1595 | .private_value = xpval, \ | ||
1596 | } | ||
1122 | 1597 | ||
1123 | enum { | 1598 | enum { |
1124 | STAC_CTL_WIDGET_VOL, | 1599 | STAC_CTL_WIDGET_VOL, |
1125 | STAC_CTL_WIDGET_MUTE, | 1600 | STAC_CTL_WIDGET_MUTE, |
1126 | STAC_CTL_WIDGET_IO_SWITCH, | 1601 | STAC_CTL_WIDGET_IO_SWITCH, |
1602 | STAC_CTL_WIDGET_CLFE_SWITCH | ||
1127 | }; | 1603 | }; |
1128 | 1604 | ||
1129 | static struct snd_kcontrol_new stac92xx_control_templates[] = { | 1605 | static struct snd_kcontrol_new stac92xx_control_templates[] = { |
1130 | HDA_CODEC_VOLUME(NULL, 0, 0, 0), | 1606 | HDA_CODEC_VOLUME(NULL, 0, 0, 0), |
1131 | HDA_CODEC_MUTE(NULL, 0, 0, 0), | 1607 | HDA_CODEC_MUTE(NULL, 0, 0, 0), |
1132 | STAC_CODEC_IO_SWITCH(NULL, 0), | 1608 | STAC_CODEC_IO_SWITCH(NULL, 0), |
1609 | STAC_CODEC_CLFE_SWITCH(NULL, 0), | ||
1133 | }; | 1610 | }; |
1134 | 1611 | ||
1135 | /* add dynamic controls */ | 1612 | /* add dynamic controls */ |
@@ -1182,7 +1659,8 @@ static int stac92xx_add_dyn_out_pins(struct hda_codec *codec, struct auto_pin_cf | |||
1182 | case 3: | 1659 | case 3: |
1183 | /* add line-in as side */ | 1660 | /* add line-in as side */ |
1184 | if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 3) { | 1661 | if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 3) { |
1185 | cfg->line_out_pins[3] = cfg->input_pins[AUTO_PIN_LINE]; | 1662 | cfg->line_out_pins[cfg->line_outs] = |
1663 | cfg->input_pins[AUTO_PIN_LINE]; | ||
1186 | spec->line_switch = 1; | 1664 | spec->line_switch = 1; |
1187 | cfg->line_outs++; | 1665 | cfg->line_outs++; |
1188 | } | 1666 | } |
@@ -1190,12 +1668,14 @@ static int stac92xx_add_dyn_out_pins(struct hda_codec *codec, struct auto_pin_cf | |||
1190 | case 2: | 1668 | case 2: |
1191 | /* add line-in as clfe and mic as side */ | 1669 | /* add line-in as clfe and mic as side */ |
1192 | if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 2) { | 1670 | if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 2) { |
1193 | cfg->line_out_pins[2] = cfg->input_pins[AUTO_PIN_LINE]; | 1671 | cfg->line_out_pins[cfg->line_outs] = |
1672 | cfg->input_pins[AUTO_PIN_LINE]; | ||
1194 | spec->line_switch = 1; | 1673 | spec->line_switch = 1; |
1195 | cfg->line_outs++; | 1674 | cfg->line_outs++; |
1196 | } | 1675 | } |
1197 | if (cfg->input_pins[AUTO_PIN_MIC] && num_dacs > 3) { | 1676 | if (cfg->input_pins[AUTO_PIN_MIC] && num_dacs > 3) { |
1198 | cfg->line_out_pins[3] = cfg->input_pins[AUTO_PIN_MIC]; | 1677 | cfg->line_out_pins[cfg->line_outs] = |
1678 | cfg->input_pins[AUTO_PIN_MIC]; | ||
1199 | spec->mic_switch = 1; | 1679 | spec->mic_switch = 1; |
1200 | cfg->line_outs++; | 1680 | cfg->line_outs++; |
1201 | } | 1681 | } |
@@ -1203,12 +1683,14 @@ static int stac92xx_add_dyn_out_pins(struct hda_codec *codec, struct auto_pin_cf | |||
1203 | case 1: | 1683 | case 1: |
1204 | /* add line-in as surr and mic as clfe */ | 1684 | /* add line-in as surr and mic as clfe */ |
1205 | if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 1) { | 1685 | if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 1) { |
1206 | cfg->line_out_pins[1] = cfg->input_pins[AUTO_PIN_LINE]; | 1686 | cfg->line_out_pins[cfg->line_outs] = |
1687 | cfg->input_pins[AUTO_PIN_LINE]; | ||
1207 | spec->line_switch = 1; | 1688 | spec->line_switch = 1; |
1208 | cfg->line_outs++; | 1689 | cfg->line_outs++; |
1209 | } | 1690 | } |
1210 | if (cfg->input_pins[AUTO_PIN_MIC] && num_dacs > 2) { | 1691 | if (cfg->input_pins[AUTO_PIN_MIC] && num_dacs > 2) { |
1211 | cfg->line_out_pins[2] = cfg->input_pins[AUTO_PIN_MIC]; | 1692 | cfg->line_out_pins[cfg->line_outs] = |
1693 | cfg->input_pins[AUTO_PIN_MIC]; | ||
1212 | spec->mic_switch = 1; | 1694 | spec->mic_switch = 1; |
1213 | cfg->line_outs++; | 1695 | cfg->line_outs++; |
1214 | } | 1696 | } |
@@ -1282,8 +1764,8 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec, | |||
1282 | spec->multiout.num_dacs++; | 1764 | spec->multiout.num_dacs++; |
1283 | if (conn_len > 1) { | 1765 | if (conn_len > 1) { |
1284 | /* select this DAC in the pin's input mux */ | 1766 | /* select this DAC in the pin's input mux */ |
1285 | snd_hda_codec_write(codec, nid, 0, | 1767 | snd_hda_codec_write_cache(codec, nid, 0, |
1286 | AC_VERB_SET_CONNECT_SEL, j); | 1768 | AC_VERB_SET_CONNECT_SEL, j); |
1287 | 1769 | ||
1288 | } | 1770 | } |
1289 | } | 1771 | } |
@@ -1318,7 +1800,7 @@ static int create_controls(struct sigmatel_spec *spec, const char *pfx, hda_nid_ | |||
1318 | } | 1800 | } |
1319 | 1801 | ||
1320 | /* add playback controls from the parsed DAC table */ | 1802 | /* add playback controls from the parsed DAC table */ |
1321 | static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec, | 1803 | static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec, |
1322 | const struct auto_pin_cfg *cfg) | 1804 | const struct auto_pin_cfg *cfg) |
1323 | { | 1805 | { |
1324 | static const char *chname[4] = { | 1806 | static const char *chname[4] = { |
@@ -1327,6 +1809,10 @@ static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec, | |||
1327 | hda_nid_t nid; | 1809 | hda_nid_t nid; |
1328 | int i, err; | 1810 | int i, err; |
1329 | 1811 | ||
1812 | struct sigmatel_spec *spec = codec->spec; | ||
1813 | unsigned int wid_caps; | ||
1814 | |||
1815 | |||
1330 | for (i = 0; i < cfg->line_outs; i++) { | 1816 | for (i = 0; i < cfg->line_outs; i++) { |
1331 | if (!spec->multiout.dac_nids[i]) | 1817 | if (!spec->multiout.dac_nids[i]) |
1332 | continue; | 1818 | continue; |
@@ -1341,6 +1827,18 @@ static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec, | |||
1341 | err = create_controls(spec, "LFE", nid, 2); | 1827 | err = create_controls(spec, "LFE", nid, 2); |
1342 | if (err < 0) | 1828 | if (err < 0) |
1343 | return err; | 1829 | return err; |
1830 | |||
1831 | wid_caps = get_wcaps(codec, nid); | ||
1832 | |||
1833 | if (wid_caps & AC_WCAP_LR_SWAP) { | ||
1834 | err = stac92xx_add_control(spec, | ||
1835 | STAC_CTL_WIDGET_CLFE_SWITCH, | ||
1836 | "Swap Center/LFE Playback Switch", nid); | ||
1837 | |||
1838 | if (err < 0) | ||
1839 | return err; | ||
1840 | } | ||
1841 | |||
1344 | } else { | 1842 | } else { |
1345 | err = create_controls(spec, chname[i], nid, 3); | 1843 | err = create_controls(spec, chname[i], nid, 3); |
1346 | if (err < 0) | 1844 | if (err < 0) |
@@ -1536,9 +2034,9 @@ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const | |||
1536 | * NID lists. Hopefully this won't get confused. | 2034 | * NID lists. Hopefully this won't get confused. |
1537 | */ | 2035 | */ |
1538 | for (i = 0; i < spec->num_muxes; i++) { | 2036 | for (i = 0; i < spec->num_muxes; i++) { |
1539 | snd_hda_codec_write(codec, spec->mux_nids[i], 0, | 2037 | snd_hda_codec_write_cache(codec, spec->mux_nids[i], 0, |
1540 | AC_VERB_SET_CONNECT_SEL, | 2038 | AC_VERB_SET_CONNECT_SEL, |
1541 | imux->items[0].index); | 2039 | imux->items[0].index); |
1542 | } | 2040 | } |
1543 | } | 2041 | } |
1544 | 2042 | ||
@@ -1593,9 +2091,19 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
1593 | if ((err = stac92xx_auto_fill_dac_nids(codec, &spec->autocfg)) < 0) | 2091 | if ((err = stac92xx_auto_fill_dac_nids(codec, &spec->autocfg)) < 0) |
1594 | return err; | 2092 | return err; |
1595 | 2093 | ||
1596 | if ((err = stac92xx_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || | 2094 | err = stac92xx_auto_create_multi_out_ctls(codec, &spec->autocfg); |
1597 | (err = stac92xx_auto_create_hp_ctls(codec, &spec->autocfg)) < 0 || | 2095 | |
1598 | (err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0) | 2096 | if (err < 0) |
2097 | return err; | ||
2098 | |||
2099 | err = stac92xx_auto_create_hp_ctls(codec, &spec->autocfg); | ||
2100 | |||
2101 | if (err < 0) | ||
2102 | return err; | ||
2103 | |||
2104 | err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg); | ||
2105 | |||
2106 | if (err < 0) | ||
1599 | return err; | 2107 | return err; |
1600 | 2108 | ||
1601 | if (spec->num_dmics > 0) | 2109 | if (spec->num_dmics > 0) |
@@ -1764,9 +2272,9 @@ static void enable_pin_detect(struct hda_codec *codec, hda_nid_t nid, | |||
1764 | unsigned int event) | 2272 | unsigned int event) |
1765 | { | 2273 | { |
1766 | if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) | 2274 | if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) |
1767 | snd_hda_codec_write(codec, nid, 0, | 2275 | snd_hda_codec_write_cache(codec, nid, 0, |
1768 | AC_VERB_SET_UNSOLICITED_ENABLE, | 2276 | AC_VERB_SET_UNSOLICITED_ENABLE, |
1769 | (AC_USRSP_EN | event)); | 2277 | (AC_USRSP_EN | event)); |
1770 | } | 2278 | } |
1771 | 2279 | ||
1772 | static int stac92xx_init(struct hda_codec *codec) | 2280 | static int stac92xx_init(struct hda_codec *codec) |
@@ -1870,7 +2378,7 @@ static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid, | |||
1870 | if (flag & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN)) | 2378 | if (flag & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN)) |
1871 | pin_ctl &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN); | 2379 | pin_ctl &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN); |
1872 | 2380 | ||
1873 | snd_hda_codec_write(codec, nid, 0, | 2381 | snd_hda_codec_write_cache(codec, nid, 0, |
1874 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 2382 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
1875 | pin_ctl | flag); | 2383 | pin_ctl | flag); |
1876 | } | 2384 | } |
@@ -1880,7 +2388,7 @@ static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid, | |||
1880 | { | 2388 | { |
1881 | unsigned int pin_ctl = snd_hda_codec_read(codec, nid, | 2389 | unsigned int pin_ctl = snd_hda_codec_read(codec, nid, |
1882 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); | 2390 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); |
1883 | snd_hda_codec_write(codec, nid, 0, | 2391 | snd_hda_codec_write_cache(codec, nid, 0, |
1884 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 2392 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
1885 | pin_ctl & ~flag); | 2393 | pin_ctl & ~flag); |
1886 | } | 2394 | } |
@@ -1936,22 +2444,22 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) | |||
1936 | } | 2444 | } |
1937 | } | 2445 | } |
1938 | 2446 | ||
1939 | #ifdef CONFIG_PM | 2447 | #ifdef SND_HDA_NEEDS_RESUME |
1940 | static int stac92xx_resume(struct hda_codec *codec) | 2448 | static int stac92xx_resume(struct hda_codec *codec) |
1941 | { | 2449 | { |
1942 | struct sigmatel_spec *spec = codec->spec; | 2450 | struct sigmatel_spec *spec = codec->spec; |
1943 | int i; | ||
1944 | 2451 | ||
1945 | stac92xx_init(codec); | ||
1946 | stac92xx_set_config_regs(codec); | 2452 | stac92xx_set_config_regs(codec); |
1947 | snd_hda_resume_ctls(codec, spec->mixer); | 2453 | snd_hda_sequence_write(codec, spec->init); |
1948 | for (i = 0; i < spec->num_mixers; i++) | 2454 | if (spec->gpio_mute) { |
1949 | snd_hda_resume_ctls(codec, spec->mixers[i]); | 2455 | stac922x_gpio_mute(codec, 0, 0); |
1950 | if (spec->multiout.dig_out_nid) | 2456 | stac922x_gpio_mute(codec, 1, 0); |
1951 | snd_hda_resume_spdif_out(codec); | 2457 | } |
1952 | if (spec->dig_in_nid) | 2458 | snd_hda_codec_resume_amp(codec); |
1953 | snd_hda_resume_spdif_in(codec); | 2459 | snd_hda_codec_resume_cache(codec); |
1954 | 2460 | /* invoke unsolicited event to reset the HP state */ | |
2461 | if (spec->hp_detect) | ||
2462 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); | ||
1955 | return 0; | 2463 | return 0; |
1956 | } | 2464 | } |
1957 | #endif | 2465 | #endif |
@@ -1962,7 +2470,7 @@ static struct hda_codec_ops stac92xx_patch_ops = { | |||
1962 | .init = stac92xx_init, | 2470 | .init = stac92xx_init, |
1963 | .free = stac92xx_free, | 2471 | .free = stac92xx_free, |
1964 | .unsol_event = stac92xx_unsol_event, | 2472 | .unsol_event = stac92xx_unsol_event, |
1965 | #ifdef CONFIG_PM | 2473 | #ifdef SND_HDA_NEEDS_RESUME |
1966 | .resume = stac92xx_resume, | 2474 | .resume = stac92xx_resume, |
1967 | #endif | 2475 | #endif |
1968 | }; | 2476 | }; |
@@ -2002,8 +2510,12 @@ static int patch_stac9200(struct hda_codec *codec) | |||
2002 | spec->mux_nids = stac9200_mux_nids; | 2510 | spec->mux_nids = stac9200_mux_nids; |
2003 | spec->num_muxes = 1; | 2511 | spec->num_muxes = 1; |
2004 | spec->num_dmics = 0; | 2512 | spec->num_dmics = 0; |
2513 | spec->num_adcs = 1; | ||
2005 | 2514 | ||
2006 | spec->init = stac9200_core_init; | 2515 | if (spec->board_config == STAC_9200_GATEWAY) |
2516 | spec->init = stac9200_eapd_init; | ||
2517 | else | ||
2518 | spec->init = stac9200_core_init; | ||
2007 | spec->mixer = stac9200_mixer; | 2519 | spec->mixer = stac9200_mixer; |
2008 | 2520 | ||
2009 | err = stac9200_parse_auto_config(codec); | 2521 | err = stac9200_parse_auto_config(codec); |
@@ -2053,12 +2565,13 @@ static int patch_stac925x(struct hda_codec *codec) | |||
2053 | spec->adc_nids = stac925x_adc_nids; | 2565 | spec->adc_nids = stac925x_adc_nids; |
2054 | spec->mux_nids = stac925x_mux_nids; | 2566 | spec->mux_nids = stac925x_mux_nids; |
2055 | spec->num_muxes = 1; | 2567 | spec->num_muxes = 1; |
2568 | spec->num_adcs = 1; | ||
2056 | switch (codec->vendor_id) { | 2569 | switch (codec->vendor_id) { |
2057 | case 0x83847632: /* STAC9202 */ | 2570 | case 0x83847632: /* STAC9202 */ |
2058 | case 0x83847633: /* STAC9202D */ | 2571 | case 0x83847633: /* STAC9202D */ |
2059 | case 0x83847636: /* STAC9251 */ | 2572 | case 0x83847636: /* STAC9251 */ |
2060 | case 0x83847637: /* STAC9251D */ | 2573 | case 0x83847637: /* STAC9251D */ |
2061 | spec->num_dmics = 1; | 2574 | spec->num_dmics = STAC925X_NUM_DMICS; |
2062 | spec->dmic_nids = stac925x_dmic_nids; | 2575 | spec->dmic_nids = stac925x_dmic_nids; |
2063 | break; | 2576 | break; |
2064 | default: | 2577 | default: |
@@ -2156,6 +2669,7 @@ static int patch_stac922x(struct hda_codec *codec) | |||
2156 | spec->adc_nids = stac922x_adc_nids; | 2669 | spec->adc_nids = stac922x_adc_nids; |
2157 | spec->mux_nids = stac922x_mux_nids; | 2670 | spec->mux_nids = stac922x_mux_nids; |
2158 | spec->num_muxes = ARRAY_SIZE(stac922x_mux_nids); | 2671 | spec->num_muxes = ARRAY_SIZE(stac922x_mux_nids); |
2672 | spec->num_adcs = ARRAY_SIZE(stac922x_adc_nids); | ||
2159 | spec->num_dmics = 0; | 2673 | spec->num_dmics = 0; |
2160 | 2674 | ||
2161 | spec->init = stac922x_core_init; | 2675 | spec->init = stac922x_core_init; |
@@ -2224,22 +2738,25 @@ static int patch_stac927x(struct hda_codec *codec) | |||
2224 | spec->adc_nids = stac927x_adc_nids; | 2738 | spec->adc_nids = stac927x_adc_nids; |
2225 | spec->mux_nids = stac927x_mux_nids; | 2739 | spec->mux_nids = stac927x_mux_nids; |
2226 | spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids); | 2740 | spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids); |
2741 | spec->num_adcs = ARRAY_SIZE(stac927x_adc_nids); | ||
2227 | spec->num_dmics = 0; | 2742 | spec->num_dmics = 0; |
2228 | spec->init = d965_core_init; | 2743 | spec->init = d965_core_init; |
2229 | spec->mixer = stac9227_mixer; | 2744 | spec->mixer = stac927x_mixer; |
2230 | break; | 2745 | break; |
2231 | case STAC_D965_5ST: | 2746 | case STAC_D965_5ST: |
2232 | spec->adc_nids = stac927x_adc_nids; | 2747 | spec->adc_nids = stac927x_adc_nids; |
2233 | spec->mux_nids = stac927x_mux_nids; | 2748 | spec->mux_nids = stac927x_mux_nids; |
2234 | spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids); | 2749 | spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids); |
2750 | spec->num_adcs = ARRAY_SIZE(stac927x_adc_nids); | ||
2235 | spec->num_dmics = 0; | 2751 | spec->num_dmics = 0; |
2236 | spec->init = d965_core_init; | 2752 | spec->init = d965_core_init; |
2237 | spec->mixer = stac9227_mixer; | 2753 | spec->mixer = stac927x_mixer; |
2238 | break; | 2754 | break; |
2239 | default: | 2755 | default: |
2240 | spec->adc_nids = stac927x_adc_nids; | 2756 | spec->adc_nids = stac927x_adc_nids; |
2241 | spec->mux_nids = stac927x_mux_nids; | 2757 | spec->mux_nids = stac927x_mux_nids; |
2242 | spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids); | 2758 | spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids); |
2759 | spec->num_adcs = ARRAY_SIZE(stac927x_adc_nids); | ||
2243 | spec->num_dmics = 0; | 2760 | spec->num_dmics = 0; |
2244 | spec->init = stac927x_core_init; | 2761 | spec->init = stac927x_core_init; |
2245 | spec->mixer = stac927x_mixer; | 2762 | spec->mixer = stac927x_mixer; |
@@ -2247,7 +2764,8 @@ static int patch_stac927x(struct hda_codec *codec) | |||
2247 | 2764 | ||
2248 | spec->multiout.dac_nids = spec->dac_nids; | 2765 | spec->multiout.dac_nids = spec->dac_nids; |
2249 | /* GPIO0 High = Enable EAPD */ | 2766 | /* GPIO0 High = Enable EAPD */ |
2250 | stac92xx_enable_gpio_mask(codec, 0x00000001, 0x00000001); | 2767 | spec->gpio_mask = spec->gpio_data = 0x00000001; |
2768 | stac92xx_enable_gpio_mask(codec); | ||
2251 | 2769 | ||
2252 | err = stac92xx_parse_auto_config(codec, 0x1e, 0x20); | 2770 | err = stac92xx_parse_auto_config(codec, 0x1e, 0x20); |
2253 | if (!err) { | 2771 | if (!err) { |
@@ -2272,7 +2790,7 @@ static int patch_stac927x(struct hda_codec *codec) | |||
2272 | static int patch_stac9205(struct hda_codec *codec) | 2790 | static int patch_stac9205(struct hda_codec *codec) |
2273 | { | 2791 | { |
2274 | struct sigmatel_spec *spec; | 2792 | struct sigmatel_spec *spec; |
2275 | int err, gpio_mask, gpio_data; | 2793 | int err; |
2276 | 2794 | ||
2277 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 2795 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
2278 | if (spec == NULL) | 2796 | if (spec == NULL) |
@@ -2299,10 +2817,11 @@ static int patch_stac9205(struct hda_codec *codec) | |||
2299 | } | 2817 | } |
2300 | 2818 | ||
2301 | spec->adc_nids = stac9205_adc_nids; | 2819 | spec->adc_nids = stac9205_adc_nids; |
2820 | spec->num_adcs = ARRAY_SIZE(stac9205_adc_nids); | ||
2302 | spec->mux_nids = stac9205_mux_nids; | 2821 | spec->mux_nids = stac9205_mux_nids; |
2303 | spec->num_muxes = ARRAY_SIZE(stac9205_mux_nids); | 2822 | spec->num_muxes = ARRAY_SIZE(stac9205_mux_nids); |
2304 | spec->dmic_nids = stac9205_dmic_nids; | 2823 | spec->dmic_nids = stac9205_dmic_nids; |
2305 | spec->num_dmics = ARRAY_SIZE(stac9205_dmic_nids); | 2824 | spec->num_dmics = STAC9205_NUM_DMICS; |
2306 | spec->dmux_nid = 0x1d; | 2825 | spec->dmux_nid = 0x1d; |
2307 | 2826 | ||
2308 | spec->init = stac9205_core_init; | 2827 | spec->init = stac9205_core_init; |
@@ -2310,20 +2829,25 @@ static int patch_stac9205(struct hda_codec *codec) | |||
2310 | 2829 | ||
2311 | spec->multiout.dac_nids = spec->dac_nids; | 2830 | spec->multiout.dac_nids = spec->dac_nids; |
2312 | 2831 | ||
2313 | if (spec->board_config == STAC_M43xx) { | 2832 | switch (spec->board_config){ |
2833 | case STAC_9205_DELL_M43: | ||
2314 | /* Enable SPDIF in/out */ | 2834 | /* Enable SPDIF in/out */ |
2315 | stac92xx_set_config_reg(codec, 0x1f, 0x01441030); | 2835 | stac92xx_set_config_reg(codec, 0x1f, 0x01441030); |
2316 | stac92xx_set_config_reg(codec, 0x20, 0x1c410030); | 2836 | stac92xx_set_config_reg(codec, 0x20, 0x1c410030); |
2317 | 2837 | ||
2318 | gpio_mask = 0x00000007; /* GPIO0-2 */ | 2838 | spec->gpio_mask = 0x00000007; /* GPIO0-2 */ |
2319 | /* GPIO0 High = EAPD, GPIO1 Low = DRM, | 2839 | /* GPIO0 High = EAPD, GPIO1 Low = DRM, |
2320 | * GPIO2 High = Headphone Mute | 2840 | * GPIO2 High = Headphone Mute |
2321 | */ | 2841 | */ |
2322 | gpio_data = 0x00000005; | 2842 | spec->gpio_data = 0x00000005; |
2323 | } else | 2843 | break; |
2324 | gpio_mask = gpio_data = 0x00000001; /* GPIO0 High = EAPD */ | 2844 | default: |
2845 | /* GPIO0 High = EAPD */ | ||
2846 | spec->gpio_mask = spec->gpio_data = 0x00000001; | ||
2847 | break; | ||
2848 | } | ||
2325 | 2849 | ||
2326 | stac92xx_enable_gpio_mask(codec, gpio_mask, gpio_data); | 2850 | stac92xx_enable_gpio_mask(codec); |
2327 | err = stac92xx_parse_auto_config(codec, 0x1f, 0x20); | 2851 | err = stac92xx_parse_auto_config(codec, 0x1f, 0x20); |
2328 | if (!err) { | 2852 | if (!err) { |
2329 | if (spec->board_config < 0) { | 2853 | if (spec->board_config < 0) { |
@@ -2355,7 +2879,7 @@ static hda_nid_t vaio_adcs[] = { 0x8 /*,0x6*/ }; | |||
2355 | static hda_nid_t vaio_mux_nids[] = { 0x15 }; | 2879 | static hda_nid_t vaio_mux_nids[] = { 0x15 }; |
2356 | 2880 | ||
2357 | static struct hda_input_mux vaio_mux = { | 2881 | static struct hda_input_mux vaio_mux = { |
2358 | .num_items = 2, | 2882 | .num_items = 3, |
2359 | .items = { | 2883 | .items = { |
2360 | /* { "HP", 0x0 }, */ | 2884 | /* { "HP", 0x0 }, */ |
2361 | { "Mic Jack", 0x1 }, | 2885 | { "Mic Jack", 0x1 }, |
@@ -2366,6 +2890,7 @@ static struct hda_input_mux vaio_mux = { | |||
2366 | 2890 | ||
2367 | static struct hda_verb vaio_init[] = { | 2891 | static struct hda_verb vaio_init[] = { |
2368 | {0x0a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP <- 0x2 */ | 2892 | {0x0a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP <- 0x2 */ |
2893 | {0x0a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | STAC_HP_EVENT}, | ||
2369 | {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Speaker <- 0x5 */ | 2894 | {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Speaker <- 0x5 */ |
2370 | {0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? (<- 0x2) */ | 2895 | {0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? (<- 0x2) */ |
2371 | {0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD */ | 2896 | {0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD */ |
@@ -2397,61 +2922,28 @@ static struct hda_verb vaio_ar_init[] = { | |||
2397 | }; | 2922 | }; |
2398 | 2923 | ||
2399 | /* bind volumes of both NID 0x02 and 0x05 */ | 2924 | /* bind volumes of both NID 0x02 and 0x05 */ |
2400 | static int vaio_master_vol_put(struct snd_kcontrol *kcontrol, | 2925 | static struct hda_bind_ctls vaio_bind_master_vol = { |
2401 | struct snd_ctl_elem_value *ucontrol) | 2926 | .ops = &snd_hda_bind_vol, |
2402 | { | 2927 | .values = { |
2403 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 2928 | HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT), |
2404 | long *valp = ucontrol->value.integer.value; | 2929 | HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT), |
2405 | int change; | 2930 | 0 |
2406 | 2931 | }, | |
2407 | change = snd_hda_codec_amp_update(codec, 0x02, 0, HDA_OUTPUT, 0, | 2932 | }; |
2408 | 0x7f, valp[0] & 0x7f); | ||
2409 | change |= snd_hda_codec_amp_update(codec, 0x02, 1, HDA_OUTPUT, 0, | ||
2410 | 0x7f, valp[1] & 0x7f); | ||
2411 | snd_hda_codec_amp_update(codec, 0x05, 0, HDA_OUTPUT, 0, | ||
2412 | 0x7f, valp[0] & 0x7f); | ||
2413 | snd_hda_codec_amp_update(codec, 0x05, 1, HDA_OUTPUT, 0, | ||
2414 | 0x7f, valp[1] & 0x7f); | ||
2415 | return change; | ||
2416 | } | ||
2417 | 2933 | ||
2418 | /* bind volumes of both NID 0x02 and 0x05 */ | 2934 | /* bind volumes of both NID 0x02 and 0x05 */ |
2419 | static int vaio_master_sw_put(struct snd_kcontrol *kcontrol, | 2935 | static struct hda_bind_ctls vaio_bind_master_sw = { |
2420 | struct snd_ctl_elem_value *ucontrol) | 2936 | .ops = &snd_hda_bind_sw, |
2421 | { | 2937 | .values = { |
2422 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 2938 | HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT), |
2423 | long *valp = ucontrol->value.integer.value; | 2939 | HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT), |
2424 | int change; | 2940 | 0, |
2425 | 2941 | }, | |
2426 | change = snd_hda_codec_amp_update(codec, 0x02, 0, HDA_OUTPUT, 0, | 2942 | }; |
2427 | 0x80, (valp[0] ? 0 : 0x80)); | ||
2428 | change |= snd_hda_codec_amp_update(codec, 0x02, 1, HDA_OUTPUT, 0, | ||
2429 | 0x80, (valp[1] ? 0 : 0x80)); | ||
2430 | snd_hda_codec_amp_update(codec, 0x05, 0, HDA_OUTPUT, 0, | ||
2431 | 0x80, (valp[0] ? 0 : 0x80)); | ||
2432 | snd_hda_codec_amp_update(codec, 0x05, 1, HDA_OUTPUT, 0, | ||
2433 | 0x80, (valp[1] ? 0 : 0x80)); | ||
2434 | return change; | ||
2435 | } | ||
2436 | 2943 | ||
2437 | static struct snd_kcontrol_new vaio_mixer[] = { | 2944 | static struct snd_kcontrol_new vaio_mixer[] = { |
2438 | { | 2945 | HDA_BIND_VOL("Master Playback Volume", &vaio_bind_master_vol), |
2439 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2946 | HDA_BIND_SW("Master Playback Switch", &vaio_bind_master_sw), |
2440 | .name = "Master Playback Volume", | ||
2441 | .info = snd_hda_mixer_amp_volume_info, | ||
2442 | .get = snd_hda_mixer_amp_volume_get, | ||
2443 | .put = vaio_master_vol_put, | ||
2444 | .tlv = { .c = snd_hda_mixer_amp_tlv }, | ||
2445 | .private_value = HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT), | ||
2446 | }, | ||
2447 | { | ||
2448 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2449 | .name = "Master Playback Switch", | ||
2450 | .info = snd_hda_mixer_amp_switch_info, | ||
2451 | .get = snd_hda_mixer_amp_switch_get, | ||
2452 | .put = vaio_master_sw_put, | ||
2453 | .private_value = HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT), | ||
2454 | }, | ||
2455 | /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */ | 2947 | /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */ |
2456 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), | 2948 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), |
2457 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), | 2949 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), |
@@ -2467,22 +2959,8 @@ static struct snd_kcontrol_new vaio_mixer[] = { | |||
2467 | }; | 2959 | }; |
2468 | 2960 | ||
2469 | static struct snd_kcontrol_new vaio_ar_mixer[] = { | 2961 | static struct snd_kcontrol_new vaio_ar_mixer[] = { |
2470 | { | 2962 | HDA_BIND_VOL("Master Playback Volume", &vaio_bind_master_vol), |
2471 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2963 | HDA_BIND_SW("Master Playback Switch", &vaio_bind_master_sw), |
2472 | .name = "Master Playback Volume", | ||
2473 | .info = snd_hda_mixer_amp_volume_info, | ||
2474 | .get = snd_hda_mixer_amp_volume_get, | ||
2475 | .put = vaio_master_vol_put, | ||
2476 | .private_value = HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT), | ||
2477 | }, | ||
2478 | { | ||
2479 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2480 | .name = "Master Playback Switch", | ||
2481 | .info = snd_hda_mixer_amp_switch_info, | ||
2482 | .get = snd_hda_mixer_amp_switch_get, | ||
2483 | .put = vaio_master_sw_put, | ||
2484 | .private_value = HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT), | ||
2485 | }, | ||
2486 | /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */ | 2964 | /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */ |
2487 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), | 2965 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), |
2488 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), | 2966 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), |
@@ -2504,6 +2982,49 @@ static struct hda_codec_ops stac9872_patch_ops = { | |||
2504 | .build_pcms = stac92xx_build_pcms, | 2982 | .build_pcms = stac92xx_build_pcms, |
2505 | .init = stac92xx_init, | 2983 | .init = stac92xx_init, |
2506 | .free = stac92xx_free, | 2984 | .free = stac92xx_free, |
2985 | #ifdef SND_HDA_NEEDS_RESUME | ||
2986 | .resume = stac92xx_resume, | ||
2987 | #endif | ||
2988 | }; | ||
2989 | |||
2990 | static int stac9872_vaio_init(struct hda_codec *codec) | ||
2991 | { | ||
2992 | int err; | ||
2993 | |||
2994 | err = stac92xx_init(codec); | ||
2995 | if (err < 0) | ||
2996 | return err; | ||
2997 | if (codec->patch_ops.unsol_event) | ||
2998 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); | ||
2999 | return 0; | ||
3000 | } | ||
3001 | |||
3002 | static void stac9872_vaio_hp_detect(struct hda_codec *codec, unsigned int res) | ||
3003 | { | ||
3004 | if (get_pin_presence(codec, 0x0a)) { | ||
3005 | stac92xx_reset_pinctl(codec, 0x0f, AC_PINCTL_OUT_EN); | ||
3006 | stac92xx_set_pinctl(codec, 0x0a, AC_PINCTL_OUT_EN); | ||
3007 | } else { | ||
3008 | stac92xx_reset_pinctl(codec, 0x0a, AC_PINCTL_OUT_EN); | ||
3009 | stac92xx_set_pinctl(codec, 0x0f, AC_PINCTL_OUT_EN); | ||
3010 | } | ||
3011 | } | ||
3012 | |||
3013 | static void stac9872_vaio_unsol_event(struct hda_codec *codec, unsigned int res) | ||
3014 | { | ||
3015 | switch (res >> 26) { | ||
3016 | case STAC_HP_EVENT: | ||
3017 | stac9872_vaio_hp_detect(codec, res); | ||
3018 | break; | ||
3019 | } | ||
3020 | } | ||
3021 | |||
3022 | static struct hda_codec_ops stac9872_vaio_patch_ops = { | ||
3023 | .build_controls = stac92xx_build_controls, | ||
3024 | .build_pcms = stac92xx_build_pcms, | ||
3025 | .init = stac9872_vaio_init, | ||
3026 | .free = stac92xx_free, | ||
3027 | .unsol_event = stac9872_vaio_unsol_event, | ||
2507 | #ifdef CONFIG_PM | 3028 | #ifdef CONFIG_PM |
2508 | .resume = stac92xx_resume, | 3029 | .resume = stac92xx_resume, |
2509 | #endif | 3030 | #endif |
@@ -2564,6 +3085,7 @@ static int patch_stac9872(struct hda_codec *codec) | |||
2564 | spec->adc_nids = vaio_adcs; | 3085 | spec->adc_nids = vaio_adcs; |
2565 | spec->input_mux = &vaio_mux; | 3086 | spec->input_mux = &vaio_mux; |
2566 | spec->mux_nids = vaio_mux_nids; | 3087 | spec->mux_nids = vaio_mux_nids; |
3088 | codec->patch_ops = stac9872_vaio_patch_ops; | ||
2567 | break; | 3089 | break; |
2568 | 3090 | ||
2569 | case CXD9872AKD_VAIO: | 3091 | case CXD9872AKD_VAIO: |
@@ -2577,10 +3099,10 @@ static int patch_stac9872(struct hda_codec *codec) | |||
2577 | spec->adc_nids = vaio_adcs; | 3099 | spec->adc_nids = vaio_adcs; |
2578 | spec->input_mux = &vaio_mux; | 3100 | spec->input_mux = &vaio_mux; |
2579 | spec->mux_nids = vaio_mux_nids; | 3101 | spec->mux_nids = vaio_mux_nids; |
3102 | codec->patch_ops = stac9872_patch_ops; | ||
2580 | break; | 3103 | break; |
2581 | } | 3104 | } |
2582 | 3105 | ||
2583 | codec->patch_ops = stac9872_patch_ops; | ||
2584 | return 0; | 3106 | return 0; |
2585 | } | 3107 | } |
2586 | 3108 | ||
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index ba32d1e52cb8..33b5e1ffa817 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c | |||
@@ -115,6 +115,10 @@ struct via_spec { | |||
115 | struct snd_kcontrol_new *kctl_alloc; | 115 | struct snd_kcontrol_new *kctl_alloc; |
116 | struct hda_input_mux private_imux; | 116 | struct hda_input_mux private_imux; |
117 | hda_nid_t private_dac_nids[4]; | 117 | hda_nid_t private_dac_nids[4]; |
118 | |||
119 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
120 | struct hda_loopback_check loopback; | ||
121 | #endif | ||
118 | }; | 122 | }; |
119 | 123 | ||
120 | static hda_nid_t vt1708_adc_nids[2] = { | 124 | static hda_nid_t vt1708_adc_nids[2] = { |
@@ -305,15 +309,15 @@ static struct hda_verb vt1708_volume_init_verbs[] = { | |||
305 | {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 309 | {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
306 | 310 | ||
307 | 311 | ||
308 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | 312 | /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback |
309 | * mixer widget | 313 | * mixer widget |
310 | */ | 314 | */ |
311 | /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */ | 315 | /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */ |
312 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 316 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* master */ |
313 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 317 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
314 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 318 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
315 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 319 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
316 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 320 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
317 | 321 | ||
318 | /* | 322 | /* |
319 | * Set up output mixers (0x19 - 0x1b) | 323 | * Set up output mixers (0x19 - 0x1b) |
@@ -543,24 +547,11 @@ static int via_init(struct hda_codec *codec) | |||
543 | return 0; | 547 | return 0; |
544 | } | 548 | } |
545 | 549 | ||
546 | #ifdef CONFIG_PM | 550 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
547 | /* | 551 | static int via_check_power_status(struct hda_codec *codec, hda_nid_t nid) |
548 | * resume | ||
549 | */ | ||
550 | static int via_resume(struct hda_codec *codec) | ||
551 | { | 552 | { |
552 | struct via_spec *spec = codec->spec; | 553 | struct via_spec *spec = codec->spec; |
553 | int i; | 554 | return snd_hda_check_amp_list_power(codec, &spec->loopback, nid); |
554 | |||
555 | via_init(codec); | ||
556 | for (i = 0; i < spec->num_mixers; i++) | ||
557 | snd_hda_resume_ctls(codec, spec->mixers[i]); | ||
558 | if (spec->multiout.dig_out_nid) | ||
559 | snd_hda_resume_spdif_out(codec); | ||
560 | if (spec->dig_in_nid) | ||
561 | snd_hda_resume_spdif_in(codec); | ||
562 | |||
563 | return 0; | ||
564 | } | 555 | } |
565 | #endif | 556 | #endif |
566 | 557 | ||
@@ -571,8 +562,8 @@ static struct hda_codec_ops via_patch_ops = { | |||
571 | .build_pcms = via_build_pcms, | 562 | .build_pcms = via_build_pcms, |
572 | .init = via_init, | 563 | .init = via_init, |
573 | .free = via_free, | 564 | .free = via_free, |
574 | #ifdef CONFIG_PM | 565 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
575 | .resume = via_resume, | 566 | .check_power_status = via_check_power_status, |
576 | #endif | 567 | #endif |
577 | }; | 568 | }; |
578 | 569 | ||
@@ -762,6 +753,16 @@ static int vt1708_auto_create_analog_input_ctls(struct via_spec *spec, | |||
762 | return 0; | 753 | return 0; |
763 | } | 754 | } |
764 | 755 | ||
756 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
757 | static struct hda_amp_list vt1708_loopbacks[] = { | ||
758 | { 0x17, HDA_INPUT, 1 }, | ||
759 | { 0x17, HDA_INPUT, 2 }, | ||
760 | { 0x17, HDA_INPUT, 3 }, | ||
761 | { 0x17, HDA_INPUT, 4 }, | ||
762 | { } /* end */ | ||
763 | }; | ||
764 | #endif | ||
765 | |||
765 | static int vt1708_parse_auto_config(struct hda_codec *codec) | 766 | static int vt1708_parse_auto_config(struct hda_codec *codec) |
766 | { | 767 | { |
767 | struct via_spec *spec = codec->spec; | 768 | struct via_spec *spec = codec->spec; |
@@ -855,6 +856,9 @@ static int patch_vt1708(struct hda_codec *codec) | |||
855 | codec->patch_ops = via_patch_ops; | 856 | codec->patch_ops = via_patch_ops; |
856 | 857 | ||
857 | codec->patch_ops.init = via_auto_init; | 858 | codec->patch_ops.init = via_auto_init; |
859 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
860 | spec->loopback.amplist = vt1708_loopbacks; | ||
861 | #endif | ||
858 | 862 | ||
859 | return 0; | 863 | return 0; |
860 | } | 864 | } |
@@ -895,15 +899,15 @@ static struct hda_verb vt1709_10ch_volume_init_verbs[] = { | |||
895 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 899 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
896 | 900 | ||
897 | 901 | ||
898 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | 902 | /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback |
899 | * mixer widget | 903 | * mixer widget |
900 | */ | 904 | */ |
901 | /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */ | 905 | /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */ |
902 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 906 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* unmute master */ |
903 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 907 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
904 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 908 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
905 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 909 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
906 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 910 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
907 | 911 | ||
908 | /* | 912 | /* |
909 | * Set up output selector (0x1a, 0x1b, 0x29) | 913 | * Set up output selector (0x1a, 0x1b, 0x29) |
@@ -1251,6 +1255,16 @@ static int vt1709_parse_auto_config(struct hda_codec *codec) | |||
1251 | return 1; | 1255 | return 1; |
1252 | } | 1256 | } |
1253 | 1257 | ||
1258 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1259 | static struct hda_amp_list vt1709_loopbacks[] = { | ||
1260 | { 0x18, HDA_INPUT, 1 }, | ||
1261 | { 0x18, HDA_INPUT, 2 }, | ||
1262 | { 0x18, HDA_INPUT, 3 }, | ||
1263 | { 0x18, HDA_INPUT, 4 }, | ||
1264 | { } /* end */ | ||
1265 | }; | ||
1266 | #endif | ||
1267 | |||
1254 | static int patch_vt1709_10ch(struct hda_codec *codec) | 1268 | static int patch_vt1709_10ch(struct hda_codec *codec) |
1255 | { | 1269 | { |
1256 | struct via_spec *spec; | 1270 | struct via_spec *spec; |
@@ -1293,6 +1307,9 @@ static int patch_vt1709_10ch(struct hda_codec *codec) | |||
1293 | codec->patch_ops = via_patch_ops; | 1307 | codec->patch_ops = via_patch_ops; |
1294 | 1308 | ||
1295 | codec->patch_ops.init = via_auto_init; | 1309 | codec->patch_ops.init = via_auto_init; |
1310 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1311 | spec->loopback.amplist = vt1709_loopbacks; | ||
1312 | #endif | ||
1296 | 1313 | ||
1297 | return 0; | 1314 | return 0; |
1298 | } | 1315 | } |
@@ -1383,6 +1400,9 @@ static int patch_vt1709_6ch(struct hda_codec *codec) | |||
1383 | codec->patch_ops = via_patch_ops; | 1400 | codec->patch_ops = via_patch_ops; |
1384 | 1401 | ||
1385 | codec->patch_ops.init = via_auto_init; | 1402 | codec->patch_ops.init = via_auto_init; |
1403 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1404 | spec->loopback.amplist = vt1709_loopbacks; | ||
1405 | #endif | ||
1386 | 1406 | ||
1387 | return 0; | 1407 | return 0; |
1388 | } | 1408 | } |
diff --git a/sound/pci/ice1712/Makefile b/sound/pci/ice1712/Makefile index 6efdd62f6837..65ce66adba5a 100644 --- a/sound/pci/ice1712/Makefile +++ b/sound/pci/ice1712/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-ice17xx-ak4xxx-objs := ak4xxx.o | 6 | snd-ice17xx-ak4xxx-objs := ak4xxx.o |
diff --git a/sound/pci/ice1712/ak4xxx.c b/sound/pci/ice1712/ak4xxx.c index ab00cce2c39f..a1aba0d7d0e4 100644 --- a/sound/pci/ice1712/ak4xxx.c +++ b/sound/pci/ice1712/ak4xxx.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * AK4524 / AK4528 / AK4529 / AK4355 / AK4381 interface | 4 | * AK4524 / AK4528 / AK4529 / AK4355 / AK4381 interface |
5 | * | 5 | * |
6 | * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz> | 6 | * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz> |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
@@ -30,7 +30,7 @@ | |||
30 | #include <sound/initval.h> | 30 | #include <sound/initval.h> |
31 | #include "ice1712.h" | 31 | #include "ice1712.h" |
32 | 32 | ||
33 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 33 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
34 | MODULE_DESCRIPTION("ICEnsemble ICE17xx <-> AK4xxx AD/DA chip interface"); | 34 | MODULE_DESCRIPTION("ICEnsemble ICE17xx <-> AK4xxx AD/DA chip interface"); |
35 | MODULE_LICENSE("GPL"); | 35 | MODULE_LICENSE("GPL"); |
36 | 36 | ||
diff --git a/sound/pci/ice1712/amp.c b/sound/pci/ice1712/amp.c index 44bbb630b949..6e13d758bb5d 100644 --- a/sound/pci/ice1712/amp.c +++ b/sound/pci/ice1712/amp.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Lowlevel functions for Advanced Micro Peripherals Ltd AUDIO2000 | 4 | * Lowlevel functions for Advanced Micro Peripherals Ltd AUDIO2000 |
5 | * | 5 | * |
6 | * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz> | 6 | * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz> |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
diff --git a/sound/pci/ice1712/amp.h b/sound/pci/ice1712/amp.h index a0fc89b48122..bf81d30d9150 100644 --- a/sound/pci/ice1712/amp.h +++ b/sound/pci/ice1712/amp.h | |||
@@ -6,7 +6,7 @@ | |||
6 | * | 6 | * |
7 | * Lowlevel functions for Advanced Micro Peripherals Ltd AUDIO2000 | 7 | * Lowlevel functions for Advanced Micro Peripherals Ltd AUDIO2000 |
8 | * | 8 | * |
9 | * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz> | 9 | * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz> |
10 | * | 10 | * |
11 | * This program is free software; you can redistribute it and/or modify | 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 | 12 | * it under the terms of the GNU General Public License as published by |
diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c index 66bacde1ead3..ec0699c89952 100644 --- a/sound/pci/ice1712/aureon.c +++ b/sound/pci/ice1712/aureon.c | |||
@@ -394,7 +394,7 @@ static int aureon_ac97_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ele | |||
394 | /* | 394 | /* |
395 | * AC'97 mute controls | 395 | * AC'97 mute controls |
396 | */ | 396 | */ |
397 | #define aureon_ac97_mute_info aureon_mono_bool_info | 397 | #define aureon_ac97_mute_info snd_ctl_boolean_mono_info |
398 | 398 | ||
399 | static int aureon_ac97_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 399 | static int aureon_ac97_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
400 | { | 400 | { |
@@ -430,7 +430,7 @@ static int aureon_ac97_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el | |||
430 | /* | 430 | /* |
431 | * AC'97 mute controls | 431 | * AC'97 mute controls |
432 | */ | 432 | */ |
433 | #define aureon_ac97_micboost_info aureon_mono_bool_info | 433 | #define aureon_ac97_micboost_info snd_ctl_boolean_mono_info |
434 | 434 | ||
435 | static int aureon_ac97_micboost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 435 | static int aureon_ac97_micboost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
436 | { | 436 | { |
@@ -621,19 +621,12 @@ static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val) | |||
621 | 621 | ||
622 | /* | 622 | /* |
623 | */ | 623 | */ |
624 | static int aureon_mono_bool_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo) | 624 | #define aureon_mono_bool_info snd_ctl_boolean_mono_info |
625 | { | ||
626 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
627 | uinfo->count = 1; | ||
628 | uinfo->value.integer.min = 0; | ||
629 | uinfo->value.integer.max = 1; | ||
630 | return 0; | ||
631 | } | ||
632 | 625 | ||
633 | /* | 626 | /* |
634 | * AC'97 master playback mute controls (Mute on WM8770 chip) | 627 | * AC'97 master playback mute controls (Mute on WM8770 chip) |
635 | */ | 628 | */ |
636 | #define aureon_ac97_mmute_info aureon_mono_bool_info | 629 | #define aureon_ac97_mmute_info snd_ctl_boolean_mono_info |
637 | 630 | ||
638 | static int aureon_ac97_mmute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 631 | static int aureon_ac97_mmute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
639 | { | 632 | { |
@@ -708,7 +701,7 @@ static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index, unsigned sho | |||
708 | /* | 701 | /* |
709 | * DAC mute control | 702 | * DAC mute control |
710 | */ | 703 | */ |
711 | #define wm_pcm_mute_info aureon_mono_bool_info | 704 | #define wm_pcm_mute_info snd_ctl_boolean_mono_info |
712 | 705 | ||
713 | static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 706 | static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
714 | { | 707 | { |
@@ -879,13 +872,7 @@ static int wm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value | |||
879 | /* | 872 | /* |
880 | * WM8770 master mute control | 873 | * WM8770 master mute control |
881 | */ | 874 | */ |
882 | static int wm_master_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { | 875 | #define wm_master_mute_info snd_ctl_boolean_stereo_info |
883 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
884 | uinfo->count = 2; | ||
885 | uinfo->value.integer.min = 0; | ||
886 | uinfo->value.integer.max = 1; | ||
887 | return 0; | ||
888 | } | ||
889 | 876 | ||
890 | static int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 877 | static int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
891 | { | 878 | { |
@@ -969,14 +956,7 @@ static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val | |||
969 | /* | 956 | /* |
970 | * ADC mute control | 957 | * ADC mute control |
971 | */ | 958 | */ |
972 | static int wm_adc_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 959 | #define wm_adc_mute_info snd_ctl_boolean_stereo_info |
973 | { | ||
974 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
975 | uinfo->count = 2; | ||
976 | uinfo->value.integer.min = 0; | ||
977 | uinfo->value.integer.max = 1; | ||
978 | return 0; | ||
979 | } | ||
980 | 960 | ||
981 | static int wm_adc_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 961 | static int wm_adc_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
982 | { | 962 | { |
@@ -1210,12 +1190,7 @@ static int aureon_cs8415_rate_get (struct snd_kcontrol *kcontrol, struct snd_ctl | |||
1210 | /* | 1190 | /* |
1211 | * CS8415A Mute | 1191 | * CS8415A Mute |
1212 | */ | 1192 | */ |
1213 | static int aureon_cs8415_mute_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1193 | #define aureon_cs8415_mute_info snd_ctl_boolean_mono_info |
1214 | { | ||
1215 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1216 | uinfo->count = 1; | ||
1217 | return 0; | ||
1218 | } | ||
1219 | 1194 | ||
1220 | static int aureon_cs8415_mute_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1195 | static int aureon_cs8415_mute_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1221 | { | 1196 | { |
@@ -1316,7 +1291,7 @@ static int aureon_get_headphone_amp(struct snd_ice1712 *ice) | |||
1316 | return ( tmp & AUREON_HP_SEL )!= 0; | 1291 | return ( tmp & AUREON_HP_SEL )!= 0; |
1317 | } | 1292 | } |
1318 | 1293 | ||
1319 | #define aureon_hpamp_info aureon_mono_bool_info | 1294 | #define aureon_hpamp_info snd_ctl_boolean_mono_info |
1320 | 1295 | ||
1321 | static int aureon_hpamp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1296 | static int aureon_hpamp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1322 | { | 1297 | { |
@@ -1338,7 +1313,7 @@ static int aureon_hpamp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v | |||
1338 | * Deemphasis | 1313 | * Deemphasis |
1339 | */ | 1314 | */ |
1340 | 1315 | ||
1341 | #define aureon_deemp_info aureon_mono_bool_info | 1316 | #define aureon_deemp_info snd_ctl_boolean_mono_info |
1342 | 1317 | ||
1343 | static int aureon_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1318 | static int aureon_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1344 | { | 1319 | { |
diff --git a/sound/pci/ice1712/delta.c b/sound/pci/ice1712/delta.c index af659800c9b0..371f78461db4 100644 --- a/sound/pci/ice1712/delta.c +++ b/sound/pci/ice1712/delta.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * Lowlevel functions for M-Audio Delta 1010, 44, 66, Dio2496, Audiophile | 4 | * Lowlevel functions for M-Audio Delta 1010, 44, 66, Dio2496, Audiophile |
5 | * Digigram VX442 | 5 | * Digigram VX442 |
6 | * | 6 | * |
7 | * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz> | 7 | * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz> |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License as published by | 10 | * it under the terms of the GNU General Public License as published by |
@@ -393,15 +393,8 @@ static void delta_setup_spdif(struct snd_ice1712 *ice, int rate) | |||
393 | snd_ice1712_delta_cs8403_spdif_write(ice, tmp); | 393 | snd_ice1712_delta_cs8403_spdif_write(ice, tmp); |
394 | } | 394 | } |
395 | 395 | ||
396 | static int snd_ice1712_delta1010lt_wordclock_status_info(struct snd_kcontrol *kcontrol, | 396 | #define snd_ice1712_delta1010lt_wordclock_status_info \ |
397 | struct snd_ctl_elem_info *uinfo) | 397 | snd_ctl_boolean_mono_info |
398 | { | ||
399 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
400 | uinfo->count = 1; | ||
401 | uinfo->value.integer.min = 0; | ||
402 | uinfo->value.integer.max = 1; | ||
403 | return 0; | ||
404 | } | ||
405 | 398 | ||
406 | static int snd_ice1712_delta1010lt_wordclock_status_get(struct snd_kcontrol *kcontrol, | 399 | static int snd_ice1712_delta1010lt_wordclock_status_get(struct snd_kcontrol *kcontrol, |
407 | struct snd_ctl_elem_value *ucontrol) | 400 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/pci/ice1712/delta.h b/sound/pci/ice1712/delta.h index 2697156607e4..26ea05a32f56 100644 --- a/sound/pci/ice1712/delta.h +++ b/sound/pci/ice1712/delta.h | |||
@@ -7,7 +7,7 @@ | |||
7 | * Lowlevel functions for M-Audio Delta 1010, 44, 66, Dio2496, Audiophile | 7 | * Lowlevel functions for M-Audio Delta 1010, 44, 66, Dio2496, Audiophile |
8 | * Digigram VX442 | 8 | * Digigram VX442 |
9 | * | 9 | * |
10 | * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz> | 10 | * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz> |
11 | * | 11 | * |
12 | * This program is free software; you can redistribute it and/or modify | 12 | * This program is free software; you can redistribute it and/or modify |
13 | * it under the terms of the GNU General Public License as published by | 13 | * it under the terms of the GNU General Public License as published by |
diff --git a/sound/pci/ice1712/envy24ht.h b/sound/pci/ice1712/envy24ht.h index b58afcda9ed6..43b9e3e858be 100644 --- a/sound/pci/ice1712/envy24ht.h +++ b/sound/pci/ice1712/envy24ht.h | |||
@@ -4,7 +4,7 @@ | |||
4 | /* | 4 | /* |
5 | * ALSA driver for ICEnsemble VT1724 (Envy24) | 5 | * ALSA driver for ICEnsemble VT1724 (Envy24) |
6 | * | 6 | * |
7 | * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz> | 7 | * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz> |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License as published by | 10 | * it under the terms of the GNU General Public License as published by |
diff --git a/sound/pci/ice1712/ews.c b/sound/pci/ice1712/ews.c index b135389fec6c..75e4e5e0f1e4 100644 --- a/sound/pci/ice1712/ews.c +++ b/sound/pci/ice1712/ews.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Lowlevel functions for Terratec EWS88MT/D, EWX24/96, DMX 6Fire | 4 | * Lowlevel functions for Terratec EWS88MT/D, EWX24/96, DMX 6Fire |
5 | * | 5 | * |
6 | * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz> | 6 | * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz> |
7 | * 2002 Takashi Iwai <tiwai@suse.de> | 7 | * 2002 Takashi Iwai <tiwai@suse.de> |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
@@ -700,14 +700,7 @@ static struct snd_kcontrol_new snd_ice1712_ews88mt_output_sense __devinitdata = | |||
700 | * EWS88D specific controls | 700 | * EWS88D specific controls |
701 | */ | 701 | */ |
702 | 702 | ||
703 | static int snd_ice1712_ews88d_control_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 703 | #define snd_ice1712_ews88d_control_info snd_ctl_boolean_mono_info |
704 | { | ||
705 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
706 | uinfo->count = 1; | ||
707 | uinfo->value.integer.min = 0; | ||
708 | uinfo->value.integer.max = 1; | ||
709 | return 0; | ||
710 | } | ||
711 | 704 | ||
712 | static int snd_ice1712_ews88d_control_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 705 | static int snd_ice1712_ews88d_control_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
713 | { | 706 | { |
@@ -812,14 +805,7 @@ static int snd_ice1712_6fire_write_pca(struct snd_ice1712 *ice, unsigned char re | |||
812 | return 0; | 805 | return 0; |
813 | } | 806 | } |
814 | 807 | ||
815 | static int snd_ice1712_6fire_control_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 808 | #define snd_ice1712_6fire_control_info snd_ctl_boolean_mono_info |
816 | { | ||
817 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
818 | uinfo->count = 1; | ||
819 | uinfo->value.integer.min = 0; | ||
820 | uinfo->value.integer.max = 1; | ||
821 | return 0; | ||
822 | } | ||
823 | 809 | ||
824 | static int snd_ice1712_6fire_control_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 810 | static int snd_ice1712_6fire_control_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
825 | { | 811 | { |
diff --git a/sound/pci/ice1712/ews.h b/sound/pci/ice1712/ews.h index a12a0b053558..e4ed1b475b08 100644 --- a/sound/pci/ice1712/ews.h +++ b/sound/pci/ice1712/ews.h | |||
@@ -6,7 +6,7 @@ | |||
6 | * | 6 | * |
7 | * Lowlevel functions for Terratec EWS88MT/D, EWX24/96, DMX 6Fire | 7 | * Lowlevel functions for Terratec EWS88MT/D, EWX24/96, DMX 6Fire |
8 | * | 8 | * |
9 | * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz> | 9 | * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz> |
10 | * 2002 Takashi Iwai <tiwai@suse.de> | 10 | * 2002 Takashi Iwai <tiwai@suse.de> |
11 | * | 11 | * |
12 | * This program is free software; you can redistribute it and/or modify | 12 | * This program is free software; you can redistribute it and/or modify |
diff --git a/sound/pci/ice1712/hoontech.c b/sound/pci/ice1712/hoontech.c index 8203562ef7e7..abcfd1da6587 100644 --- a/sound/pci/ice1712/hoontech.c +++ b/sound/pci/ice1712/hoontech.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Lowlevel functions for Hoontech STDSP24 | 4 | * Lowlevel functions for Hoontech STDSP24 |
5 | * | 5 | * |
6 | * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz> | 6 | * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz> |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
diff --git a/sound/pci/ice1712/hoontech.h b/sound/pci/ice1712/hoontech.h index 1ee538b20fbf..cc1da1e69ad1 100644 --- a/sound/pci/ice1712/hoontech.h +++ b/sound/pci/ice1712/hoontech.h | |||
@@ -6,7 +6,7 @@ | |||
6 | * | 6 | * |
7 | * Lowlevel functions for Hoontech STDSP24 | 7 | * Lowlevel functions for Hoontech STDSP24 |
8 | * | 8 | * |
9 | * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz> | 9 | * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz> |
10 | * | 10 | * |
11 | * This program is free software; you can redistribute it and/or modify | 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 | 12 | * it under the terms of the GNU General Public License as published by |
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index 6630a0ae9527..052fc3cb3272 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * ALSA driver for ICEnsemble ICE1712 (Envy24) | 2 | * ALSA driver for ICEnsemble ICE1712 (Envy24) |
3 | * | 3 | * |
4 | * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz> | 4 | * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
@@ -73,7 +73,7 @@ | |||
73 | #include "ews.h" | 73 | #include "ews.h" |
74 | #include "hoontech.h" | 74 | #include "hoontech.h" |
75 | 75 | ||
76 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 76 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
77 | MODULE_DESCRIPTION("ICEnsemble ICE1712 (Envy24)"); | 77 | MODULE_DESCRIPTION("ICEnsemble ICE1712 (Envy24)"); |
78 | MODULE_LICENSE("GPL"); | 78 | MODULE_LICENSE("GPL"); |
79 | MODULE_SUPPORTED_DEVICE("{" | 79 | MODULE_SUPPORTED_DEVICE("{" |
@@ -256,14 +256,7 @@ static unsigned short snd_ice1712_pro_ac97_read(struct snd_ac97 *ac97, | |||
256 | /* | 256 | /* |
257 | * consumer ac97 digital mix | 257 | * consumer ac97 digital mix |
258 | */ | 258 | */ |
259 | static int snd_ice1712_digmix_route_ac97_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 259 | #define snd_ice1712_digmix_route_ac97_info snd_ctl_boolean_mono_info |
260 | { | ||
261 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
262 | uinfo->count = 1; | ||
263 | uinfo->value.integer.min = 0; | ||
264 | uinfo->value.integer.max = 1; | ||
265 | return 0; | ||
266 | } | ||
267 | 260 | ||
268 | static int snd_ice1712_digmix_route_ac97_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 261 | static int snd_ice1712_digmix_route_ac97_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
269 | { | 262 | { |
@@ -1300,14 +1293,7 @@ static void snd_ice1712_update_volume(struct snd_ice1712 *ice, int index) | |||
1300 | outw(val, ICEMT(ice, MONITOR_VOLUME)); | 1293 | outw(val, ICEMT(ice, MONITOR_VOLUME)); |
1301 | } | 1294 | } |
1302 | 1295 | ||
1303 | static int snd_ice1712_pro_mixer_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1296 | #define snd_ice1712_pro_mixer_switch_info snd_ctl_boolean_stereo_info |
1304 | { | ||
1305 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1306 | uinfo->count = 2; | ||
1307 | uinfo->value.integer.min = 0; | ||
1308 | uinfo->value.integer.max = 1; | ||
1309 | return 0; | ||
1310 | } | ||
1311 | 1297 | ||
1312 | static int snd_ice1712_pro_mixer_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1298 | static int snd_ice1712_pro_mixer_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1313 | { | 1299 | { |
@@ -1759,16 +1745,6 @@ static struct snd_kcontrol_new snd_ice1712_spdif_stream __devinitdata = | |||
1759 | .put = snd_ice1712_spdif_stream_put | 1745 | .put = snd_ice1712_spdif_stream_put |
1760 | }; | 1746 | }; |
1761 | 1747 | ||
1762 | int snd_ice1712_gpio_info(struct snd_kcontrol *kcontrol, | ||
1763 | struct snd_ctl_elem_info *uinfo) | ||
1764 | { | ||
1765 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1766 | uinfo->count = 1; | ||
1767 | uinfo->value.integer.min = 0; | ||
1768 | uinfo->value.integer.max = 1; | ||
1769 | return 0; | ||
1770 | } | ||
1771 | |||
1772 | int snd_ice1712_gpio_get(struct snd_kcontrol *kcontrol, | 1748 | int snd_ice1712_gpio_get(struct snd_kcontrol *kcontrol, |
1773 | struct snd_ctl_elem_value *ucontrol) | 1749 | struct snd_ctl_elem_value *ucontrol) |
1774 | { | 1750 | { |
@@ -1968,15 +1944,7 @@ static struct snd_kcontrol_new snd_ice1712_pro_internal_clock_default __devinitd | |||
1968 | .put = snd_ice1712_pro_internal_clock_default_put | 1944 | .put = snd_ice1712_pro_internal_clock_default_put |
1969 | }; | 1945 | }; |
1970 | 1946 | ||
1971 | static int snd_ice1712_pro_rate_locking_info(struct snd_kcontrol *kcontrol, | 1947 | #define snd_ice1712_pro_rate_locking_info snd_ctl_boolean_mono_info |
1972 | struct snd_ctl_elem_info *uinfo) | ||
1973 | { | ||
1974 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1975 | uinfo->count = 1; | ||
1976 | uinfo->value.integer.min = 0; | ||
1977 | uinfo->value.integer.max = 1; | ||
1978 | return 0; | ||
1979 | } | ||
1980 | 1948 | ||
1981 | static int snd_ice1712_pro_rate_locking_get(struct snd_kcontrol *kcontrol, | 1949 | static int snd_ice1712_pro_rate_locking_get(struct snd_kcontrol *kcontrol, |
1982 | struct snd_ctl_elem_value *ucontrol) | 1950 | struct snd_ctl_elem_value *ucontrol) |
@@ -2007,15 +1975,7 @@ static struct snd_kcontrol_new snd_ice1712_pro_rate_locking __devinitdata = { | |||
2007 | .put = snd_ice1712_pro_rate_locking_put | 1975 | .put = snd_ice1712_pro_rate_locking_put |
2008 | }; | 1976 | }; |
2009 | 1977 | ||
2010 | static int snd_ice1712_pro_rate_reset_info(struct snd_kcontrol *kcontrol, | 1978 | #define snd_ice1712_pro_rate_reset_info snd_ctl_boolean_mono_info |
2011 | struct snd_ctl_elem_info *uinfo) | ||
2012 | { | ||
2013 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
2014 | uinfo->count = 1; | ||
2015 | uinfo->value.integer.min = 0; | ||
2016 | uinfo->value.integer.max = 1; | ||
2017 | return 0; | ||
2018 | } | ||
2019 | 1979 | ||
2020 | static int snd_ice1712_pro_rate_reset_get(struct snd_kcontrol *kcontrol, | 1980 | static int snd_ice1712_pro_rate_reset_get(struct snd_kcontrol *kcontrol, |
2021 | struct snd_ctl_elem_value *ucontrol) | 1981 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h index 6ac486d9c138..58640afa5404 100644 --- a/sound/pci/ice1712/ice1712.h +++ b/sound/pci/ice1712/ice1712.h | |||
@@ -4,7 +4,7 @@ | |||
4 | /* | 4 | /* |
5 | * ALSA driver for ICEnsemble ICE1712 (Envy24) | 5 | * ALSA driver for ICEnsemble ICE1712 (Envy24) |
6 | * | 6 | * |
7 | * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz> | 7 | * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz> |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License as published by | 10 | * it under the terms of the GNU General Public License as published by |
@@ -451,11 +451,10 @@ static inline void snd_ice1712_restore_gpio_status(struct snd_ice1712 *ice) | |||
451 | 451 | ||
452 | /* for bit controls */ | 452 | /* for bit controls */ |
453 | #define ICE1712_GPIO(xiface, xname, xindex, mask, invert, xaccess) \ | 453 | #define ICE1712_GPIO(xiface, xname, xindex, mask, invert, xaccess) \ |
454 | { .iface = xiface, .name = xname, .access = xaccess, .info = snd_ice1712_gpio_info, \ | 454 | { .iface = xiface, .name = xname, .access = xaccess, .info = snd_ctl_boolean_mono_info, \ |
455 | .get = snd_ice1712_gpio_get, .put = snd_ice1712_gpio_put, \ | 455 | .get = snd_ice1712_gpio_get, .put = snd_ice1712_gpio_put, \ |
456 | .private_value = mask | (invert << 24) } | 456 | .private_value = mask | (invert << 24) } |
457 | 457 | ||
458 | int snd_ice1712_gpio_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); | ||
459 | int snd_ice1712_gpio_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); | 458 | int snd_ice1712_gpio_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); |
460 | int snd_ice1712_gpio_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); | 459 | int snd_ice1712_gpio_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); |
461 | 460 | ||
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index ee620dea7ef3..0b0bbb0d96b9 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * ALSA driver for VT1724 ICEnsemble ICE1724 / VIA VT1724 (Envy24HT) | 2 | * ALSA driver for VT1724 ICEnsemble ICE1724 / VIA VT1724 (Envy24HT) |
3 | * VIA VT1720 (Envy24PT) | 3 | * VIA VT1720 (Envy24PT) |
4 | * | 4 | * |
5 | * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz> | 5 | * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz> |
6 | * 2002 James Stafford <jstafford@ampltd.com> | 6 | * 2002 James Stafford <jstafford@ampltd.com> |
7 | * 2003 Takashi Iwai <tiwai@suse.de> | 7 | * 2003 Takashi Iwai <tiwai@suse.de> |
8 | * | 8 | * |
@@ -52,7 +52,7 @@ | |||
52 | #include "phase.h" | 52 | #include "phase.h" |
53 | #include "wtm.h" | 53 | #include "wtm.h" |
54 | 54 | ||
55 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 55 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
56 | MODULE_DESCRIPTION("VIA ICEnsemble ICE1724/1720 (Envy24HT/PT)"); | 56 | MODULE_DESCRIPTION("VIA ICEnsemble ICE1724/1720 (Envy24HT/PT)"); |
57 | MODULE_LICENSE("GPL"); | 57 | MODULE_LICENSE("GPL"); |
58 | MODULE_SUPPORTED_DEVICE("{" | 58 | MODULE_SUPPORTED_DEVICE("{" |
@@ -341,10 +341,12 @@ static int snd_vt1724_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
341 | 341 | ||
342 | what = 0; | 342 | what = 0; |
343 | snd_pcm_group_for_each_entry(s, substream) { | 343 | snd_pcm_group_for_each_entry(s, substream) { |
344 | const struct vt1724_pcm_reg *reg; | 344 | if (snd_pcm_substream_chip(s) == ice) { |
345 | reg = s->runtime->private_data; | 345 | const struct vt1724_pcm_reg *reg; |
346 | what |= reg->start; | 346 | reg = s->runtime->private_data; |
347 | snd_pcm_trigger_done(s, substream); | 347 | what |= reg->start; |
348 | snd_pcm_trigger_done(s, substream); | ||
349 | } | ||
348 | } | 350 | } |
349 | 351 | ||
350 | switch (cmd) { | 352 | switch (cmd) { |
@@ -1479,15 +1481,7 @@ static struct snd_kcontrol_new snd_vt1724_spdif_maskp __devinitdata = | |||
1479 | .get = snd_vt1724_spdif_maskp_get, | 1481 | .get = snd_vt1724_spdif_maskp_get, |
1480 | }; | 1482 | }; |
1481 | 1483 | ||
1482 | static int snd_vt1724_spdif_sw_info(struct snd_kcontrol *kcontrol, | 1484 | #define snd_vt1724_spdif_sw_info snd_ctl_boolean_mono_info |
1483 | struct snd_ctl_elem_info *uinfo) | ||
1484 | { | ||
1485 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1486 | uinfo->count = 1; | ||
1487 | uinfo->value.integer.min = 0; | ||
1488 | uinfo->value.integer.max = 1; | ||
1489 | return 0; | ||
1490 | } | ||
1491 | 1485 | ||
1492 | static int snd_vt1724_spdif_sw_get(struct snd_kcontrol *kcontrol, | 1486 | static int snd_vt1724_spdif_sw_get(struct snd_kcontrol *kcontrol, |
1493 | struct snd_ctl_elem_value *ucontrol) | 1487 | struct snd_ctl_elem_value *ucontrol) |
@@ -1532,15 +1526,7 @@ static struct snd_kcontrol_new snd_vt1724_spdif_switch __devinitdata = | |||
1532 | * GPIO access from extern | 1526 | * GPIO access from extern |
1533 | */ | 1527 | */ |
1534 | 1528 | ||
1535 | int snd_vt1724_gpio_info(struct snd_kcontrol *kcontrol, | 1529 | #define snd_vt1724_gpio_info snd_ctl_boolean_mono_info |
1536 | struct snd_ctl_elem_info *uinfo) | ||
1537 | { | ||
1538 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1539 | uinfo->count = 1; | ||
1540 | uinfo->value.integer.min = 0; | ||
1541 | uinfo->value.integer.max = 1; | ||
1542 | return 0; | ||
1543 | } | ||
1544 | 1530 | ||
1545 | int snd_vt1724_gpio_get(struct snd_kcontrol *kcontrol, | 1531 | int snd_vt1724_gpio_get(struct snd_kcontrol *kcontrol, |
1546 | struct snd_ctl_elem_value *ucontrol) | 1532 | struct snd_ctl_elem_value *ucontrol) |
@@ -1706,15 +1692,7 @@ static struct snd_kcontrol_new snd_vt1724_pro_internal_clock __devinitdata = { | |||
1706 | .put = snd_vt1724_pro_internal_clock_put | 1692 | .put = snd_vt1724_pro_internal_clock_put |
1707 | }; | 1693 | }; |
1708 | 1694 | ||
1709 | static int snd_vt1724_pro_rate_locking_info(struct snd_kcontrol *kcontrol, | 1695 | #define snd_vt1724_pro_rate_locking_info snd_ctl_boolean_mono_info |
1710 | struct snd_ctl_elem_info *uinfo) | ||
1711 | { | ||
1712 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1713 | uinfo->count = 1; | ||
1714 | uinfo->value.integer.min = 0; | ||
1715 | uinfo->value.integer.max = 1; | ||
1716 | return 0; | ||
1717 | } | ||
1718 | 1696 | ||
1719 | static int snd_vt1724_pro_rate_locking_get(struct snd_kcontrol *kcontrol, | 1697 | static int snd_vt1724_pro_rate_locking_get(struct snd_kcontrol *kcontrol, |
1720 | struct snd_ctl_elem_value *ucontrol) | 1698 | struct snd_ctl_elem_value *ucontrol) |
@@ -1745,15 +1723,7 @@ static struct snd_kcontrol_new snd_vt1724_pro_rate_locking __devinitdata = { | |||
1745 | .put = snd_vt1724_pro_rate_locking_put | 1723 | .put = snd_vt1724_pro_rate_locking_put |
1746 | }; | 1724 | }; |
1747 | 1725 | ||
1748 | static int snd_vt1724_pro_rate_reset_info(struct snd_kcontrol *kcontrol, | 1726 | #define snd_vt1724_pro_rate_reset_info snd_ctl_boolean_mono_info |
1749 | struct snd_ctl_elem_info *uinfo) | ||
1750 | { | ||
1751 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1752 | uinfo->count = 1; | ||
1753 | uinfo->value.integer.min = 0; | ||
1754 | uinfo->value.integer.max = 1; | ||
1755 | return 0; | ||
1756 | } | ||
1757 | 1727 | ||
1758 | static int snd_vt1724_pro_rate_reset_get(struct snd_kcontrol *kcontrol, | 1728 | static int snd_vt1724_pro_rate_reset_get(struct snd_kcontrol *kcontrol, |
1759 | struct snd_ctl_elem_value *ucontrol) | 1729 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c index 3d8e74e493d7..1fbe3ef8e60a 100644 --- a/sound/pci/ice1712/juli.c +++ b/sound/pci/ice1712/juli.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Lowlevel functions for ESI Juli@ cards | 4 | * Lowlevel functions for ESI Juli@ cards |
5 | * | 5 | * |
6 | * Copyright (c) 2004 Jaroslav Kysela <perex@suse.cz> | 6 | * Copyright (c) 2004 Jaroslav Kysela <perex@perex.cz> |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
diff --git a/sound/pci/ice1712/phase.c b/sound/pci/ice1712/phase.c index 40a9098af777..3ac25058bb58 100644 --- a/sound/pci/ice1712/phase.c +++ b/sound/pci/ice1712/phase.c | |||
@@ -270,7 +270,7 @@ static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index, unsigned sho | |||
270 | /* | 270 | /* |
271 | * DAC mute control | 271 | * DAC mute control |
272 | */ | 272 | */ |
273 | #define wm_pcm_mute_info phase28_mono_bool_info | 273 | #define wm_pcm_mute_info snd_ctl_boolean_mono_info |
274 | 274 | ||
275 | static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 275 | static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
276 | { | 276 | { |
@@ -527,13 +527,7 @@ static int wm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value | |||
527 | /* | 527 | /* |
528 | * WM8770 master mute control | 528 | * WM8770 master mute control |
529 | */ | 529 | */ |
530 | static int wm_master_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { | 530 | #define wm_master_mute_info snd_ctl_boolean_stereo_info |
531 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
532 | uinfo->count = 2; | ||
533 | uinfo->value.integer.min = 0; | ||
534 | uinfo->value.integer.max = 1; | ||
535 | return 0; | ||
536 | } | ||
537 | 531 | ||
538 | static int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 532 | static int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
539 | { | 533 | { |
@@ -615,20 +609,9 @@ static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val | |||
615 | } | 609 | } |
616 | 610 | ||
617 | /* | 611 | /* |
618 | */ | ||
619 | static int phase28_mono_bool_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo) | ||
620 | { | ||
621 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
622 | uinfo->count = 1; | ||
623 | uinfo->value.integer.min = 0; | ||
624 | uinfo->value.integer.max = 1; | ||
625 | return 0; | ||
626 | } | ||
627 | |||
628 | /* | ||
629 | * Deemphasis | 612 | * Deemphasis |
630 | */ | 613 | */ |
631 | #define phase28_deemp_info phase28_mono_bool_info | 614 | #define phase28_deemp_info snd_ctl_boolean_mono_info |
632 | 615 | ||
633 | static int phase28_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 616 | static int phase28_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
634 | { | 617 | { |
diff --git a/sound/pci/ice1712/pontis.c b/sound/pci/ice1712/pontis.c index 01c69453ddeb..faefd52c1b80 100644 --- a/sound/pci/ice1712/pontis.c +++ b/sound/pci/ice1712/pontis.c | |||
@@ -216,14 +216,7 @@ static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val | |||
216 | /* | 216 | /* |
217 | * ADC input mux mixer control | 217 | * ADC input mux mixer control |
218 | */ | 218 | */ |
219 | static int wm_adc_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 219 | #define wm_adc_mux_info snd_ctl_boolean_mono_info |
220 | { | ||
221 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
222 | uinfo->count = 1; | ||
223 | uinfo->value.integer.min = 0; | ||
224 | uinfo->value.integer.max = 1; | ||
225 | return 0; | ||
226 | } | ||
227 | 220 | ||
228 | static int wm_adc_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 221 | static int wm_adc_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
229 | { | 222 | { |
@@ -260,14 +253,7 @@ static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val | |||
260 | /* | 253 | /* |
261 | * Analog bypass (In -> Out) | 254 | * Analog bypass (In -> Out) |
262 | */ | 255 | */ |
263 | static int wm_bypass_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 256 | #define wm_bypass_info snd_ctl_boolean_mono_info |
264 | { | ||
265 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
266 | uinfo->count = 1; | ||
267 | uinfo->value.integer.min = 0; | ||
268 | uinfo->value.integer.max = 1; | ||
269 | return 0; | ||
270 | } | ||
271 | 257 | ||
272 | static int wm_bypass_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 258 | static int wm_bypass_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
273 | { | 259 | { |
@@ -302,14 +288,7 @@ static int wm_bypass_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu | |||
302 | /* | 288 | /* |
303 | * Left/Right swap | 289 | * Left/Right swap |
304 | */ | 290 | */ |
305 | static int wm_chswap_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 291 | #define wm_chswap_info snd_ctl_boolean_mono_info |
306 | { | ||
307 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
308 | uinfo->count = 1; | ||
309 | uinfo->value.integer.min = 0; | ||
310 | uinfo->value.integer.max = 1; | ||
311 | return 0; | ||
312 | } | ||
313 | 292 | ||
314 | static int wm_chswap_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 293 | static int wm_chswap_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
315 | { | 294 | { |
diff --git a/sound/pci/ice1712/prodigy192.c b/sound/pci/ice1712/prodigy192.c index 4bae7305a79b..4180f9739ecb 100644 --- a/sound/pci/ice1712/prodigy192.c +++ b/sound/pci/ice1712/prodigy192.c | |||
@@ -81,14 +81,7 @@ static inline unsigned char stac9460_get(struct snd_ice1712 *ice, int reg) | |||
81 | /* | 81 | /* |
82 | * DAC mute control | 82 | * DAC mute control |
83 | */ | 83 | */ |
84 | static int stac9460_dac_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 84 | #define stac9460_dac_mute_info snd_ctl_boolean_mono_info |
85 | { | ||
86 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
87 | uinfo->count = 1; | ||
88 | uinfo->value.integer.min = 0; | ||
89 | uinfo->value.integer.max = 1; | ||
90 | return 0; | ||
91 | } | ||
92 | 85 | ||
93 | static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 86 | static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
94 | { | 87 | { |
@@ -177,14 +170,7 @@ static int stac9460_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el | |||
177 | /* | 170 | /* |
178 | * ADC mute control | 171 | * ADC mute control |
179 | */ | 172 | */ |
180 | static int stac9460_adc_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 173 | #define stac9460_adc_mute_info snd_ctl_boolean_stereo_info |
181 | { | ||
182 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
183 | uinfo->count = 2; | ||
184 | uinfo->value.integer.min = 0; | ||
185 | uinfo->value.integer.max = 1; | ||
186 | return 0; | ||
187 | } | ||
188 | 174 | ||
189 | static int stac9460_adc_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 175 | static int stac9460_adc_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
190 | { | 176 | { |
@@ -292,14 +278,7 @@ static int aureon_get_headphone_amp(struct snd_ice1712 *ice) | |||
292 | return ( tmp & AUREON_HP_SEL )!= 0; | 278 | return ( tmp & AUREON_HP_SEL )!= 0; |
293 | } | 279 | } |
294 | 280 | ||
295 | static int aureon_bool_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo) | 281 | #define aureon_bool_info snd_ctl_boolean_mono_info |
296 | { | ||
297 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
298 | uinfo->count = 1; | ||
299 | uinfo->value.integer.min = 0; | ||
300 | uinfo->value.integer.max = 1; | ||
301 | return 0; | ||
302 | } | ||
303 | 282 | ||
304 | static int aureon_hpamp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 283 | static int aureon_hpamp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
305 | { | 284 | { |
diff --git a/sound/pci/ice1712/wtm.c b/sound/pci/ice1712/wtm.c index 04e535c8542b..7fcce0a506d6 100644 --- a/sound/pci/ice1712/wtm.c +++ b/sound/pci/ice1712/wtm.c | |||
@@ -71,14 +71,7 @@ static inline unsigned char stac9460_2_get(struct snd_ice1712 *ice, int reg) | |||
71 | /* | 71 | /* |
72 | * DAC mute control | 72 | * DAC mute control |
73 | */ | 73 | */ |
74 | static int stac9460_dac_mute_info(struct snd_kcontrol *kcontrol, | 74 | #define stac9460_dac_mute_info snd_ctl_boolean_mono_info |
75 | struct snd_ctl_elem_info *uinfo) | ||
76 | { | ||
77 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
78 | uinfo->count = 1; | ||
79 | uinfo->value.integer.min = 0; | ||
80 | return 0; | ||
81 | } | ||
82 | 75 | ||
83 | static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol, | 76 | static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol, |
84 | struct snd_ctl_elem_value *ucontrol) | 77 | struct snd_ctl_elem_value *ucontrol) |
@@ -218,15 +211,7 @@ static int stac9460_dac_vol_put(struct snd_kcontrol *kcontrol, | |||
218 | /* | 211 | /* |
219 | * ADC mute control | 212 | * ADC mute control |
220 | */ | 213 | */ |
221 | static int stac9460_adc_mute_info(struct snd_kcontrol *kcontrol, | 214 | #define stac9460_adc_mute_info snd_ctl_boolean_stereo_info |
222 | struct snd_ctl_elem_info *uinfo) | ||
223 | { | ||
224 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
225 | uinfo->count = 2; | ||
226 | uinfo->value.integer.min = 0; | ||
227 | uinfo->value.integer.max = 1; | ||
228 | return 0; | ||
229 | } | ||
230 | 215 | ||
231 | static int stac9460_adc_mute_get(struct snd_kcontrol *kcontrol, | 216 | static int stac9460_adc_mute_get(struct snd_kcontrol *kcontrol, |
232 | struct snd_ctl_elem_value *ucontrol) | 217 | struct snd_ctl_elem_value *ucontrol) |
@@ -357,15 +342,7 @@ static int stac9460_adc_vol_put(struct snd_kcontrol *kcontrol, | |||
357 | * MIC / LINE switch fonction | 342 | * MIC / LINE switch fonction |
358 | */ | 343 | */ |
359 | 344 | ||
360 | static int stac9460_mic_sw_info(struct snd_kcontrol *kcontrol, | 345 | #define stac9460_mic_sw_info snd_ctl_boolean_mono_info |
361 | struct snd_ctl_elem_info *uinfo) | ||
362 | { | ||
363 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
364 | uinfo->count = 1; | ||
365 | uinfo->value.integer.min = 0; | ||
366 | uinfo->value.integer.max = 1; | ||
367 | return 0; | ||
368 | } | ||
369 | 346 | ||
370 | static int stac9460_mic_sw_get(struct snd_kcontrol *kcontrol, | 347 | static int stac9460_mic_sw_get(struct snd_kcontrol *kcontrol, |
371 | struct snd_ctl_elem_value *ucontrol) | 348 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index da9734073dba..b4a38a3d855b 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * ALSA driver for Intel ICH (i8x0) chipsets | 2 | * ALSA driver for Intel ICH (i8x0) chipsets |
3 | * | 3 | * |
4 | * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz> | 4 | * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz> |
5 | * | 5 | * |
6 | * | 6 | * |
7 | * This code also contains alpha support for SiS 735 chipsets provided | 7 | * This code also contains alpha support for SiS 735 chipsets provided |
@@ -43,7 +43,7 @@ | |||
43 | #include <asm/pgtable.h> | 43 | #include <asm/pgtable.h> |
44 | #include <asm/cacheflush.h> | 44 | #include <asm/cacheflush.h> |
45 | 45 | ||
46 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 46 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
47 | MODULE_DESCRIPTION("Intel 82801AA,82901AB,i810,i820,i830,i840,i845,MX440; SiS 7012; Ali 5455"); | 47 | MODULE_DESCRIPTION("Intel 82801AA,82901AB,i810,i820,i830,i840,i845,MX440; SiS 7012; Ali 5455"); |
48 | MODULE_LICENSE("GPL"); | 48 | MODULE_LICENSE("GPL"); |
49 | MODULE_SUPPORTED_DEVICE("{{Intel,82801AA-ICH}," | 49 | MODULE_SUPPORTED_DEVICE("{{Intel,82801AA-ICH}," |
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index c155e1f3a0e5..fad806e60f36 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * ALSA modem driver for Intel ICH (i8x0) chipsets | 2 | * ALSA modem driver for Intel ICH (i8x0) chipsets |
3 | * | 3 | * |
4 | * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz> | 4 | * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz> |
5 | * | 5 | * |
6 | * This is modified (by Sasha Khapyorsky <sashak@alsa-project.org>) version | 6 | * This is modified (by Sasha Khapyorsky <sashak@alsa-project.org>) version |
7 | * of ALSA ICH sound driver intel8x0.c . | 7 | * of ALSA ICH sound driver intel8x0.c . |
@@ -37,7 +37,7 @@ | |||
37 | #include <sound/info.h> | 37 | #include <sound/info.h> |
38 | #include <sound/initval.h> | 38 | #include <sound/initval.h> |
39 | 39 | ||
40 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 40 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
41 | MODULE_DESCRIPTION("Intel 82801AA,82901AB,i810,i820,i830,i840,i845,MX440; " | 41 | MODULE_DESCRIPTION("Intel 82801AA,82901AB,i810,i820,i830,i840,i845,MX440; " |
42 | "SiS 7013; NVidia MCP/2/2S/3 modems"); | 42 | "SiS 7013; NVidia MCP/2/2S/3 modems"); |
43 | MODULE_LICENSE("GPL"); | 43 | MODULE_LICENSE("GPL"); |
diff --git a/sound/pci/korg1212/Makefile b/sound/pci/korg1212/Makefile index 78c9dc6eeb2d..f11ce1b1b3d4 100644 --- a/sound/pci/korg1212/Makefile +++ b/sound/pci/korg1212/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-korg1212-objs := korg1212.o | 6 | snd-korg1212-objs := korg1212.o |
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c index 5338243fb035..c4af57fb5af1 100644 --- a/sound/pci/korg1212/korg1212.c +++ b/sound/pci/korg1212/korg1212.c | |||
@@ -1391,8 +1391,6 @@ static int snd_korg1212_playback_open(struct snd_pcm_substream *substream) | |||
1391 | K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_playback_open [%s]\n", | 1391 | K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_playback_open [%s]\n", |
1392 | stateName[korg1212->cardState]); | 1392 | stateName[korg1212->cardState]); |
1393 | 1393 | ||
1394 | snd_pcm_set_sync(substream); // ??? | ||
1395 | |||
1396 | snd_korg1212_OpenCard(korg1212); | 1394 | snd_korg1212_OpenCard(korg1212); |
1397 | 1395 | ||
1398 | runtime->hw = snd_korg1212_playback_info; | 1396 | runtime->hw = snd_korg1212_playback_info; |
@@ -1422,8 +1420,6 @@ static int snd_korg1212_capture_open(struct snd_pcm_substream *substream) | |||
1422 | K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_capture_open [%s]\n", | 1420 | K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_capture_open [%s]\n", |
1423 | stateName[korg1212->cardState]); | 1421 | stateName[korg1212->cardState]); |
1424 | 1422 | ||
1425 | snd_pcm_set_sync(substream); | ||
1426 | |||
1427 | snd_korg1212_OpenCard(korg1212); | 1423 | snd_korg1212_OpenCard(korg1212); |
1428 | 1424 | ||
1429 | runtime->hw = snd_korg1212_capture_info; | 1425 | runtime->hw = snd_korg1212_capture_info; |
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index 8a5ff1cb5362..32245770595e 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c | |||
@@ -1821,7 +1821,6 @@ snd_m3_playback_open(struct snd_pcm_substream *subs) | |||
1821 | return err; | 1821 | return err; |
1822 | 1822 | ||
1823 | runtime->hw = snd_m3_playback; | 1823 | runtime->hw = snd_m3_playback; |
1824 | snd_pcm_set_sync(subs); | ||
1825 | 1824 | ||
1826 | return 0; | 1825 | return 0; |
1827 | } | 1826 | } |
@@ -1846,7 +1845,6 @@ snd_m3_capture_open(struct snd_pcm_substream *subs) | |||
1846 | return err; | 1845 | return err; |
1847 | 1846 | ||
1848 | runtime->hw = snd_m3_capture; | 1847 | runtime->hw = snd_m3_capture; |
1849 | snd_pcm_set_sync(subs); | ||
1850 | 1848 | ||
1851 | return 0; | 1849 | return 0; |
1852 | } | 1850 | } |
diff --git a/sound/pci/mixart/Makefile b/sound/pci/mixart/Makefile index fe6ba0c4b567..cce159ec5624 100644 --- a/sound/pci/mixart/Makefile +++ b/sound/pci/mixart/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-mixart-objs := mixart.o mixart_core.o mixart_hwdep.o mixart_mixer.o | 6 | snd-mixart-objs := mixart.o mixart_core.o mixart_hwdep.o mixart_mixer.o |
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index ac007cec0879..880b824e24cd 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c | |||
@@ -652,7 +652,7 @@ static int snd_mixart_hw_free(struct snd_pcm_substream *subs) | |||
652 | static struct snd_pcm_hardware snd_mixart_analog_caps = | 652 | static struct snd_pcm_hardware snd_mixart_analog_caps = |
653 | { | 653 | { |
654 | .info = ( SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | | 654 | .info = ( SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | |
655 | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START | | 655 | SNDRV_PCM_INFO_MMAP_VALID | |
656 | SNDRV_PCM_INFO_PAUSE), | 656 | SNDRV_PCM_INFO_PAUSE), |
657 | .formats = ( SNDRV_PCM_FMTBIT_U8 | | 657 | .formats = ( SNDRV_PCM_FMTBIT_U8 | |
658 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | | 658 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | |
@@ -673,7 +673,7 @@ static struct snd_pcm_hardware snd_mixart_analog_caps = | |||
673 | static struct snd_pcm_hardware snd_mixart_digital_caps = | 673 | static struct snd_pcm_hardware snd_mixart_digital_caps = |
674 | { | 674 | { |
675 | .info = ( SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | | 675 | .info = ( SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | |
676 | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START | | 676 | SNDRV_PCM_INFO_MMAP_VALID | |
677 | SNDRV_PCM_INFO_PAUSE), | 677 | SNDRV_PCM_INFO_PAUSE), |
678 | .formats = ( SNDRV_PCM_FMTBIT_U8 | | 678 | .formats = ( SNDRV_PCM_FMTBIT_U8 | |
679 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | | 679 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | |
@@ -1317,6 +1317,12 @@ static int __devinit snd_mixart_probe(struct pci_dev *pci, | |||
1317 | mgr->mem[i].phys = pci_resource_start(pci, i); | 1317 | mgr->mem[i].phys = pci_resource_start(pci, i); |
1318 | mgr->mem[i].virt = ioremap_nocache(mgr->mem[i].phys, | 1318 | mgr->mem[i].virt = ioremap_nocache(mgr->mem[i].phys, |
1319 | pci_resource_len(pci, i)); | 1319 | pci_resource_len(pci, i)); |
1320 | if (!mgr->mem[i].virt) { | ||
1321 | printk(KERN_ERR "unable to remap resource 0x%lx\n", | ||
1322 | mgr->mem[i].phys); | ||
1323 | snd_mixart_free(mgr); | ||
1324 | return -EBUSY; | ||
1325 | } | ||
1320 | } | 1326 | } |
1321 | 1327 | ||
1322 | if (request_irq(pci->irq, snd_mixart_interrupt, IRQF_SHARED, | 1328 | if (request_irq(pci->irq, snd_mixart_interrupt, IRQF_SHARED, |
diff --git a/sound/pci/mixart/mixart_mixer.c b/sound/pci/mixart/mixart_mixer.c index d7d15c036e02..0e16512d25f7 100644 --- a/sound/pci/mixart/mixart_mixer.c +++ b/sound/pci/mixart/mixart_mixer.c | |||
@@ -403,14 +403,7 @@ static struct snd_kcontrol_new mixart_control_analog_level = { | |||
403 | }; | 403 | }; |
404 | 404 | ||
405 | /* shared */ | 405 | /* shared */ |
406 | static int mixart_sw_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 406 | #define mixart_sw_info snd_ctl_boolean_stereo_info |
407 | { | ||
408 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
409 | uinfo->count = 2; | ||
410 | uinfo->value.integer.min = 0; | ||
411 | uinfo->value.integer.max = 1; | ||
412 | return 0; | ||
413 | } | ||
414 | 407 | ||
415 | static int mixart_audio_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 408 | static int mixart_audio_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
416 | { | 409 | { |
diff --git a/sound/pci/nm256/Makefile b/sound/pci/nm256/Makefile index d91d8c519212..a1bd44ff850e 100644 --- a/sound/pci/nm256/Makefile +++ b/sound/pci/nm256/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-nm256-objs := nm256.o | 6 | snd-nm256-objs := nm256.o |
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index c7621bd770a6..276c5763f0e5 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c | |||
@@ -842,7 +842,6 @@ static void snd_nm256_setup_stream(struct nm256 *chip, struct nm256_stream *s, | |||
842 | runtime->private_data = s; | 842 | runtime->private_data = s; |
843 | s->substream = substream; | 843 | s->substream = substream; |
844 | 844 | ||
845 | snd_pcm_set_sync(substream); | ||
846 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | 845 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, |
847 | &constraints_rates); | 846 | &constraints_rates); |
848 | } | 847 | } |
diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c index f7f6a687f033..2d618bd7e62b 100644 --- a/sound/pci/pcxhr/pcxhr.c +++ b/sound/pci/pcxhr/pcxhr.c | |||
@@ -646,6 +646,8 @@ static int pcxhr_trigger(struct snd_pcm_substream *subs, int cmd) | |||
646 | if (snd_pcm_stream_linked(subs)) { | 646 | if (snd_pcm_stream_linked(subs)) { |
647 | struct snd_pcxhr *chip = snd_pcm_substream_chip(subs); | 647 | struct snd_pcxhr *chip = snd_pcm_substream_chip(subs); |
648 | snd_pcm_group_for_each_entry(s, subs) { | 648 | snd_pcm_group_for_each_entry(s, subs) { |
649 | if (snd_pcm_substream_chip(s) != chip) | ||
650 | continue; | ||
649 | stream = s->runtime->private_data; | 651 | stream = s->runtime->private_data; |
650 | stream->status = | 652 | stream->status = |
651 | PCXHR_STREAM_STATUS_SCHEDULE_RUN; | 653 | PCXHR_STREAM_STATUS_SCHEDULE_RUN; |
@@ -662,6 +664,7 @@ static int pcxhr_trigger(struct snd_pcm_substream *subs, int cmd) | |||
662 | if (pcxhr_update_r_buffer(stream)) | 664 | if (pcxhr_update_r_buffer(stream)) |
663 | return -EINVAL; | 665 | return -EINVAL; |
664 | 666 | ||
667 | stream->status = PCXHR_STREAM_STATUS_SCHEDULE_RUN; | ||
665 | if (pcxhr_set_stream_state(stream)) | 668 | if (pcxhr_set_stream_state(stream)) |
666 | return -EINVAL; | 669 | return -EINVAL; |
667 | stream->status = PCXHR_STREAM_STATUS_RUNNING; | 670 | stream->status = PCXHR_STREAM_STATUS_RUNNING; |
@@ -902,6 +905,8 @@ static int pcxhr_open(struct snd_pcm_substream *subs) | |||
902 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 4); | 905 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 4); |
903 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4); | 906 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4); |
904 | 907 | ||
908 | snd_pcm_set_sync(subs); | ||
909 | |||
905 | mgr->ref_count_rate++; | 910 | mgr->ref_count_rate++; |
906 | 911 | ||
907 | mutex_unlock(&mgr->setup_mutex); | 912 | mutex_unlock(&mgr->setup_mutex); |
diff --git a/sound/pci/pcxhr/pcxhr_mixer.c b/sound/pci/pcxhr/pcxhr_mixer.c index d9cc8d2beb6d..5f8d42633b04 100644 --- a/sound/pci/pcxhr/pcxhr_mixer.c +++ b/sound/pci/pcxhr/pcxhr_mixer.c | |||
@@ -44,8 +44,8 @@ | |||
44 | #define PCXHR_ANALOG_PLAYBACK_LEVEL_MAX 128 /* 0.0 dB */ | 44 | #define PCXHR_ANALOG_PLAYBACK_LEVEL_MAX 128 /* 0.0 dB */ |
45 | #define PCXHR_ANALOG_PLAYBACK_ZERO_LEVEL 104 /* -24.0 dB ( 0.0 dB - fix level +24.0 dB ) */ | 45 | #define PCXHR_ANALOG_PLAYBACK_ZERO_LEVEL 104 /* -24.0 dB ( 0.0 dB - fix level +24.0 dB ) */ |
46 | 46 | ||
47 | static const DECLARE_TLV_DB_SCALE(db_scale_analog_capture, -9600, 50, 0); | 47 | static const DECLARE_TLV_DB_SCALE(db_scale_analog_capture, -9600, 50, 3150); |
48 | static const DECLARE_TLV_DB_SCALE(db_scale_analog_playback, -12800, 100, 0); | 48 | static const DECLARE_TLV_DB_SCALE(db_scale_analog_playback, -10400, 100, 2400); |
49 | 49 | ||
50 | static int pcxhr_update_analog_audio_level(struct snd_pcxhr *chip, int is_capture, int channel) | 50 | static int pcxhr_update_analog_audio_level(struct snd_pcxhr *chip, int is_capture, int channel) |
51 | { | 51 | { |
@@ -144,14 +144,7 @@ static struct snd_kcontrol_new pcxhr_control_analog_level = { | |||
144 | }; | 144 | }; |
145 | 145 | ||
146 | /* shared */ | 146 | /* shared */ |
147 | static int pcxhr_sw_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 147 | #define pcxhr_sw_info snd_ctl_boolean_stereo_info |
148 | { | ||
149 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
150 | uinfo->count = 2; | ||
151 | uinfo->value.integer.min = 0; | ||
152 | uinfo->value.integer.max = 1; | ||
153 | return 0; | ||
154 | } | ||
155 | 148 | ||
156 | static int pcxhr_audio_sw_get(struct snd_kcontrol *kcontrol, | 149 | static int pcxhr_audio_sw_get(struct snd_kcontrol *kcontrol, |
157 | struct snd_ctl_elem_value *ucontrol) | 150 | struct snd_ctl_elem_value *ucontrol) |
@@ -195,7 +188,7 @@ static struct snd_kcontrol_new pcxhr_control_output_switch = { | |||
195 | #define PCXHR_DIGITAL_LEVEL_MAX 0x1ff /* +18 dB */ | 188 | #define PCXHR_DIGITAL_LEVEL_MAX 0x1ff /* +18 dB */ |
196 | #define PCXHR_DIGITAL_ZERO_LEVEL 0x1b7 /* 0 dB */ | 189 | #define PCXHR_DIGITAL_ZERO_LEVEL 0x1b7 /* 0 dB */ |
197 | 190 | ||
198 | static const DECLARE_TLV_DB_SCALE(db_scale_digital, -10950, 50, 0); | 191 | static const DECLARE_TLV_DB_SCALE(db_scale_digital, -10975, 25, 1800); |
199 | 192 | ||
200 | #define MORE_THAN_ONE_STREAM_LEVEL 0x000001 | 193 | #define MORE_THAN_ONE_STREAM_LEVEL 0x000001 |
201 | #define VALID_STREAM_PAN_LEVEL_MASK 0x800000 | 194 | #define VALID_STREAM_PAN_LEVEL_MASK 0x800000 |
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c index 618653e22561..1475912588e9 100644 --- a/sound/pci/rme32.c +++ b/sound/pci/rme32.c | |||
@@ -258,19 +258,6 @@ static inline unsigned int snd_rme32_pcm_byteptr(struct rme32 * rme32) | |||
258 | & RME32_RCR_AUDIO_ADDR_MASK); | 258 | & RME32_RCR_AUDIO_ADDR_MASK); |
259 | } | 259 | } |
260 | 260 | ||
261 | static int snd_rme32_ratecode(int rate) | ||
262 | { | ||
263 | switch (rate) { | ||
264 | case 32000: return SNDRV_PCM_RATE_32000; | ||
265 | case 44100: return SNDRV_PCM_RATE_44100; | ||
266 | case 48000: return SNDRV_PCM_RATE_48000; | ||
267 | case 64000: return SNDRV_PCM_RATE_64000; | ||
268 | case 88200: return SNDRV_PCM_RATE_88200; | ||
269 | case 96000: return SNDRV_PCM_RATE_96000; | ||
270 | } | ||
271 | return 0; | ||
272 | } | ||
273 | |||
274 | /* silence callback for halfduplex mode */ | 261 | /* silence callback for halfduplex mode */ |
275 | static int snd_rme32_playback_silence(struct snd_pcm_substream *substream, int channel, /* not used (interleaved data) */ | 262 | static int snd_rme32_playback_silence(struct snd_pcm_substream *substream, int channel, /* not used (interleaved data) */ |
276 | snd_pcm_uframes_t pos, | 263 | snd_pcm_uframes_t pos, |
@@ -887,7 +874,7 @@ static int snd_rme32_playback_spdif_open(struct snd_pcm_substream *substream) | |||
887 | if ((rme32->rcreg & RME32_RCR_KMODE) && | 874 | if ((rme32->rcreg & RME32_RCR_KMODE) && |
888 | (rate = snd_rme32_capture_getrate(rme32, &dummy)) > 0) { | 875 | (rate = snd_rme32_capture_getrate(rme32, &dummy)) > 0) { |
889 | /* AutoSync */ | 876 | /* AutoSync */ |
890 | runtime->hw.rates = snd_rme32_ratecode(rate); | 877 | runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); |
891 | runtime->hw.rate_min = rate; | 878 | runtime->hw.rate_min = rate; |
892 | runtime->hw.rate_max = rate; | 879 | runtime->hw.rate_max = rate; |
893 | } | 880 | } |
@@ -929,7 +916,7 @@ static int snd_rme32_capture_spdif_open(struct snd_pcm_substream *substream) | |||
929 | if (isadat) { | 916 | if (isadat) { |
930 | return -EIO; | 917 | return -EIO; |
931 | } | 918 | } |
932 | runtime->hw.rates = snd_rme32_ratecode(rate); | 919 | runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); |
933 | runtime->hw.rate_min = rate; | 920 | runtime->hw.rate_min = rate; |
934 | runtime->hw.rate_max = rate; | 921 | runtime->hw.rate_max = rate; |
935 | } | 922 | } |
@@ -965,7 +952,7 @@ snd_rme32_playback_adat_open(struct snd_pcm_substream *substream) | |||
965 | if ((rme32->rcreg & RME32_RCR_KMODE) && | 952 | if ((rme32->rcreg & RME32_RCR_KMODE) && |
966 | (rate = snd_rme32_capture_getrate(rme32, &dummy)) > 0) { | 953 | (rate = snd_rme32_capture_getrate(rme32, &dummy)) > 0) { |
967 | /* AutoSync */ | 954 | /* AutoSync */ |
968 | runtime->hw.rates = snd_rme32_ratecode(rate); | 955 | runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); |
969 | runtime->hw.rate_min = rate; | 956 | runtime->hw.rate_min = rate; |
970 | runtime->hw.rate_max = rate; | 957 | runtime->hw.rate_max = rate; |
971 | } | 958 | } |
@@ -989,7 +976,7 @@ snd_rme32_capture_adat_open(struct snd_pcm_substream *substream) | |||
989 | if (!isadat) { | 976 | if (!isadat) { |
990 | return -EIO; | 977 | return -EIO; |
991 | } | 978 | } |
992 | runtime->hw.rates = snd_rme32_ratecode(rate); | 979 | runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); |
993 | runtime->hw.rate_min = rate; | 980 | runtime->hw.rate_min = rate; |
994 | runtime->hw.rate_max = rate; | 981 | runtime->hw.rate_max = rate; |
995 | } | 982 | } |
@@ -1582,16 +1569,8 @@ static void __devinit snd_rme32_proc_init(struct rme32 * rme32) | |||
1582 | * control interface | 1569 | * control interface |
1583 | */ | 1570 | */ |
1584 | 1571 | ||
1585 | static int | 1572 | #define snd_rme32_info_loopback_control snd_ctl_boolean_mono_info |
1586 | snd_rme32_info_loopback_control(struct snd_kcontrol *kcontrol, | 1573 | |
1587 | struct snd_ctl_elem_info *uinfo) | ||
1588 | { | ||
1589 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1590 | uinfo->count = 1; | ||
1591 | uinfo->value.integer.min = 0; | ||
1592 | uinfo->value.integer.max = 1; | ||
1593 | return 0; | ||
1594 | } | ||
1595 | static int | 1574 | static int |
1596 | snd_rme32_get_loopback_control(struct snd_kcontrol *kcontrol, | 1575 | snd_rme32_get_loopback_control(struct snd_kcontrol *kcontrol, |
1597 | struct snd_ctl_elem_value *ucontrol) | 1576 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c index e3304b7ccbcb..0b3c532c4014 100644 --- a/sound/pci/rme96.c +++ b/sound/pci/rme96.c | |||
@@ -301,20 +301,6 @@ snd_rme96_capture_ptr(struct rme96 *rme96) | |||
301 | } | 301 | } |
302 | 302 | ||
303 | static int | 303 | static int |
304 | snd_rme96_ratecode(int rate) | ||
305 | { | ||
306 | switch (rate) { | ||
307 | case 32000: return SNDRV_PCM_RATE_32000; | ||
308 | case 44100: return SNDRV_PCM_RATE_44100; | ||
309 | case 48000: return SNDRV_PCM_RATE_48000; | ||
310 | case 64000: return SNDRV_PCM_RATE_64000; | ||
311 | case 88200: return SNDRV_PCM_RATE_88200; | ||
312 | case 96000: return SNDRV_PCM_RATE_96000; | ||
313 | } | ||
314 | return 0; | ||
315 | } | ||
316 | |||
317 | static int | ||
318 | snd_rme96_playback_silence(struct snd_pcm_substream *substream, | 304 | snd_rme96_playback_silence(struct snd_pcm_substream *substream, |
319 | int channel, /* not used (interleaved data) */ | 305 | int channel, /* not used (interleaved data) */ |
320 | snd_pcm_uframes_t pos, | 306 | snd_pcm_uframes_t pos, |
@@ -1176,8 +1162,6 @@ snd_rme96_playback_spdif_open(struct snd_pcm_substream *substream) | |||
1176 | struct rme96 *rme96 = snd_pcm_substream_chip(substream); | 1162 | struct rme96 *rme96 = snd_pcm_substream_chip(substream); |
1177 | struct snd_pcm_runtime *runtime = substream->runtime; | 1163 | struct snd_pcm_runtime *runtime = substream->runtime; |
1178 | 1164 | ||
1179 | snd_pcm_set_sync(substream); | ||
1180 | |||
1181 | spin_lock_irq(&rme96->lock); | 1165 | spin_lock_irq(&rme96->lock); |
1182 | if (rme96->playback_substream != NULL) { | 1166 | if (rme96->playback_substream != NULL) { |
1183 | spin_unlock_irq(&rme96->lock); | 1167 | spin_unlock_irq(&rme96->lock); |
@@ -1194,7 +1178,7 @@ snd_rme96_playback_spdif_open(struct snd_pcm_substream *substream) | |||
1194 | (rate = snd_rme96_capture_getrate(rme96, &dummy)) > 0) | 1178 | (rate = snd_rme96_capture_getrate(rme96, &dummy)) > 0) |
1195 | { | 1179 | { |
1196 | /* slave clock */ | 1180 | /* slave clock */ |
1197 | runtime->hw.rates = snd_rme96_ratecode(rate); | 1181 | runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); |
1198 | runtime->hw.rate_min = rate; | 1182 | runtime->hw.rate_min = rate; |
1199 | runtime->hw.rate_max = rate; | 1183 | runtime->hw.rate_max = rate; |
1200 | } | 1184 | } |
@@ -1214,8 +1198,6 @@ snd_rme96_capture_spdif_open(struct snd_pcm_substream *substream) | |||
1214 | struct rme96 *rme96 = snd_pcm_substream_chip(substream); | 1198 | struct rme96 *rme96 = snd_pcm_substream_chip(substream); |
1215 | struct snd_pcm_runtime *runtime = substream->runtime; | 1199 | struct snd_pcm_runtime *runtime = substream->runtime; |
1216 | 1200 | ||
1217 | snd_pcm_set_sync(substream); | ||
1218 | |||
1219 | runtime->hw = snd_rme96_capture_spdif_info; | 1201 | runtime->hw = snd_rme96_capture_spdif_info; |
1220 | if (snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG && | 1202 | if (snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG && |
1221 | (rate = snd_rme96_capture_getrate(rme96, &isadat)) > 0) | 1203 | (rate = snd_rme96_capture_getrate(rme96, &isadat)) > 0) |
@@ -1223,7 +1205,7 @@ snd_rme96_capture_spdif_open(struct snd_pcm_substream *substream) | |||
1223 | if (isadat) { | 1205 | if (isadat) { |
1224 | return -EIO; | 1206 | return -EIO; |
1225 | } | 1207 | } |
1226 | runtime->hw.rates = snd_rme96_ratecode(rate); | 1208 | runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); |
1227 | runtime->hw.rate_min = rate; | 1209 | runtime->hw.rate_min = rate; |
1228 | runtime->hw.rate_max = rate; | 1210 | runtime->hw.rate_max = rate; |
1229 | } | 1211 | } |
@@ -1247,8 +1229,6 @@ snd_rme96_playback_adat_open(struct snd_pcm_substream *substream) | |||
1247 | struct rme96 *rme96 = snd_pcm_substream_chip(substream); | 1229 | struct rme96 *rme96 = snd_pcm_substream_chip(substream); |
1248 | struct snd_pcm_runtime *runtime = substream->runtime; | 1230 | struct snd_pcm_runtime *runtime = substream->runtime; |
1249 | 1231 | ||
1250 | snd_pcm_set_sync(substream); | ||
1251 | |||
1252 | spin_lock_irq(&rme96->lock); | 1232 | spin_lock_irq(&rme96->lock); |
1253 | if (rme96->playback_substream != NULL) { | 1233 | if (rme96->playback_substream != NULL) { |
1254 | spin_unlock_irq(&rme96->lock); | 1234 | spin_unlock_irq(&rme96->lock); |
@@ -1265,7 +1245,7 @@ snd_rme96_playback_adat_open(struct snd_pcm_substream *substream) | |||
1265 | (rate = snd_rme96_capture_getrate(rme96, &dummy)) > 0) | 1245 | (rate = snd_rme96_capture_getrate(rme96, &dummy)) > 0) |
1266 | { | 1246 | { |
1267 | /* slave clock */ | 1247 | /* slave clock */ |
1268 | runtime->hw.rates = snd_rme96_ratecode(rate); | 1248 | runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); |
1269 | runtime->hw.rate_min = rate; | 1249 | runtime->hw.rate_min = rate; |
1270 | runtime->hw.rate_max = rate; | 1250 | runtime->hw.rate_max = rate; |
1271 | } | 1251 | } |
@@ -1280,8 +1260,6 @@ snd_rme96_capture_adat_open(struct snd_pcm_substream *substream) | |||
1280 | struct rme96 *rme96 = snd_pcm_substream_chip(substream); | 1260 | struct rme96 *rme96 = snd_pcm_substream_chip(substream); |
1281 | struct snd_pcm_runtime *runtime = substream->runtime; | 1261 | struct snd_pcm_runtime *runtime = substream->runtime; |
1282 | 1262 | ||
1283 | snd_pcm_set_sync(substream); | ||
1284 | |||
1285 | runtime->hw = snd_rme96_capture_adat_info; | 1263 | runtime->hw = snd_rme96_capture_adat_info; |
1286 | if (snd_rme96_getinputtype(rme96) == RME96_INPUT_ANALOG) { | 1264 | if (snd_rme96_getinputtype(rme96) == RME96_INPUT_ANALOG) { |
1287 | /* makes no sense to use analog input. Note that analog | 1265 | /* makes no sense to use analog input. Note that analog |
@@ -1292,7 +1270,7 @@ snd_rme96_capture_adat_open(struct snd_pcm_substream *substream) | |||
1292 | if (!isadat) { | 1270 | if (!isadat) { |
1293 | return -EIO; | 1271 | return -EIO; |
1294 | } | 1272 | } |
1295 | runtime->hw.rates = snd_rme96_ratecode(rate); | 1273 | runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); |
1296 | runtime->hw.rate_min = rate; | 1274 | runtime->hw.rate_min = rate; |
1297 | runtime->hw.rate_max = rate; | 1275 | runtime->hw.rate_max = rate; |
1298 | } | 1276 | } |
@@ -1826,15 +1804,8 @@ snd_rme96_proc_init(struct rme96 *rme96) | |||
1826 | * control interface | 1804 | * control interface |
1827 | */ | 1805 | */ |
1828 | 1806 | ||
1829 | static int | 1807 | #define snd_rme96_info_loopback_control snd_ctl_boolean_mono_info |
1830 | snd_rme96_info_loopback_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1808 | |
1831 | { | ||
1832 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1833 | uinfo->count = 1; | ||
1834 | uinfo->value.integer.min = 0; | ||
1835 | uinfo->value.integer.max = 1; | ||
1836 | return 0; | ||
1837 | } | ||
1838 | static int | 1809 | static int |
1839 | snd_rme96_get_loopback_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1810 | snd_rme96_get_loopback_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1840 | { | 1811 | { |
diff --git a/sound/pci/rme9652/Makefile b/sound/pci/rme9652/Makefile index d2c294e136f9..dcba56040205 100644 --- a/sound/pci/rme9652/Makefile +++ b/sound/pci/rme9652/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-rme9652-objs := rme9652.o | 6 | snd-rme9652-objs := rme9652.o |
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index 3b3ef657f73e..ff26a3672d40 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c | |||
@@ -606,28 +606,28 @@ static void snd_hdsp_9652_enable_mixer (struct hdsp *hdsp); | |||
606 | 606 | ||
607 | static int hdsp_playback_to_output_key (struct hdsp *hdsp, int in, int out) | 607 | static int hdsp_playback_to_output_key (struct hdsp *hdsp, int in, int out) |
608 | { | 608 | { |
609 | switch (hdsp->firmware_rev) { | 609 | switch (hdsp->io_type) { |
610 | case 0xa: | 610 | case Multiface: |
611 | case Digiface: | ||
612 | default: | ||
611 | return (64 * out) + (32 + (in)); | 613 | return (64 * out) + (32 + (in)); |
612 | case 0x96: | 614 | case H9632: |
613 | case 0x97: | ||
614 | case 0x98: | ||
615 | return (32 * out) + (16 + (in)); | 615 | return (32 * out) + (16 + (in)); |
616 | default: | 616 | case H9652: |
617 | return (52 * out) + (26 + (in)); | 617 | return (52 * out) + (26 + (in)); |
618 | } | 618 | } |
619 | } | 619 | } |
620 | 620 | ||
621 | static int hdsp_input_to_output_key (struct hdsp *hdsp, int in, int out) | 621 | static int hdsp_input_to_output_key (struct hdsp *hdsp, int in, int out) |
622 | { | 622 | { |
623 | switch (hdsp->firmware_rev) { | 623 | switch (hdsp->io_type) { |
624 | case 0xa: | 624 | case Multiface: |
625 | case Digiface: | ||
626 | default: | ||
625 | return (64 * out) + in; | 627 | return (64 * out) + in; |
626 | case 0x96: | 628 | case H9632: |
627 | case 0x97: | ||
628 | case 0x98: | ||
629 | return (32 * out) + in; | 629 | return (32 * out) + in; |
630 | default: | 630 | case H9652: |
631 | return (52 * out) + in; | 631 | return (52 * out) + in; |
632 | } | 632 | } |
633 | } | 633 | } |
@@ -1623,14 +1623,7 @@ static int hdsp_set_spdif_output(struct hdsp *hdsp, int out) | |||
1623 | return 0; | 1623 | return 0; |
1624 | } | 1624 | } |
1625 | 1625 | ||
1626 | static int snd_hdsp_info_spdif_bits(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1626 | #define snd_hdsp_info_spdif_bits snd_ctl_boolean_mono_info |
1627 | { | ||
1628 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1629 | uinfo->count = 1; | ||
1630 | uinfo->value.integer.min = 0; | ||
1631 | uinfo->value.integer.max = 1; | ||
1632 | return 0; | ||
1633 | } | ||
1634 | 1627 | ||
1635 | static int snd_hdsp_get_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1628 | static int snd_hdsp_get_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1636 | { | 1629 | { |
@@ -2111,14 +2104,7 @@ static int snd_hdsp_put_clock_source(struct snd_kcontrol *kcontrol, struct snd_c | |||
2111 | return change; | 2104 | return change; |
2112 | } | 2105 | } |
2113 | 2106 | ||
2114 | static int snd_hdsp_info_clock_source_lock(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 2107 | #define snd_hdsp_info_clock_source_lock snd_ctl_boolean_mono_info |
2115 | { | ||
2116 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
2117 | uinfo->count = 1; | ||
2118 | uinfo->value.integer.min = 0; | ||
2119 | uinfo->value.integer.max = 1; | ||
2120 | return 0; | ||
2121 | } | ||
2122 | 2108 | ||
2123 | static int snd_hdsp_get_clock_source_lock(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 2109 | static int snd_hdsp_get_clock_source_lock(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
2124 | { | 2110 | { |
@@ -2420,14 +2406,7 @@ static int hdsp_set_xlr_breakout_cable(struct hdsp *hdsp, int mode) | |||
2420 | return 0; | 2406 | return 0; |
2421 | } | 2407 | } |
2422 | 2408 | ||
2423 | static int snd_hdsp_info_xlr_breakout_cable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 2409 | #define snd_hdsp_info_xlr_breakout_cable snd_ctl_boolean_mono_info |
2424 | { | ||
2425 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
2426 | uinfo->count = 1; | ||
2427 | uinfo->value.integer.min = 0; | ||
2428 | uinfo->value.integer.max = 1; | ||
2429 | return 0; | ||
2430 | } | ||
2431 | 2410 | ||
2432 | static int snd_hdsp_get_xlr_breakout_cable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 2411 | static int snd_hdsp_get_xlr_breakout_cable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
2433 | { | 2412 | { |
@@ -2483,14 +2462,7 @@ static int hdsp_set_aeb(struct hdsp *hdsp, int mode) | |||
2483 | return 0; | 2462 | return 0; |
2484 | } | 2463 | } |
2485 | 2464 | ||
2486 | static int snd_hdsp_info_aeb(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 2465 | #define snd_hdsp_info_aeb snd_ctl_boolean_mono_info |
2487 | { | ||
2488 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
2489 | uinfo->count = 1; | ||
2490 | uinfo->value.integer.min = 0; | ||
2491 | uinfo->value.integer.max = 1; | ||
2492 | return 0; | ||
2493 | } | ||
2494 | 2466 | ||
2495 | static int snd_hdsp_get_aeb(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 2467 | static int snd_hdsp_get_aeb(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
2496 | { | 2468 | { |
@@ -2729,14 +2701,7 @@ static int hdsp_set_line_output(struct hdsp *hdsp, int out) | |||
2729 | return 0; | 2701 | return 0; |
2730 | } | 2702 | } |
2731 | 2703 | ||
2732 | static int snd_hdsp_info_line_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 2704 | #define snd_hdsp_info_line_out snd_ctl_boolean_mono_info |
2733 | { | ||
2734 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
2735 | uinfo->count = 1; | ||
2736 | uinfo->value.integer.min = 0; | ||
2737 | uinfo->value.integer.max = 1; | ||
2738 | return 0; | ||
2739 | } | ||
2740 | 2705 | ||
2741 | static int snd_hdsp_get_line_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 2706 | static int snd_hdsp_get_line_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
2742 | { | 2707 | { |
@@ -2782,14 +2747,7 @@ static int hdsp_set_precise_pointer(struct hdsp *hdsp, int precise) | |||
2782 | return 0; | 2747 | return 0; |
2783 | } | 2748 | } |
2784 | 2749 | ||
2785 | static int snd_hdsp_info_precise_pointer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 2750 | #define snd_hdsp_info_precise_pointer snd_ctl_boolean_mono_info |
2786 | { | ||
2787 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
2788 | uinfo->count = 1; | ||
2789 | uinfo->value.integer.min = 0; | ||
2790 | uinfo->value.integer.max = 1; | ||
2791 | return 0; | ||
2792 | } | ||
2793 | 2751 | ||
2794 | static int snd_hdsp_get_precise_pointer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 2752 | static int snd_hdsp_get_precise_pointer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
2795 | { | 2753 | { |
@@ -2835,14 +2793,7 @@ static int hdsp_set_use_midi_tasklet(struct hdsp *hdsp, int use_tasklet) | |||
2835 | return 0; | 2793 | return 0; |
2836 | } | 2794 | } |
2837 | 2795 | ||
2838 | static int snd_hdsp_info_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 2796 | #define snd_hdsp_info_use_midi_tasklet snd_ctl_boolean_mono_info |
2839 | { | ||
2840 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
2841 | uinfo->count = 1; | ||
2842 | uinfo->value.integer.min = 0; | ||
2843 | uinfo->value.integer.max = 1; | ||
2844 | return 0; | ||
2845 | } | ||
2846 | 2797 | ||
2847 | static int snd_hdsp_get_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 2798 | static int snd_hdsp_get_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
2848 | { | 2799 | { |
@@ -3108,6 +3059,9 @@ static int hdsp_dds_offset(struct hdsp *hdsp) | |||
3108 | unsigned int dds_value = hdsp->dds_value; | 3059 | unsigned int dds_value = hdsp->dds_value; |
3109 | int system_sample_rate = hdsp->system_sample_rate; | 3060 | int system_sample_rate = hdsp->system_sample_rate; |
3110 | 3061 | ||
3062 | if (!dds_value) | ||
3063 | return 0; | ||
3064 | |||
3111 | n = DDS_NUMERATOR; | 3065 | n = DDS_NUMERATOR; |
3112 | /* | 3066 | /* |
3113 | * dds_value = n / rate | 3067 | * dds_value = n / rate |
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 143185e7e4dc..f1bdda6cbcff 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c | |||
@@ -1,5 +1,4 @@ | |||
1 | /* -*- linux-c -*- | 1 | /* |
2 | * | ||
3 | * ALSA driver for RME Hammerfall DSP MADI audio interface(s) | 2 | * ALSA driver for RME Hammerfall DSP MADI audio interface(s) |
4 | * | 3 | * |
5 | * Copyright (c) 2003 Winfried Ritsch (IEM) | 4 | * Copyright (c) 2003 Winfried Ritsch (IEM) |
@@ -78,7 +77,8 @@ MODULE_PARM_DESC(enable_monitor, | |||
78 | "Enable Analog Out on Channel 63/64 by default."); | 77 | "Enable Analog Out on Channel 63/64 by default."); |
79 | 78 | ||
80 | MODULE_AUTHOR | 79 | MODULE_AUTHOR |
81 | ("Winfried Ritsch <ritsch_AT_iem.at>, Paul Davis <paul@linuxaudiosystems.com>, " | 80 | ("Winfried Ritsch <ritsch_AT_iem.at>, " |
81 | "Paul Davis <paul@linuxaudiosystems.com>, " | ||
82 | "Marcus Andersson, Thomas Charbonnel <thomas@undata.org>, " | 82 | "Marcus Andersson, Thomas Charbonnel <thomas@undata.org>, " |
83 | "Remy Bruno <remy.bruno@trinnov.com>"); | 83 | "Remy Bruno <remy.bruno@trinnov.com>"); |
84 | MODULE_DESCRIPTION("RME HDSPM"); | 84 | MODULE_DESCRIPTION("RME HDSPM"); |
@@ -161,7 +161,9 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
161 | 0=off, 1=on */ /* MADI ONLY */ | 161 | 0=off, 1=on */ /* MADI ONLY */ |
162 | #define HDSPM_Dolby (1<<11) /* Dolby = "NonAudio" ?? */ /* AES32 ONLY */ | 162 | #define HDSPM_Dolby (1<<11) /* Dolby = "NonAudio" ?? */ /* AES32 ONLY */ |
163 | 163 | ||
164 | #define HDSPM_InputSelect0 (1<<14) /* Input select 0= optical, 1=coax */ /* MADI ONLY*/ | 164 | #define HDSPM_InputSelect0 (1<<14) /* Input select 0= optical, 1=coax |
165 | * -- MADI ONLY | ||
166 | */ | ||
165 | #define HDSPM_InputSelect1 (1<<15) /* should be 0 */ | 167 | #define HDSPM_InputSelect1 (1<<15) /* should be 0 */ |
166 | 168 | ||
167 | #define HDSPM_SyncRef0 (1<<16) /* 0=WOrd, 1=MADI */ | 169 | #define HDSPM_SyncRef0 (1<<16) /* 0=WOrd, 1=MADI */ |
@@ -189,11 +191,13 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
189 | 191 | ||
190 | /* --- bit helper defines */ | 192 | /* --- bit helper defines */ |
191 | #define HDSPM_LatencyMask (HDSPM_Latency0|HDSPM_Latency1|HDSPM_Latency2) | 193 | #define HDSPM_LatencyMask (HDSPM_Latency0|HDSPM_Latency1|HDSPM_Latency2) |
192 | #define HDSPM_FrequencyMask (HDSPM_Frequency0|HDSPM_Frequency1|HDSPM_DoubleSpeed|HDSPM_QuadSpeed) | 194 | #define HDSPM_FrequencyMask (HDSPM_Frequency0|HDSPM_Frequency1|\ |
195 | HDSPM_DoubleSpeed|HDSPM_QuadSpeed) | ||
193 | #define HDSPM_InputMask (HDSPM_InputSelect0|HDSPM_InputSelect1) | 196 | #define HDSPM_InputMask (HDSPM_InputSelect0|HDSPM_InputSelect1) |
194 | #define HDSPM_InputOptical 0 | 197 | #define HDSPM_InputOptical 0 |
195 | #define HDSPM_InputCoaxial (HDSPM_InputSelect0) | 198 | #define HDSPM_InputCoaxial (HDSPM_InputSelect0) |
196 | #define HDSPM_SyncRefMask (HDSPM_SyncRef0|HDSPM_SyncRef1|HDSPM_SyncRef2|HDSPM_SyncRef3) | 199 | #define HDSPM_SyncRefMask (HDSPM_SyncRef0|HDSPM_SyncRef1|\ |
200 | HDSPM_SyncRef2|HDSPM_SyncRef3) | ||
197 | #define HDSPM_SyncRef_Word 0 | 201 | #define HDSPM_SyncRef_Word 0 |
198 | #define HDSPM_SyncRef_MADI (HDSPM_SyncRef0) | 202 | #define HDSPM_SyncRef_MADI (HDSPM_SyncRef0) |
199 | 203 | ||
@@ -205,10 +209,12 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
205 | #define HDSPM_Frequency48KHz (HDSPM_Frequency1|HDSPM_Frequency0) | 209 | #define HDSPM_Frequency48KHz (HDSPM_Frequency1|HDSPM_Frequency0) |
206 | #define HDSPM_Frequency64KHz (HDSPM_DoubleSpeed|HDSPM_Frequency0) | 210 | #define HDSPM_Frequency64KHz (HDSPM_DoubleSpeed|HDSPM_Frequency0) |
207 | #define HDSPM_Frequency88_2KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1) | 211 | #define HDSPM_Frequency88_2KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1) |
208 | #define HDSPM_Frequency96KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1|HDSPM_Frequency0) | 212 | #define HDSPM_Frequency96KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1|\ |
213 | HDSPM_Frequency0) | ||
209 | #define HDSPM_Frequency128KHz (HDSPM_QuadSpeed|HDSPM_Frequency0) | 214 | #define HDSPM_Frequency128KHz (HDSPM_QuadSpeed|HDSPM_Frequency0) |
210 | #define HDSPM_Frequency176_4KHz (HDSPM_QuadSpeed|HDSPM_Frequency1) | 215 | #define HDSPM_Frequency176_4KHz (HDSPM_QuadSpeed|HDSPM_Frequency1) |
211 | #define HDSPM_Frequency192KHz (HDSPM_QuadSpeed|HDSPM_Frequency1|HDSPM_Frequency0) | 216 | #define HDSPM_Frequency192KHz (HDSPM_QuadSpeed|HDSPM_Frequency1|\ |
217 | HDSPM_Frequency0) | ||
212 | 218 | ||
213 | /* --- for internal discrimination */ | 219 | /* --- for internal discrimination */ |
214 | #define HDSPM_CLOCK_SOURCE_AUTOSYNC 0 /* Sample Clock Sources */ | 220 | #define HDSPM_CLOCK_SOURCE_AUTOSYNC 0 /* Sample Clock Sources */ |
@@ -256,10 +262,14 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
256 | #define HDSPM_RD_MULTIPLE (1<<10) | 262 | #define HDSPM_RD_MULTIPLE (1<<10) |
257 | 263 | ||
258 | /* --- Status Register bits --- */ /* MADI ONLY */ /* Bits defined here and | 264 | /* --- Status Register bits --- */ /* MADI ONLY */ /* Bits defined here and |
259 | that do not conflict with specific bits for AES32 seem to be valid also for the AES32 */ | 265 | that do not conflict with specific bits for AES32 seem to be valid also |
266 | for the AES32 | ||
267 | */ | ||
260 | #define HDSPM_audioIRQPending (1<<0) /* IRQ is high and pending */ | 268 | #define HDSPM_audioIRQPending (1<<0) /* IRQ is high and pending */ |
261 | #define HDSPM_RX_64ch (1<<1) /* Input 64chan. MODE=1, 56chn. MODE=0 */ | 269 | #define HDSPM_RX_64ch (1<<1) /* Input 64chan. MODE=1, 56chn MODE=0 */ |
262 | #define HDSPM_AB_int (1<<2) /* InputChannel Opt=0, Coax=1 (like inp0) */ | 270 | #define HDSPM_AB_int (1<<2) /* InputChannel Opt=0, Coax=1 |
271 | * (like inp0) | ||
272 | */ | ||
263 | #define HDSPM_madiLock (1<<3) /* MADI Locked =1, no=0 */ | 273 | #define HDSPM_madiLock (1<<3) /* MADI Locked =1, no=0 */ |
264 | 274 | ||
265 | #define HDSPM_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */ | 275 | #define HDSPM_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */ |
@@ -274,12 +284,15 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
274 | #define HDSPM_madiFreq2 (1<<24) /* 4=64, 5=88.2 6=96 */ | 284 | #define HDSPM_madiFreq2 (1<<24) /* 4=64, 5=88.2 6=96 */ |
275 | #define HDSPM_madiFreq3 (1<<25) /* 7=128, 8=176.4 9=192 */ | 285 | #define HDSPM_madiFreq3 (1<<25) /* 7=128, 8=176.4 9=192 */ |
276 | 286 | ||
277 | #define HDSPM_BufferID (1<<26) /* (Double)Buffer ID toggles with Interrupt */ | 287 | #define HDSPM_BufferID (1<<26) /* (Double)Buffer ID toggles with |
288 | * Interrupt | ||
289 | */ | ||
278 | #define HDSPM_midi0IRQPending (1<<30) /* MIDI IRQ is pending */ | 290 | #define HDSPM_midi0IRQPending (1<<30) /* MIDI IRQ is pending */ |
279 | #define HDSPM_midi1IRQPending (1<<31) /* and aktiv */ | 291 | #define HDSPM_midi1IRQPending (1<<31) /* and aktiv */ |
280 | 292 | ||
281 | /* --- status bit helpers */ | 293 | /* --- status bit helpers */ |
282 | #define HDSPM_madiFreqMask (HDSPM_madiFreq0|HDSPM_madiFreq1|HDSPM_madiFreq2|HDSPM_madiFreq3) | 294 | #define HDSPM_madiFreqMask (HDSPM_madiFreq0|HDSPM_madiFreq1|\ |
295 | HDSPM_madiFreq2|HDSPM_madiFreq3) | ||
283 | #define HDSPM_madiFreq32 (HDSPM_madiFreq0) | 296 | #define HDSPM_madiFreq32 (HDSPM_madiFreq0) |
284 | #define HDSPM_madiFreq44_1 (HDSPM_madiFreq1) | 297 | #define HDSPM_madiFreq44_1 (HDSPM_madiFreq1) |
285 | #define HDSPM_madiFreq48 (HDSPM_madiFreq0|HDSPM_madiFreq1) | 298 | #define HDSPM_madiFreq48 (HDSPM_madiFreq0|HDSPM_madiFreq1) |
@@ -319,10 +332,12 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
319 | #define HDSPM_wcFreq96 (HDSPM_wc_freq1|HDSPM_wc_freq2) | 332 | #define HDSPM_wcFreq96 (HDSPM_wc_freq1|HDSPM_wc_freq2) |
320 | 333 | ||
321 | 334 | ||
322 | #define HDSPM_SelSyncRefMask (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|HDSPM_SelSyncRef2) | 335 | #define HDSPM_SelSyncRefMask (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\ |
336 | HDSPM_SelSyncRef2) | ||
323 | #define HDSPM_SelSyncRef_WORD 0 | 337 | #define HDSPM_SelSyncRef_WORD 0 |
324 | #define HDSPM_SelSyncRef_MADI (HDSPM_SelSyncRef0) | 338 | #define HDSPM_SelSyncRef_MADI (HDSPM_SelSyncRef0) |
325 | #define HDSPM_SelSyncRef_NVALID (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|HDSPM_SelSyncRef2) | 339 | #define HDSPM_SelSyncRef_NVALID (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\ |
340 | HDSPM_SelSyncRef2) | ||
326 | 341 | ||
327 | /* | 342 | /* |
328 | For AES32, bits for status, status2 and timecode are different | 343 | For AES32, bits for status, status2 and timecode are different |
@@ -344,7 +359,7 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
344 | #define HDSPM_AES32_AUTOSYNC_FROM_AES6 6 | 359 | #define HDSPM_AES32_AUTOSYNC_FROM_AES6 6 |
345 | #define HDSPM_AES32_AUTOSYNC_FROM_AES7 7 | 360 | #define HDSPM_AES32_AUTOSYNC_FROM_AES7 7 |
346 | #define HDSPM_AES32_AUTOSYNC_FROM_AES8 8 | 361 | #define HDSPM_AES32_AUTOSYNC_FROM_AES8 8 |
347 | #define HDSPM_AES32_AUTOSYNC_FROM_NONE -1 | 362 | #define HDSPM_AES32_AUTOSYNC_FROM_NONE 9 |
348 | 363 | ||
349 | /* status2 */ | 364 | /* status2 */ |
350 | /* HDSPM_LockAES_bit is given by HDSPM_LockAES >> (AES# - 1) */ | 365 | /* HDSPM_LockAES_bit is given by HDSPM_LockAES >> (AES# - 1) */ |
@@ -398,6 +413,13 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
398 | /* revisions >= 230 indicate AES32 card */ | 413 | /* revisions >= 230 indicate AES32 card */ |
399 | #define HDSPM_AESREVISION 230 | 414 | #define HDSPM_AESREVISION 230 |
400 | 415 | ||
416 | /* speed factor modes */ | ||
417 | #define HDSPM_SPEED_SINGLE 0 | ||
418 | #define HDSPM_SPEED_DOUBLE 1 | ||
419 | #define HDSPM_SPEED_QUAD 2 | ||
420 | /* names for speed modes */ | ||
421 | static char *hdspm_speed_names[] = { "single", "double", "quad" }; | ||
422 | |||
401 | struct hdspm_midi { | 423 | struct hdspm_midi { |
402 | struct hdspm *hdspm; | 424 | struct hdspm *hdspm; |
403 | int id; | 425 | int id; |
@@ -412,8 +434,9 @@ struct hdspm_midi { | |||
412 | 434 | ||
413 | struct hdspm { | 435 | struct hdspm { |
414 | spinlock_t lock; | 436 | spinlock_t lock; |
415 | struct snd_pcm_substream *capture_substream; /* only one playback */ | 437 | /* only one playback and/or capture stream */ |
416 | struct snd_pcm_substream *playback_substream; /* and/or capture stream */ | 438 | struct snd_pcm_substream *capture_substream; |
439 | struct snd_pcm_substream *playback_substream; | ||
417 | 440 | ||
418 | char *card_name; /* for procinfo */ | 441 | char *card_name; /* for procinfo */ |
419 | unsigned short firmware_rev; /* dont know if relevant (yes if AES32)*/ | 442 | unsigned short firmware_rev; /* dont know if relevant (yes if AES32)*/ |
@@ -460,9 +483,12 @@ struct hdspm { | |||
460 | struct pci_dev *pci; /* and an pci info */ | 483 | struct pci_dev *pci; /* and an pci info */ |
461 | 484 | ||
462 | /* Mixer vars */ | 485 | /* Mixer vars */ |
463 | struct snd_kcontrol *playback_mixer_ctls[HDSPM_MAX_CHANNELS]; /* fast alsa mixer */ | 486 | /* fast alsa mixer */ |
464 | struct snd_kcontrol *input_mixer_ctls[HDSPM_MAX_CHANNELS]; /* but input to much, so not used */ | 487 | struct snd_kcontrol *playback_mixer_ctls[HDSPM_MAX_CHANNELS]; |
465 | struct hdspm_mixer *mixer; /* full mixer accessable over mixer ioctl or hwdep-device */ | 488 | /* but input to much, so not used */ |
489 | struct snd_kcontrol *input_mixer_ctls[HDSPM_MAX_CHANNELS]; | ||
490 | /* full mixer accessable over mixer ioctl or hwdep-device */ | ||
491 | struct hdspm_mixer *mixer; | ||
466 | 492 | ||
467 | }; | 493 | }; |
468 | 494 | ||
@@ -616,13 +642,15 @@ static inline int hdspm_external_sample_rate(struct hdspm * hdspm) | |||
616 | if (hdspm->is_aes32) { | 642 | if (hdspm->is_aes32) { |
617 | unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2); | 643 | unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2); |
618 | unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister); | 644 | unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister); |
619 | unsigned int timecode = hdspm_read(hdspm, HDSPM_timecodeRegister); | 645 | unsigned int timecode = |
646 | hdspm_read(hdspm, HDSPM_timecodeRegister); | ||
620 | 647 | ||
621 | int syncref = hdspm_autosync_ref(hdspm); | 648 | int syncref = hdspm_autosync_ref(hdspm); |
622 | 649 | ||
623 | if (syncref == HDSPM_AES32_AUTOSYNC_FROM_WORD && | 650 | if (syncref == HDSPM_AES32_AUTOSYNC_FROM_WORD && |
624 | status & HDSPM_AES32_wcLock) | 651 | status & HDSPM_AES32_wcLock) |
625 | return HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF); | 652 | return HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) |
653 | & 0xF); | ||
626 | if (syncref >= HDSPM_AES32_AUTOSYNC_FROM_AES1 && | 654 | if (syncref >= HDSPM_AES32_AUTOSYNC_FROM_AES1 && |
627 | syncref <= HDSPM_AES32_AUTOSYNC_FROM_AES8 && | 655 | syncref <= HDSPM_AES32_AUTOSYNC_FROM_AES8 && |
628 | status2 & (HDSPM_LockAES >> | 656 | status2 & (HDSPM_LockAES >> |
@@ -668,7 +696,9 @@ static inline int hdspm_external_sample_rate(struct hdspm * hdspm) | |||
668 | } | 696 | } |
669 | } | 697 | } |
670 | 698 | ||
671 | /* if rate detected and Syncref is Word than have it, word has priority to MADI */ | 699 | /* if rate detected and Syncref is Word than have it, |
700 | * word has priority to MADI | ||
701 | */ | ||
672 | if (rate != 0 && | 702 | if (rate != 0 && |
673 | (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD) | 703 | (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD) |
674 | return rate; | 704 | return rate; |
@@ -727,12 +757,12 @@ static snd_pcm_uframes_t hdspm_hw_pointer(struct hdspm * hdspm) | |||
727 | 757 | ||
728 | position = hdspm_read(hdspm, HDSPM_statusRegister); | 758 | position = hdspm_read(hdspm, HDSPM_statusRegister); |
729 | 759 | ||
730 | if (!hdspm->precise_ptr) { | 760 | if (!hdspm->precise_ptr) |
731 | return (position & HDSPM_BufferID) ? (hdspm->period_bytes / | 761 | return (position & HDSPM_BufferID) ? |
732 | 4) : 0; | 762 | (hdspm->period_bytes / 4) : 0; |
733 | } | ||
734 | 763 | ||
735 | /* hwpointer comes in bytes and is 64Bytes accurate (by docu since PCI Burst) | 764 | /* hwpointer comes in bytes and is 64Bytes accurate (by docu since |
765 | PCI Burst) | ||
736 | i have experimented that it is at most 64 Byte to much for playing | 766 | i have experimented that it is at most 64 Byte to much for playing |
737 | so substraction of 64 byte should be ok for ALSA, but use it only | 767 | so substraction of 64 byte should be ok for ALSA, but use it only |
738 | for application where you know what you do since if you come to | 768 | for application where you know what you do since if you come to |
@@ -811,7 +841,7 @@ static void hdspm_set_dds_value(struct hdspm *hdspm, int rate) | |||
811 | // return 104857600000000 / rate; // 100 MHz | 841 | // return 104857600000000 / rate; // 100 MHz |
812 | return 110100480000000 / rate; // 105 MHz | 842 | return 110100480000000 / rate; // 105 MHz |
813 | */ | 843 | */ |
814 | //n = 104857600000000ULL; /* = 2^20 * 10^8 */ | 844 | /* n = 104857600000000ULL; */ /* = 2^20 * 10^8 */ |
815 | n = 110100480000000ULL; /* Value checked for AES32 and MADI */ | 845 | n = 110100480000000ULL; /* Value checked for AES32 and MADI */ |
816 | div64_32(&n, rate, &r); | 846 | div64_32(&n, rate, &r); |
817 | /* n should be less than 2^32 for being written to FREQ register */ | 847 | /* n should be less than 2^32 for being written to FREQ register */ |
@@ -822,11 +852,10 @@ static void hdspm_set_dds_value(struct hdspm *hdspm, int rate) | |||
822 | /* dummy set rate lets see what happens */ | 852 | /* dummy set rate lets see what happens */ |
823 | static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally) | 853 | static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally) |
824 | { | 854 | { |
825 | int reject_if_open = 0; | ||
826 | int current_rate; | 855 | int current_rate; |
827 | int rate_bits; | 856 | int rate_bits; |
828 | int not_set = 0; | 857 | int not_set = 0; |
829 | int is_single, is_double, is_quad; | 858 | int current_speed, target_speed; |
830 | 859 | ||
831 | /* ASSUMPTION: hdspm->lock is either set, or there is no need for | 860 | /* ASSUMPTION: hdspm->lock is either set, or there is no need for |
832 | it (e.g. during module initialization). | 861 | it (e.g. during module initialization). |
@@ -841,8 +870,9 @@ static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally) | |||
841 | just make a warning an remember setting | 870 | just make a warning an remember setting |
842 | for future master mode switching */ | 871 | for future master mode switching */ |
843 | 872 | ||
844 | snd_printk | 873 | snd_printk(KERN_WARNING "HDSPM: " |
845 | (KERN_WARNING "HDSPM: Warning: device is not running as a clock master.\n"); | 874 | "Warning: device is not running " |
875 | "as a clock master.\n"); | ||
846 | not_set = 1; | 876 | not_set = 1; |
847 | } else { | 877 | } else { |
848 | 878 | ||
@@ -850,16 +880,18 @@ static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally) | |||
850 | int external_freq = | 880 | int external_freq = |
851 | hdspm_external_sample_rate(hdspm); | 881 | hdspm_external_sample_rate(hdspm); |
852 | 882 | ||
853 | if ((hdspm_autosync_ref(hdspm) == | 883 | if (hdspm_autosync_ref(hdspm) == |
854 | HDSPM_AUTOSYNC_FROM_NONE)) { | 884 | HDSPM_AUTOSYNC_FROM_NONE) { |
855 | 885 | ||
856 | snd_printk(KERN_WARNING "HDSPM: Detected no Externel Sync \n"); | 886 | snd_printk(KERN_WARNING "HDSPM: " |
887 | "Detected no Externel Sync \n"); | ||
857 | not_set = 1; | 888 | not_set = 1; |
858 | 889 | ||
859 | } else if (rate != external_freq) { | 890 | } else if (rate != external_freq) { |
860 | 891 | ||
861 | snd_printk | 892 | snd_printk(KERN_WARNING "HDSPM: " |
862 | (KERN_WARNING "HDSPM: Warning: No AutoSync source for requested rate\n"); | 893 | "Warning: No AutoSync source for " |
894 | "requested rate\n"); | ||
863 | not_set = 1; | 895 | not_set = 1; |
864 | } | 896 | } |
865 | } | 897 | } |
@@ -877,64 +909,60 @@ static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally) | |||
877 | changes in the read/write routines. | 909 | changes in the read/write routines. |
878 | */ | 910 | */ |
879 | 911 | ||
880 | is_single = (current_rate <= 48000); | 912 | if (current_rate <= 48000) |
881 | is_double = (current_rate > 48000 && current_rate <= 96000); | 913 | current_speed = HDSPM_SPEED_SINGLE; |
882 | is_quad = (current_rate > 96000); | 914 | else if (current_rate <= 96000) |
915 | current_speed = HDSPM_SPEED_DOUBLE; | ||
916 | else | ||
917 | current_speed = HDSPM_SPEED_QUAD; | ||
918 | |||
919 | if (rate <= 48000) | ||
920 | target_speed = HDSPM_SPEED_SINGLE; | ||
921 | else if (rate <= 96000) | ||
922 | target_speed = HDSPM_SPEED_DOUBLE; | ||
923 | else | ||
924 | target_speed = HDSPM_SPEED_QUAD; | ||
883 | 925 | ||
884 | switch (rate) { | 926 | switch (rate) { |
885 | case 32000: | 927 | case 32000: |
886 | if (!is_single) | ||
887 | reject_if_open = 1; | ||
888 | rate_bits = HDSPM_Frequency32KHz; | 928 | rate_bits = HDSPM_Frequency32KHz; |
889 | break; | 929 | break; |
890 | case 44100: | 930 | case 44100: |
891 | if (!is_single) | ||
892 | reject_if_open = 1; | ||
893 | rate_bits = HDSPM_Frequency44_1KHz; | 931 | rate_bits = HDSPM_Frequency44_1KHz; |
894 | break; | 932 | break; |
895 | case 48000: | 933 | case 48000: |
896 | if (!is_single) | ||
897 | reject_if_open = 1; | ||
898 | rate_bits = HDSPM_Frequency48KHz; | 934 | rate_bits = HDSPM_Frequency48KHz; |
899 | break; | 935 | break; |
900 | case 64000: | 936 | case 64000: |
901 | if (!is_double) | ||
902 | reject_if_open = 1; | ||
903 | rate_bits = HDSPM_Frequency64KHz; | 937 | rate_bits = HDSPM_Frequency64KHz; |
904 | break; | 938 | break; |
905 | case 88200: | 939 | case 88200: |
906 | if (!is_double) | ||
907 | reject_if_open = 1; | ||
908 | rate_bits = HDSPM_Frequency88_2KHz; | 940 | rate_bits = HDSPM_Frequency88_2KHz; |
909 | break; | 941 | break; |
910 | case 96000: | 942 | case 96000: |
911 | if (!is_double) | ||
912 | reject_if_open = 1; | ||
913 | rate_bits = HDSPM_Frequency96KHz; | 943 | rate_bits = HDSPM_Frequency96KHz; |
914 | break; | 944 | break; |
915 | case 128000: | 945 | case 128000: |
916 | if (!is_quad) | ||
917 | reject_if_open = 1; | ||
918 | rate_bits = HDSPM_Frequency128KHz; | 946 | rate_bits = HDSPM_Frequency128KHz; |
919 | break; | 947 | break; |
920 | case 176400: | 948 | case 176400: |
921 | if (!is_quad) | ||
922 | reject_if_open = 1; | ||
923 | rate_bits = HDSPM_Frequency176_4KHz; | 949 | rate_bits = HDSPM_Frequency176_4KHz; |
924 | break; | 950 | break; |
925 | case 192000: | 951 | case 192000: |
926 | if (!is_quad) | ||
927 | reject_if_open = 1; | ||
928 | rate_bits = HDSPM_Frequency192KHz; | 952 | rate_bits = HDSPM_Frequency192KHz; |
929 | break; | 953 | break; |
930 | default: | 954 | default: |
931 | return -EINVAL; | 955 | return -EINVAL; |
932 | } | 956 | } |
933 | 957 | ||
934 | if (reject_if_open | 958 | if (current_speed != target_speed |
935 | && (hdspm->capture_pid >= 0 || hdspm->playback_pid >= 0)) { | 959 | && (hdspm->capture_pid >= 0 || hdspm->playback_pid >= 0)) { |
936 | snd_printk | 960 | snd_printk |
937 | (KERN_ERR "HDSPM: cannot change between single- and double-speed mode (capture PID = %d, playback PID = %d)\n", | 961 | (KERN_ERR "HDSPM: " |
962 | "cannot change from %s speed to %s speed mode " | ||
963 | "(capture PID = %d, playback PID = %d)\n", | ||
964 | hdspm_speed_names[current_speed], | ||
965 | hdspm_speed_names[target_speed], | ||
938 | hdspm->capture_pid, hdspm->playback_pid); | 966 | hdspm->capture_pid, hdspm->playback_pid); |
939 | return -EBUSY; | 967 | return -EBUSY; |
940 | } | 968 | } |
@@ -966,8 +994,14 @@ static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally) | |||
966 | static void all_in_all_mixer(struct hdspm * hdspm, int sgain) | 994 | static void all_in_all_mixer(struct hdspm * hdspm, int sgain) |
967 | { | 995 | { |
968 | int i, j; | 996 | int i, j; |
969 | unsigned int gain = | 997 | unsigned int gain; |
970 | (sgain > UNITY_GAIN) ? UNITY_GAIN : (sgain < 0) ? 0 : sgain; | 998 | |
999 | if (sgain > UNITY_GAIN) | ||
1000 | gain = UNITY_GAIN; | ||
1001 | else if (sgain < 0) | ||
1002 | gain = 0; | ||
1003 | else | ||
1004 | gain = sgain; | ||
971 | 1005 | ||
972 | for (i = 0; i < HDSPM_MIXER_CHANNELS; i++) | 1006 | for (i = 0; i < HDSPM_MIXER_CHANNELS; i++) |
973 | for (j = 0; j < HDSPM_MIXER_CHANNELS; j++) { | 1007 | for (j = 0; j < HDSPM_MIXER_CHANNELS; j++) { |
@@ -980,7 +1014,8 @@ static void all_in_all_mixer(struct hdspm * hdspm, int sgain) | |||
980 | MIDI | 1014 | MIDI |
981 | ----------------------------------------------------------------------------*/ | 1015 | ----------------------------------------------------------------------------*/ |
982 | 1016 | ||
983 | static inline unsigned char snd_hdspm_midi_read_byte (struct hdspm *hdspm, int id) | 1017 | static inline unsigned char snd_hdspm_midi_read_byte (struct hdspm *hdspm, |
1018 | int id) | ||
984 | { | 1019 | { |
985 | /* the hardware already does the relevant bit-mask with 0xff */ | 1020 | /* the hardware already does the relevant bit-mask with 0xff */ |
986 | if (id) | 1021 | if (id) |
@@ -989,7 +1024,8 @@ static inline unsigned char snd_hdspm_midi_read_byte (struct hdspm *hdspm, int i | |||
989 | return hdspm_read(hdspm, HDSPM_midiDataIn0); | 1024 | return hdspm_read(hdspm, HDSPM_midiDataIn0); |
990 | } | 1025 | } |
991 | 1026 | ||
992 | static inline void snd_hdspm_midi_write_byte (struct hdspm *hdspm, int id, int val) | 1027 | static inline void snd_hdspm_midi_write_byte (struct hdspm *hdspm, int id, |
1028 | int val) | ||
993 | { | 1029 | { |
994 | /* the hardware already does the relevant bit-mask with 0xff */ | 1030 | /* the hardware already does the relevant bit-mask with 0xff */ |
995 | if (id) | 1031 | if (id) |
@@ -1011,9 +1047,10 @@ static inline int snd_hdspm_midi_output_possible (struct hdspm *hdspm, int id) | |||
1011 | int fifo_bytes_used; | 1047 | int fifo_bytes_used; |
1012 | 1048 | ||
1013 | if (id) | 1049 | if (id) |
1014 | fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xff; | 1050 | fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut1); |
1015 | else | 1051 | else |
1016 | fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xff; | 1052 | fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut0); |
1053 | fifo_bytes_used &= 0xff; | ||
1017 | 1054 | ||
1018 | if (fifo_bytes_used < 128) | 1055 | if (fifo_bytes_used < 128) |
1019 | return 128 - fifo_bytes_used; | 1056 | return 128 - fifo_bytes_used; |
@@ -1038,16 +1075,21 @@ static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi) | |||
1038 | /* Output is not interrupt driven */ | 1075 | /* Output is not interrupt driven */ |
1039 | 1076 | ||
1040 | spin_lock_irqsave (&hmidi->lock, flags); | 1077 | spin_lock_irqsave (&hmidi->lock, flags); |
1041 | if (hmidi->output) { | 1078 | if (hmidi->output && |
1042 | if (!snd_rawmidi_transmit_empty (hmidi->output)) { | 1079 | !snd_rawmidi_transmit_empty (hmidi->output)) { |
1043 | if ((n_pending = snd_hdspm_midi_output_possible (hmidi->hdspm, hmidi->id)) > 0) { | 1080 | n_pending = snd_hdspm_midi_output_possible (hmidi->hdspm, |
1044 | if (n_pending > (int)sizeof (buf)) | 1081 | hmidi->id); |
1045 | n_pending = sizeof (buf); | 1082 | if (n_pending > 0) { |
1046 | 1083 | if (n_pending > (int)sizeof (buf)) | |
1047 | if ((to_write = snd_rawmidi_transmit (hmidi->output, buf, n_pending)) > 0) { | 1084 | n_pending = sizeof (buf); |
1048 | for (i = 0; i < to_write; ++i) | 1085 | |
1049 | snd_hdspm_midi_write_byte (hmidi->hdspm, hmidi->id, buf[i]); | 1086 | to_write = snd_rawmidi_transmit (hmidi->output, buf, |
1050 | } | 1087 | n_pending); |
1088 | if (to_write > 0) { | ||
1089 | for (i = 0; i < to_write; ++i) | ||
1090 | snd_hdspm_midi_write_byte (hmidi->hdspm, | ||
1091 | hmidi->id, | ||
1092 | buf[i]); | ||
1051 | } | 1093 | } |
1052 | } | 1094 | } |
1053 | } | 1095 | } |
@@ -1057,51 +1099,55 @@ static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi) | |||
1057 | 1099 | ||
1058 | static int snd_hdspm_midi_input_read (struct hdspm_midi *hmidi) | 1100 | static int snd_hdspm_midi_input_read (struct hdspm_midi *hmidi) |
1059 | { | 1101 | { |
1060 | unsigned char buf[128]; /* this buffer is designed to match the MIDI input FIFO size */ | 1102 | unsigned char buf[128]; /* this buffer is designed to match the MIDI |
1103 | * input FIFO size | ||
1104 | */ | ||
1061 | unsigned long flags; | 1105 | unsigned long flags; |
1062 | int n_pending; | 1106 | int n_pending; |
1063 | int i; | 1107 | int i; |
1064 | 1108 | ||
1065 | spin_lock_irqsave (&hmidi->lock, flags); | 1109 | spin_lock_irqsave (&hmidi->lock, flags); |
1066 | if ((n_pending = snd_hdspm_midi_input_available (hmidi->hdspm, hmidi->id)) > 0) { | 1110 | n_pending = snd_hdspm_midi_input_available (hmidi->hdspm, hmidi->id); |
1111 | if (n_pending > 0) { | ||
1067 | if (hmidi->input) { | 1112 | if (hmidi->input) { |
1068 | if (n_pending > (int)sizeof (buf)) { | 1113 | if (n_pending > (int)sizeof (buf)) |
1069 | n_pending = sizeof (buf); | 1114 | n_pending = sizeof (buf); |
1070 | } | 1115 | for (i = 0; i < n_pending; ++i) |
1071 | for (i = 0; i < n_pending; ++i) { | 1116 | buf[i] = snd_hdspm_midi_read_byte (hmidi->hdspm, |
1072 | buf[i] = snd_hdspm_midi_read_byte (hmidi->hdspm, hmidi->id); | 1117 | hmidi->id); |
1073 | } | 1118 | if (n_pending) |
1074 | if (n_pending) { | 1119 | snd_rawmidi_receive (hmidi->input, buf, |
1075 | snd_rawmidi_receive (hmidi->input, buf, n_pending); | 1120 | n_pending); |
1076 | } | ||
1077 | } else { | 1121 | } else { |
1078 | /* flush the MIDI input FIFO */ | 1122 | /* flush the MIDI input FIFO */ |
1079 | while (n_pending--) { | 1123 | while (n_pending--) |
1080 | snd_hdspm_midi_read_byte (hmidi->hdspm, hmidi->id); | 1124 | snd_hdspm_midi_read_byte (hmidi->hdspm, |
1081 | } | 1125 | hmidi->id); |
1082 | } | 1126 | } |
1083 | } | 1127 | } |
1084 | hmidi->pending = 0; | 1128 | hmidi->pending = 0; |
1085 | if (hmidi->id) { | 1129 | if (hmidi->id) |
1086 | hmidi->hdspm->control_register |= HDSPM_Midi1InterruptEnable; | 1130 | hmidi->hdspm->control_register |= HDSPM_Midi1InterruptEnable; |
1087 | } else { | 1131 | else |
1088 | hmidi->hdspm->control_register |= HDSPM_Midi0InterruptEnable; | 1132 | hmidi->hdspm->control_register |= HDSPM_Midi0InterruptEnable; |
1089 | } | 1133 | hdspm_write(hmidi->hdspm, HDSPM_controlRegister, |
1090 | hdspm_write(hmidi->hdspm, HDSPM_controlRegister, hmidi->hdspm->control_register); | 1134 | hmidi->hdspm->control_register); |
1091 | spin_unlock_irqrestore (&hmidi->lock, flags); | 1135 | spin_unlock_irqrestore (&hmidi->lock, flags); |
1092 | return snd_hdspm_midi_output_write (hmidi); | 1136 | return snd_hdspm_midi_output_write (hmidi); |
1093 | } | 1137 | } |
1094 | 1138 | ||
1095 | static void snd_hdspm_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) | 1139 | static void |
1140 | snd_hdspm_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) | ||
1096 | { | 1141 | { |
1097 | struct hdspm *hdspm; | 1142 | struct hdspm *hdspm; |
1098 | struct hdspm_midi *hmidi; | 1143 | struct hdspm_midi *hmidi; |
1099 | unsigned long flags; | 1144 | unsigned long flags; |
1100 | u32 ie; | 1145 | u32 ie; |
1101 | 1146 | ||
1102 | hmidi = (struct hdspm_midi *) substream->rmidi->private_data; | 1147 | hmidi = substream->rmidi->private_data; |
1103 | hdspm = hmidi->hdspm; | 1148 | hdspm = hmidi->hdspm; |
1104 | ie = hmidi->id ? HDSPM_Midi1InterruptEnable : HDSPM_Midi0InterruptEnable; | 1149 | ie = hmidi->id ? |
1150 | HDSPM_Midi1InterruptEnable : HDSPM_Midi0InterruptEnable; | ||
1105 | spin_lock_irqsave (&hdspm->lock, flags); | 1151 | spin_lock_irqsave (&hdspm->lock, flags); |
1106 | if (up) { | 1152 | if (up) { |
1107 | if (!(hdspm->control_register & ie)) { | 1153 | if (!(hdspm->control_register & ie)) { |
@@ -1138,12 +1184,13 @@ static void snd_hdspm_midi_output_timer(unsigned long data) | |||
1138 | spin_unlock_irqrestore (&hmidi->lock, flags); | 1184 | spin_unlock_irqrestore (&hmidi->lock, flags); |
1139 | } | 1185 | } |
1140 | 1186 | ||
1141 | static void snd_hdspm_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) | 1187 | static void |
1188 | snd_hdspm_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) | ||
1142 | { | 1189 | { |
1143 | struct hdspm_midi *hmidi; | 1190 | struct hdspm_midi *hmidi; |
1144 | unsigned long flags; | 1191 | unsigned long flags; |
1145 | 1192 | ||
1146 | hmidi = (struct hdspm_midi *) substream->rmidi->private_data; | 1193 | hmidi = substream->rmidi->private_data; |
1147 | spin_lock_irqsave (&hmidi->lock, flags); | 1194 | spin_lock_irqsave (&hmidi->lock, flags); |
1148 | if (up) { | 1195 | if (up) { |
1149 | if (!hmidi->istimer) { | 1196 | if (!hmidi->istimer) { |
@@ -1155,9 +1202,8 @@ static void snd_hdspm_midi_output_trigger(struct snd_rawmidi_substream *substrea | |||
1155 | hmidi->istimer++; | 1202 | hmidi->istimer++; |
1156 | } | 1203 | } |
1157 | } else { | 1204 | } else { |
1158 | if (hmidi->istimer && --hmidi->istimer <= 0) { | 1205 | if (hmidi->istimer && --hmidi->istimer <= 0) |
1159 | del_timer (&hmidi->timer); | 1206 | del_timer (&hmidi->timer); |
1160 | } | ||
1161 | } | 1207 | } |
1162 | spin_unlock_irqrestore (&hmidi->lock, flags); | 1208 | spin_unlock_irqrestore (&hmidi->lock, flags); |
1163 | if (up) | 1209 | if (up) |
@@ -1168,7 +1214,7 @@ static int snd_hdspm_midi_input_open(struct snd_rawmidi_substream *substream) | |||
1168 | { | 1214 | { |
1169 | struct hdspm_midi *hmidi; | 1215 | struct hdspm_midi *hmidi; |
1170 | 1216 | ||
1171 | hmidi = (struct hdspm_midi *) substream->rmidi->private_data; | 1217 | hmidi = substream->rmidi->private_data; |
1172 | spin_lock_irq (&hmidi->lock); | 1218 | spin_lock_irq (&hmidi->lock); |
1173 | snd_hdspm_flush_midi_input (hmidi->hdspm, hmidi->id); | 1219 | snd_hdspm_flush_midi_input (hmidi->hdspm, hmidi->id); |
1174 | hmidi->input = substream; | 1220 | hmidi->input = substream; |
@@ -1181,7 +1227,7 @@ static int snd_hdspm_midi_output_open(struct snd_rawmidi_substream *substream) | |||
1181 | { | 1227 | { |
1182 | struct hdspm_midi *hmidi; | 1228 | struct hdspm_midi *hmidi; |
1183 | 1229 | ||
1184 | hmidi = (struct hdspm_midi *) substream->rmidi->private_data; | 1230 | hmidi = substream->rmidi->private_data; |
1185 | spin_lock_irq (&hmidi->lock); | 1231 | spin_lock_irq (&hmidi->lock); |
1186 | hmidi->output = substream; | 1232 | hmidi->output = substream; |
1187 | spin_unlock_irq (&hmidi->lock); | 1233 | spin_unlock_irq (&hmidi->lock); |
@@ -1195,7 +1241,7 @@ static int snd_hdspm_midi_input_close(struct snd_rawmidi_substream *substream) | |||
1195 | 1241 | ||
1196 | snd_hdspm_midi_input_trigger (substream, 0); | 1242 | snd_hdspm_midi_input_trigger (substream, 0); |
1197 | 1243 | ||
1198 | hmidi = (struct hdspm_midi *) substream->rmidi->private_data; | 1244 | hmidi = substream->rmidi->private_data; |
1199 | spin_lock_irq (&hmidi->lock); | 1245 | spin_lock_irq (&hmidi->lock); |
1200 | hmidi->input = NULL; | 1246 | hmidi->input = NULL; |
1201 | spin_unlock_irq (&hmidi->lock); | 1247 | spin_unlock_irq (&hmidi->lock); |
@@ -1209,7 +1255,7 @@ static int snd_hdspm_midi_output_close(struct snd_rawmidi_substream *substream) | |||
1209 | 1255 | ||
1210 | snd_hdspm_midi_output_trigger (substream, 0); | 1256 | snd_hdspm_midi_output_trigger (substream, 0); |
1211 | 1257 | ||
1212 | hmidi = (struct hdspm_midi *) substream->rmidi->private_data; | 1258 | hmidi = substream->rmidi->private_data; |
1213 | spin_lock_irq (&hmidi->lock); | 1259 | spin_lock_irq (&hmidi->lock); |
1214 | hmidi->output = NULL; | 1260 | hmidi->output = NULL; |
1215 | spin_unlock_irq (&hmidi->lock); | 1261 | spin_unlock_irq (&hmidi->lock); |
@@ -1231,29 +1277,28 @@ static struct snd_rawmidi_ops snd_hdspm_midi_input = | |||
1231 | .trigger = snd_hdspm_midi_input_trigger, | 1277 | .trigger = snd_hdspm_midi_input_trigger, |
1232 | }; | 1278 | }; |
1233 | 1279 | ||
1234 | static int __devinit snd_hdspm_create_midi (struct snd_card *card, struct hdspm *hdspm, int id) | 1280 | static int __devinit snd_hdspm_create_midi (struct snd_card *card, |
1281 | struct hdspm *hdspm, int id) | ||
1235 | { | 1282 | { |
1236 | int err; | 1283 | int err; |
1237 | char buf[32]; | 1284 | char buf[32]; |
1238 | 1285 | ||
1239 | hdspm->midi[id].id = id; | 1286 | hdspm->midi[id].id = id; |
1240 | hdspm->midi[id].rmidi = NULL; | ||
1241 | hdspm->midi[id].input = NULL; | ||
1242 | hdspm->midi[id].output = NULL; | ||
1243 | hdspm->midi[id].hdspm = hdspm; | 1287 | hdspm->midi[id].hdspm = hdspm; |
1244 | hdspm->midi[id].istimer = 0; | ||
1245 | hdspm->midi[id].pending = 0; | ||
1246 | spin_lock_init (&hdspm->midi[id].lock); | 1288 | spin_lock_init (&hdspm->midi[id].lock); |
1247 | 1289 | ||
1248 | sprintf (buf, "%s MIDI %d", card->shortname, id+1); | 1290 | sprintf (buf, "%s MIDI %d", card->shortname, id+1); |
1249 | if ((err = snd_rawmidi_new (card, buf, id, 1, 1, &hdspm->midi[id].rmidi)) < 0) | 1291 | err = snd_rawmidi_new (card, buf, id, 1, 1, &hdspm->midi[id].rmidi); |
1292 | if (err < 0) | ||
1250 | return err; | 1293 | return err; |
1251 | 1294 | ||
1252 | sprintf (hdspm->midi[id].rmidi->name, "%s MIDI %d", card->id, id+1); | 1295 | sprintf (hdspm->midi[id].rmidi->name, "%s MIDI %d", card->id, id+1); |
1253 | hdspm->midi[id].rmidi->private_data = &hdspm->midi[id]; | 1296 | hdspm->midi[id].rmidi->private_data = &hdspm->midi[id]; |
1254 | 1297 | ||
1255 | snd_rawmidi_set_ops (hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_hdspm_midi_output); | 1298 | snd_rawmidi_set_ops(hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, |
1256 | snd_rawmidi_set_ops (hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_hdspm_midi_input); | 1299 | &snd_hdspm_midi_output); |
1300 | snd_rawmidi_set_ops(hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_INPUT, | ||
1301 | &snd_hdspm_midi_input); | ||
1257 | 1302 | ||
1258 | hdspm->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | | 1303 | hdspm->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | |
1259 | SNDRV_RAWMIDI_INFO_INPUT | | 1304 | SNDRV_RAWMIDI_INFO_INPUT | |
@@ -1558,8 +1603,8 @@ static int snd_hdspm_put_clock_source(struct snd_kcontrol *kcontrol, | |||
1558 | val = ucontrol->value.enumerated.item[0]; | 1603 | val = ucontrol->value.enumerated.item[0]; |
1559 | if (val < 0) | 1604 | if (val < 0) |
1560 | val = 0; | 1605 | val = 0; |
1561 | if (val > 6) | 1606 | if (val > 9) |
1562 | val = 6; | 1607 | val = 9; |
1563 | spin_lock_irq(&hdspm->lock); | 1608 | spin_lock_irq(&hdspm->lock); |
1564 | if (val != hdspm_clock_source(hdspm)) | 1609 | if (val != hdspm_clock_source(hdspm)) |
1565 | change = (hdspm_set_clock_source(hdspm, val) == 0) ? 1 : 0; | 1610 | change = (hdspm_set_clock_source(hdspm, val) == 0) ? 1 : 0; |
@@ -1637,7 +1682,8 @@ static int hdspm_set_pref_sync_ref(struct hdspm * hdspm, int pref) | |||
1637 | hdspm->control_register |= HDSPM_SyncRef2+HDSPM_SyncRef1; | 1682 | hdspm->control_register |= HDSPM_SyncRef2+HDSPM_SyncRef1; |
1638 | break; | 1683 | break; |
1639 | case 7: | 1684 | case 7: |
1640 | hdspm->control_register |= HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0; | 1685 | hdspm->control_register |= |
1686 | HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0; | ||
1641 | break; | 1687 | break; |
1642 | case 8: | 1688 | case 8: |
1643 | hdspm->control_register |= HDSPM_SyncRef3; | 1689 | hdspm->control_register |= HDSPM_SyncRef3; |
@@ -1675,7 +1721,8 @@ static int snd_hdspm_info_pref_sync_ref(struct snd_kcontrol *kcontrol, | |||
1675 | 1721 | ||
1676 | uinfo->value.enumerated.items = 9; | 1722 | uinfo->value.enumerated.items = 9; |
1677 | 1723 | ||
1678 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | 1724 | if (uinfo->value.enumerated.item >= |
1725 | uinfo->value.enumerated.items) | ||
1679 | uinfo->value.enumerated.item = | 1726 | uinfo->value.enumerated.item = |
1680 | uinfo->value.enumerated.items - 1; | 1727 | uinfo->value.enumerated.items - 1; |
1681 | strcpy(uinfo->value.enumerated.name, | 1728 | strcpy(uinfo->value.enumerated.name, |
@@ -1688,7 +1735,8 @@ static int snd_hdspm_info_pref_sync_ref(struct snd_kcontrol *kcontrol, | |||
1688 | 1735 | ||
1689 | uinfo->value.enumerated.items = 2; | 1736 | uinfo->value.enumerated.items = 2; |
1690 | 1737 | ||
1691 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | 1738 | if (uinfo->value.enumerated.item >= |
1739 | uinfo->value.enumerated.items) | ||
1692 | uinfo->value.enumerated.item = | 1740 | uinfo->value.enumerated.item = |
1693 | uinfo->value.enumerated.items - 1; | 1741 | uinfo->value.enumerated.items - 1; |
1694 | strcpy(uinfo->value.enumerated.name, | 1742 | strcpy(uinfo->value.enumerated.name, |
@@ -1740,7 +1788,8 @@ static int hdspm_autosync_ref(struct hdspm * hdspm) | |||
1740 | { | 1788 | { |
1741 | if (hdspm->is_aes32) { | 1789 | if (hdspm->is_aes32) { |
1742 | unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister); | 1790 | unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister); |
1743 | unsigned int syncref = (status >> HDSPM_AES32_syncref_bit) & 0xF; | 1791 | unsigned int syncref = (status >> HDSPM_AES32_syncref_bit) & |
1792 | 0xF; | ||
1744 | if (syncref == 0) | 1793 | if (syncref == 0) |
1745 | return HDSPM_AES32_AUTOSYNC_FROM_WORD; | 1794 | return HDSPM_AES32_AUTOSYNC_FROM_WORD; |
1746 | if (syncref <= 8) | 1795 | if (syncref <= 8) |
@@ -1777,20 +1826,20 @@ static int snd_hdspm_info_autosync_ref(struct snd_kcontrol *kcontrol, | |||
1777 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 1826 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
1778 | uinfo->count = 1; | 1827 | uinfo->count = 1; |
1779 | uinfo->value.enumerated.items = 10; | 1828 | uinfo->value.enumerated.items = 10; |
1780 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | 1829 | if (uinfo->value.enumerated.item >= |
1830 | uinfo->value.enumerated.items) | ||
1781 | uinfo->value.enumerated.item = | 1831 | uinfo->value.enumerated.item = |
1782 | uinfo->value.enumerated.items - 1; | 1832 | uinfo->value.enumerated.items - 1; |
1783 | strcpy(uinfo->value.enumerated.name, | 1833 | strcpy(uinfo->value.enumerated.name, |
1784 | texts[uinfo->value.enumerated.item]); | 1834 | texts[uinfo->value.enumerated.item]); |
1785 | } | 1835 | } else { |
1786 | else | ||
1787 | { | ||
1788 | static char *texts[] = { "WordClock", "MADI", "None" }; | 1836 | static char *texts[] = { "WordClock", "MADI", "None" }; |
1789 | 1837 | ||
1790 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 1838 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
1791 | uinfo->count = 1; | 1839 | uinfo->count = 1; |
1792 | uinfo->value.enumerated.items = 3; | 1840 | uinfo->value.enumerated.items = 3; |
1793 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | 1841 | if (uinfo->value.enumerated.item >= |
1842 | uinfo->value.enumerated.items) | ||
1794 | uinfo->value.enumerated.item = | 1843 | uinfo->value.enumerated.item = |
1795 | uinfo->value.enumerated.items - 1; | 1844 | uinfo->value.enumerated.items - 1; |
1796 | strcpy(uinfo->value.enumerated.name, | 1845 | strcpy(uinfo->value.enumerated.name, |
@@ -1804,7 +1853,7 @@ static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol, | |||
1804 | { | 1853 | { |
1805 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | 1854 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); |
1806 | 1855 | ||
1807 | ucontrol->value.enumerated.item[0] = hdspm_pref_sync_ref(hdspm); | 1856 | ucontrol->value.enumerated.item[0] = hdspm_autosync_ref(hdspm); |
1808 | return 0; | 1857 | return 0; |
1809 | } | 1858 | } |
1810 | 1859 | ||
@@ -1834,15 +1883,7 @@ static int hdspm_set_line_output(struct hdspm * hdspm, int out) | |||
1834 | return 0; | 1883 | return 0; |
1835 | } | 1884 | } |
1836 | 1885 | ||
1837 | static int snd_hdspm_info_line_out(struct snd_kcontrol *kcontrol, | 1886 | #define snd_hdspm_info_line_out snd_ctl_boolean_mono_info |
1838 | struct snd_ctl_elem_info *uinfo) | ||
1839 | { | ||
1840 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1841 | uinfo->count = 1; | ||
1842 | uinfo->value.integer.min = 0; | ||
1843 | uinfo->value.integer.max = 1; | ||
1844 | return 0; | ||
1845 | } | ||
1846 | 1887 | ||
1847 | static int snd_hdspm_get_line_out(struct snd_kcontrol *kcontrol, | 1888 | static int snd_hdspm_get_line_out(struct snd_kcontrol *kcontrol, |
1848 | struct snd_ctl_elem_value *ucontrol) | 1889 | struct snd_ctl_elem_value *ucontrol) |
@@ -1897,15 +1938,7 @@ static int hdspm_set_tx_64(struct hdspm * hdspm, int out) | |||
1897 | return 0; | 1938 | return 0; |
1898 | } | 1939 | } |
1899 | 1940 | ||
1900 | static int snd_hdspm_info_tx_64(struct snd_kcontrol *kcontrol, | 1941 | #define snd_hdspm_info_tx_64 snd_ctl_boolean_mono_info |
1901 | struct snd_ctl_elem_info *uinfo) | ||
1902 | { | ||
1903 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1904 | uinfo->count = 1; | ||
1905 | uinfo->value.integer.min = 0; | ||
1906 | uinfo->value.integer.max = 1; | ||
1907 | return 0; | ||
1908 | } | ||
1909 | 1942 | ||
1910 | static int snd_hdspm_get_tx_64(struct snd_kcontrol *kcontrol, | 1943 | static int snd_hdspm_get_tx_64(struct snd_kcontrol *kcontrol, |
1911 | struct snd_ctl_elem_value *ucontrol) | 1944 | struct snd_ctl_elem_value *ucontrol) |
@@ -1960,15 +1993,7 @@ static int hdspm_set_c_tms(struct hdspm * hdspm, int out) | |||
1960 | return 0; | 1993 | return 0; |
1961 | } | 1994 | } |
1962 | 1995 | ||
1963 | static int snd_hdspm_info_c_tms(struct snd_kcontrol *kcontrol, | 1996 | #define snd_hdspm_info_c_tms snd_ctl_boolean_mono_info |
1964 | struct snd_ctl_elem_info *uinfo) | ||
1965 | { | ||
1966 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1967 | uinfo->count = 1; | ||
1968 | uinfo->value.integer.min = 0; | ||
1969 | uinfo->value.integer.max = 1; | ||
1970 | return 0; | ||
1971 | } | ||
1972 | 1997 | ||
1973 | static int snd_hdspm_get_c_tms(struct snd_kcontrol *kcontrol, | 1998 | static int snd_hdspm_get_c_tms(struct snd_kcontrol *kcontrol, |
1974 | struct snd_ctl_elem_value *ucontrol) | 1999 | struct snd_ctl_elem_value *ucontrol) |
@@ -2023,15 +2048,7 @@ static int hdspm_set_safe_mode(struct hdspm * hdspm, int out) | |||
2023 | return 0; | 2048 | return 0; |
2024 | } | 2049 | } |
2025 | 2050 | ||
2026 | static int snd_hdspm_info_safe_mode(struct snd_kcontrol *kcontrol, | 2051 | #define snd_hdspm_info_safe_mode snd_ctl_boolean_mono_info |
2027 | struct snd_ctl_elem_info *uinfo) | ||
2028 | { | ||
2029 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
2030 | uinfo->count = 1; | ||
2031 | uinfo->value.integer.min = 0; | ||
2032 | uinfo->value.integer.max = 1; | ||
2033 | return 0; | ||
2034 | } | ||
2035 | 2052 | ||
2036 | static int snd_hdspm_get_safe_mode(struct snd_kcontrol *kcontrol, | 2053 | static int snd_hdspm_get_safe_mode(struct snd_kcontrol *kcontrol, |
2037 | struct snd_ctl_elem_value *ucontrol) | 2054 | struct snd_ctl_elem_value *ucontrol) |
@@ -2086,15 +2103,7 @@ static int hdspm_set_emphasis(struct hdspm * hdspm, int emp) | |||
2086 | return 0; | 2103 | return 0; |
2087 | } | 2104 | } |
2088 | 2105 | ||
2089 | static int snd_hdspm_info_emphasis(struct snd_kcontrol *kcontrol, | 2106 | #define snd_hdspm_info_emphasis snd_ctl_boolean_mono_info |
2090 | struct snd_ctl_elem_info *uinfo) | ||
2091 | { | ||
2092 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
2093 | uinfo->count = 1; | ||
2094 | uinfo->value.integer.min = 0; | ||
2095 | uinfo->value.integer.max = 1; | ||
2096 | return 0; | ||
2097 | } | ||
2098 | 2107 | ||
2099 | static int snd_hdspm_get_emphasis(struct snd_kcontrol *kcontrol, | 2108 | static int snd_hdspm_get_emphasis(struct snd_kcontrol *kcontrol, |
2100 | struct snd_ctl_elem_value *ucontrol) | 2109 | struct snd_ctl_elem_value *ucontrol) |
@@ -2149,15 +2158,7 @@ static int hdspm_set_dolby(struct hdspm * hdspm, int dol) | |||
2149 | return 0; | 2158 | return 0; |
2150 | } | 2159 | } |
2151 | 2160 | ||
2152 | static int snd_hdspm_info_dolby(struct snd_kcontrol *kcontrol, | 2161 | #define snd_hdspm_info_dolby snd_ctl_boolean_mono_info |
2153 | struct snd_ctl_elem_info *uinfo) | ||
2154 | { | ||
2155 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
2156 | uinfo->count = 1; | ||
2157 | uinfo->value.integer.min = 0; | ||
2158 | uinfo->value.integer.max = 1; | ||
2159 | return 0; | ||
2160 | } | ||
2161 | 2162 | ||
2162 | static int snd_hdspm_get_dolby(struct snd_kcontrol *kcontrol, | 2163 | static int snd_hdspm_get_dolby(struct snd_kcontrol *kcontrol, |
2163 | struct snd_ctl_elem_value *ucontrol) | 2164 | struct snd_ctl_elem_value *ucontrol) |
@@ -2212,15 +2213,7 @@ static int hdspm_set_professional(struct hdspm * hdspm, int dol) | |||
2212 | return 0; | 2213 | return 0; |
2213 | } | 2214 | } |
2214 | 2215 | ||
2215 | static int snd_hdspm_info_professional(struct snd_kcontrol *kcontrol, | 2216 | #define snd_hdspm_info_professional snd_ctl_boolean_mono_info |
2216 | struct snd_ctl_elem_info *uinfo) | ||
2217 | { | ||
2218 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
2219 | uinfo->count = 1; | ||
2220 | uinfo->value.integer.min = 0; | ||
2221 | uinfo->value.integer.max = 1; | ||
2222 | return 0; | ||
2223 | } | ||
2224 | 2217 | ||
2225 | static int snd_hdspm_get_professional(struct snd_kcontrol *kcontrol, | 2218 | static int snd_hdspm_get_professional(struct snd_kcontrol *kcontrol, |
2226 | struct snd_ctl_elem_value *ucontrol) | 2219 | struct snd_ctl_elem_value *ucontrol) |
@@ -2472,7 +2465,7 @@ static int snd_hdspm_put_qs_wire(struct snd_kcontrol *kcontrol, | |||
2472 | if (val > 2) | 2465 | if (val > 2) |
2473 | val = 2; | 2466 | val = 2; |
2474 | spin_lock_irq(&hdspm->lock); | 2467 | spin_lock_irq(&hdspm->lock); |
2475 | change = (int) val != hdspm_qs_wire(hdspm); | 2468 | change = val != hdspm_qs_wire(hdspm); |
2476 | hdspm_set_qs_wire(hdspm, val); | 2469 | hdspm_set_qs_wire(hdspm, val); |
2477 | spin_unlock_irq(&hdspm->lock); | 2470 | spin_unlock_irq(&hdspm->lock); |
2478 | return change; | 2471 | return change; |
@@ -2573,8 +2566,8 @@ static int snd_hdspm_put_mixer(struct snd_kcontrol *kcontrol, | |||
2573 | source - | 2566 | source - |
2574 | HDSPM_MAX_CHANNELS); | 2567 | HDSPM_MAX_CHANNELS); |
2575 | else | 2568 | else |
2576 | change = | 2569 | change = gain != hdspm_read_in_gain(hdspm, destination, |
2577 | gain != hdspm_read_in_gain(hdspm, destination, source); | 2570 | source); |
2578 | 2571 | ||
2579 | if (change) { | 2572 | if (change) { |
2580 | if (source >= HDSPM_MAX_CHANNELS) | 2573 | if (source >= HDSPM_MAX_CHANNELS) |
@@ -2627,7 +2620,8 @@ static int snd_hdspm_get_playback_mixer(struct snd_kcontrol *kcontrol, | |||
2627 | snd_assert(channel >= 0 | 2620 | snd_assert(channel >= 0 |
2628 | || channel < HDSPM_MAX_CHANNELS, return -EINVAL); | 2621 | || channel < HDSPM_MAX_CHANNELS, return -EINVAL); |
2629 | 2622 | ||
2630 | if ((mapped_channel = hdspm->channel_map[channel]) < 0) | 2623 | mapped_channel = hdspm->channel_map[channel]; |
2624 | if (mapped_channel < 0) | ||
2631 | return -EINVAL; | 2625 | return -EINVAL; |
2632 | 2626 | ||
2633 | spin_lock_irq(&hdspm->lock); | 2627 | spin_lock_irq(&hdspm->lock); |
@@ -2635,10 +2629,12 @@ static int snd_hdspm_get_playback_mixer(struct snd_kcontrol *kcontrol, | |||
2635 | hdspm_read_pb_gain(hdspm, mapped_channel, mapped_channel); | 2629 | hdspm_read_pb_gain(hdspm, mapped_channel, mapped_channel); |
2636 | spin_unlock_irq(&hdspm->lock); | 2630 | spin_unlock_irq(&hdspm->lock); |
2637 | 2631 | ||
2638 | /* snd_printdd("get pb mixer index %d, channel %d, mapped_channel %d, value %d\n", | 2632 | /* |
2639 | ucontrol->id.index, channel, mapped_channel, ucontrol->value.integer.value[0]); | 2633 | snd_printdd("get pb mixer index %d, channel %d, mapped_channel %d, " |
2640 | */ | 2634 | "value %d\n", |
2641 | 2635 | ucontrol->id.index, channel, mapped_channel, | |
2636 | ucontrol->value.integer.value[0]); | ||
2637 | */ | ||
2642 | return 0; | 2638 | return 0; |
2643 | } | 2639 | } |
2644 | 2640 | ||
@@ -2659,7 +2655,8 @@ static int snd_hdspm_put_playback_mixer(struct snd_kcontrol *kcontrol, | |||
2659 | snd_assert(channel >= 0 | 2655 | snd_assert(channel >= 0 |
2660 | || channel < HDSPM_MAX_CHANNELS, return -EINVAL); | 2656 | || channel < HDSPM_MAX_CHANNELS, return -EINVAL); |
2661 | 2657 | ||
2662 | if ((mapped_channel = hdspm->channel_map[channel]) < 0) | 2658 | mapped_channel = hdspm->channel_map[channel]; |
2659 | if (mapped_channel < 0) | ||
2663 | return -EINVAL; | 2660 | return -EINVAL; |
2664 | 2661 | ||
2665 | gain = ucontrol->value.integer.value[0]; | 2662 | gain = ucontrol->value.integer.value[0]; |
@@ -2909,28 +2906,26 @@ static int snd_hdspm_create_controls(struct snd_card *card, struct hdspm * hdspm | |||
2909 | } | 2906 | } |
2910 | 2907 | ||
2911 | /* Channel playback mixer as default control | 2908 | /* Channel playback mixer as default control |
2912 | Note: the whole matrix would be 128*HDSPM_MIXER_CHANNELS Faders, thats too big for any alsamixer | 2909 | Note: the whole matrix would be 128*HDSPM_MIXER_CHANNELS Faders, |
2913 | they are accesible via special IOCTL on hwdep | 2910 | thats too * big for any alsamixer they are accesible via special |
2914 | and the mixer 2dimensional mixer control */ | 2911 | IOCTL on hwdep and the mixer 2dimensional mixer control |
2912 | */ | ||
2915 | 2913 | ||
2916 | snd_hdspm_playback_mixer.name = "Chn"; | 2914 | snd_hdspm_playback_mixer.name = "Chn"; |
2917 | limit = HDSPM_MAX_CHANNELS; | 2915 | limit = HDSPM_MAX_CHANNELS; |
2918 | 2916 | ||
2919 | /* The index values are one greater than the channel ID so that alsamixer | 2917 | /* The index values are one greater than the channel ID so that |
2920 | will display them correctly. We want to use the index for fast lookup | 2918 | * alsamixer will display them correctly. We want to use the index |
2921 | of the relevant channel, but if we use it at all, most ALSA software | 2919 | * for fast lookup of the relevant channel, but if we use it at all, |
2922 | does the wrong thing with it ... | 2920 | * most ALSA software does the wrong thing with it ... |
2923 | */ | 2921 | */ |
2924 | 2922 | ||
2925 | for (idx = 0; idx < limit; ++idx) { | 2923 | for (idx = 0; idx < limit; ++idx) { |
2926 | snd_hdspm_playback_mixer.index = idx + 1; | 2924 | snd_hdspm_playback_mixer.index = idx + 1; |
2927 | if ((err = snd_ctl_add(card, | 2925 | kctl = snd_ctl_new1(&snd_hdspm_playback_mixer, hdspm); |
2928 | kctl = | 2926 | err = snd_ctl_add(card, kctl); |
2929 | snd_ctl_new1 | 2927 | if (err < 0) |
2930 | (&snd_hdspm_playback_mixer, | ||
2931 | hdspm)))) { | ||
2932 | return err; | 2928 | return err; |
2933 | } | ||
2934 | hdspm->playback_mixer_ctls[idx] = kctl; | 2929 | hdspm->playback_mixer_ctls[idx] = kctl; |
2935 | } | 2930 | } |
2936 | 2931 | ||
@@ -2945,7 +2940,7 @@ static void | |||
2945 | snd_hdspm_proc_read_madi(struct snd_info_entry * entry, | 2940 | snd_hdspm_proc_read_madi(struct snd_info_entry * entry, |
2946 | struct snd_info_buffer *buffer) | 2941 | struct snd_info_buffer *buffer) |
2947 | { | 2942 | { |
2948 | struct hdspm *hdspm = (struct hdspm *) entry->private_data; | 2943 | struct hdspm *hdspm = entry->private_data; |
2949 | unsigned int status; | 2944 | unsigned int status; |
2950 | unsigned int status2; | 2945 | unsigned int status2; |
2951 | char *pref_sync_ref; | 2946 | char *pref_sync_ref; |
@@ -2978,14 +2973,14 @@ snd_hdspm_proc_read_madi(struct snd_info_entry * entry, | |||
2978 | (status & HDSPM_midi1IRQPending) ? 1 : 0, | 2973 | (status & HDSPM_midi1IRQPending) ? 1 : 0, |
2979 | hdspm->irq_count); | 2974 | hdspm->irq_count); |
2980 | snd_iprintf(buffer, | 2975 | snd_iprintf(buffer, |
2981 | "HW pointer: id = %d, rawptr = %d (%d->%d) estimated= %ld (bytes)\n", | 2976 | "HW pointer: id = %d, rawptr = %d (%d->%d) " |
2977 | "estimated= %ld (bytes)\n", | ||
2982 | ((status & HDSPM_BufferID) ? 1 : 0), | 2978 | ((status & HDSPM_BufferID) ? 1 : 0), |
2983 | (status & HDSPM_BufferPositionMask), | 2979 | (status & HDSPM_BufferPositionMask), |
2984 | (status & HDSPM_BufferPositionMask) % (2 * | 2980 | (status & HDSPM_BufferPositionMask) % |
2985 | (int)hdspm-> | 2981 | (2 * (int)hdspm->period_bytes), |
2986 | period_bytes), | 2982 | ((status & HDSPM_BufferPositionMask) - 64) % |
2987 | ((status & HDSPM_BufferPositionMask) - | 2983 | (2 * (int)hdspm->period_bytes), |
2988 | 64) % (2 * (int)hdspm->period_bytes), | ||
2989 | (long) hdspm_hw_pointer(hdspm) * 4); | 2984 | (long) hdspm_hw_pointer(hdspm) * 4); |
2990 | 2985 | ||
2991 | snd_iprintf(buffer, | 2986 | snd_iprintf(buffer, |
@@ -2995,24 +2990,22 @@ snd_hdspm_proc_read_madi(struct snd_info_entry * entry, | |||
2995 | hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF, | 2990 | hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF, |
2996 | hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF); | 2991 | hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF); |
2997 | snd_iprintf(buffer, | 2992 | snd_iprintf(buffer, |
2998 | "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, status2=0x%x\n", | 2993 | "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, " |
2994 | "status2=0x%x\n", | ||
2999 | hdspm->control_register, hdspm->control2_register, | 2995 | hdspm->control_register, hdspm->control2_register, |
3000 | status, status2); | 2996 | status, status2); |
3001 | 2997 | ||
3002 | snd_iprintf(buffer, "--- Settings ---\n"); | 2998 | snd_iprintf(buffer, "--- Settings ---\n"); |
3003 | 2999 | ||
3004 | x = 1 << (6 + | 3000 | x = 1 << (6 + hdspm_decode_latency(hdspm->control_register & |
3005 | hdspm_decode_latency(hdspm-> | 3001 | HDSPM_LatencyMask)); |
3006 | control_register & | ||
3007 | HDSPM_LatencyMask)); | ||
3008 | 3002 | ||
3009 | snd_iprintf(buffer, | 3003 | snd_iprintf(buffer, |
3010 | "Size (Latency): %d samples (2 periods of %lu bytes)\n", | 3004 | "Size (Latency): %d samples (2 periods of %lu bytes)\n", |
3011 | x, (unsigned long) hdspm->period_bytes); | 3005 | x, (unsigned long) hdspm->period_bytes); |
3012 | 3006 | ||
3013 | snd_iprintf(buffer, "Line out: %s, Precise Pointer: %s\n", | 3007 | snd_iprintf(buffer, "Line out: %s, Precise Pointer: %s\n", |
3014 | (hdspm-> | 3008 | (hdspm->control_register & HDSPM_LineOut) ? "on " : "off", |
3015 | control_register & HDSPM_LineOut) ? "on " : "off", | ||
3016 | (hdspm->precise_ptr) ? "on" : "off"); | 3009 | (hdspm->precise_ptr) ? "on" : "off"); |
3017 | 3010 | ||
3018 | switch (hdspm->control_register & HDSPM_InputMask) { | 3011 | switch (hdspm->control_register & HDSPM_InputMask) { |
@@ -3040,7 +3033,8 @@ snd_hdspm_proc_read_madi(struct snd_info_entry * entry, | |||
3040 | syncref); | 3033 | syncref); |
3041 | 3034 | ||
3042 | snd_iprintf(buffer, | 3035 | snd_iprintf(buffer, |
3043 | "ClearTrackMarker = %s, Transmit in %s Channel Mode, Auto Input %s\n", | 3036 | "ClearTrackMarker = %s, Transmit in %s Channel Mode, " |
3037 | "Auto Input %s\n", | ||
3044 | (hdspm-> | 3038 | (hdspm-> |
3045 | control_register & HDSPM_clr_tms) ? "on" : "off", | 3039 | control_register & HDSPM_clr_tms) ? "on" : "off", |
3046 | (hdspm-> | 3040 | (hdspm-> |
@@ -3141,7 +3135,7 @@ static void | |||
3141 | snd_hdspm_proc_read_aes32(struct snd_info_entry * entry, | 3135 | snd_hdspm_proc_read_aes32(struct snd_info_entry * entry, |
3142 | struct snd_info_buffer *buffer) | 3136 | struct snd_info_buffer *buffer) |
3143 | { | 3137 | { |
3144 | struct hdspm *hdspm = (struct hdspm *) entry->private_data; | 3138 | struct hdspm *hdspm = entry->private_data; |
3145 | unsigned int status; | 3139 | unsigned int status; |
3146 | unsigned int status2; | 3140 | unsigned int status2; |
3147 | unsigned int timecode; | 3141 | unsigned int timecode; |
@@ -3171,14 +3165,14 @@ snd_hdspm_proc_read_aes32(struct snd_info_entry * entry, | |||
3171 | (status & HDSPM_midi1IRQPending) ? 1 : 0, | 3165 | (status & HDSPM_midi1IRQPending) ? 1 : 0, |
3172 | hdspm->irq_count); | 3166 | hdspm->irq_count); |
3173 | snd_iprintf(buffer, | 3167 | snd_iprintf(buffer, |
3174 | "HW pointer: id = %d, rawptr = %d (%d->%d) estimated= %ld (bytes)\n", | 3168 | "HW pointer: id = %d, rawptr = %d (%d->%d) " |
3169 | "estimated= %ld (bytes)\n", | ||
3175 | ((status & HDSPM_BufferID) ? 1 : 0), | 3170 | ((status & HDSPM_BufferID) ? 1 : 0), |
3176 | (status & HDSPM_BufferPositionMask), | 3171 | (status & HDSPM_BufferPositionMask), |
3177 | (status & HDSPM_BufferPositionMask) % (2 * | 3172 | (status & HDSPM_BufferPositionMask) % |
3178 | (int)hdspm-> | 3173 | (2 * (int)hdspm->period_bytes), |
3179 | period_bytes), | 3174 | ((status & HDSPM_BufferPositionMask) - 64) % |
3180 | ((status & HDSPM_BufferPositionMask) - | 3175 | (2 * (int)hdspm->period_bytes), |
3181 | 64) % (2 * (int)hdspm->period_bytes), | ||
3182 | (long) hdspm_hw_pointer(hdspm) * 4); | 3176 | (long) hdspm_hw_pointer(hdspm) * 4); |
3183 | 3177 | ||
3184 | snd_iprintf(buffer, | 3178 | snd_iprintf(buffer, |
@@ -3188,16 +3182,15 @@ snd_hdspm_proc_read_aes32(struct snd_info_entry * entry, | |||
3188 | hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF, | 3182 | hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF, |
3189 | hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF); | 3183 | hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF); |
3190 | snd_iprintf(buffer, | 3184 | snd_iprintf(buffer, |
3191 | "Register: ctrl1=0x%x, status1=0x%x, status2=0x%x, timecode=0x%x\n", | 3185 | "Register: ctrl1=0x%x, status1=0x%x, status2=0x%x, " |
3186 | "timecode=0x%x\n", | ||
3192 | hdspm->control_register, | 3187 | hdspm->control_register, |
3193 | status, status2, timecode); | 3188 | status, status2, timecode); |
3194 | 3189 | ||
3195 | snd_iprintf(buffer, "--- Settings ---\n"); | 3190 | snd_iprintf(buffer, "--- Settings ---\n"); |
3196 | 3191 | ||
3197 | x = 1 << (6 + | 3192 | x = 1 << (6 + hdspm_decode_latency(hdspm->control_register & |
3198 | hdspm_decode_latency(hdspm-> | 3193 | HDSPM_LatencyMask)); |
3199 | control_register & | ||
3200 | HDSPM_LatencyMask)); | ||
3201 | 3194 | ||
3202 | snd_iprintf(buffer, | 3195 | snd_iprintf(buffer, |
3203 | "Size (Latency): %d samples (2 periods of %lu bytes)\n", | 3196 | "Size (Latency): %d samples (2 periods of %lu bytes)\n", |
@@ -3280,14 +3273,15 @@ snd_hdspm_proc_read_aes32(struct snd_info_entry * entry, | |||
3280 | snd_iprintf(buffer, "--- Status:\n"); | 3273 | snd_iprintf(buffer, "--- Status:\n"); |
3281 | 3274 | ||
3282 | snd_iprintf(buffer, "Word: %s Frequency: %d\n", | 3275 | snd_iprintf(buffer, "Word: %s Frequency: %d\n", |
3283 | (status & HDSPM_AES32_wcLock)? "Sync " : "No Lock", | 3276 | (status & HDSPM_AES32_wcLock)? "Sync " : "No Lock", |
3284 | HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF)); | 3277 | HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF)); |
3285 | 3278 | ||
3286 | for (x = 0; x < 8; x++) { | 3279 | for (x = 0; x < 8; x++) { |
3287 | snd_iprintf(buffer, "AES%d: %s Frequency: %d\n", | 3280 | snd_iprintf(buffer, "AES%d: %s Frequency: %d\n", |
3288 | x+1, | 3281 | x+1, |
3289 | (status2 & (HDSPM_LockAES >> x))? "Sync ": "No Lock", | 3282 | (status2 & (HDSPM_LockAES >> x)) ? |
3290 | HDSPM_bit2freq((timecode >> (4*x)) & 0xF)); | 3283 | "Sync ": "No Lock", |
3284 | HDSPM_bit2freq((timecode >> (4*x)) & 0xF)); | ||
3291 | } | 3285 | } |
3292 | 3286 | ||
3293 | switch (hdspm_autosync_ref(hdspm)) { | 3287 | switch (hdspm_autosync_ref(hdspm)) { |
@@ -3313,12 +3307,11 @@ static void | |||
3313 | snd_hdspm_proc_read_debug(struct snd_info_entry * entry, | 3307 | snd_hdspm_proc_read_debug(struct snd_info_entry * entry, |
3314 | struct snd_info_buffer *buffer) | 3308 | struct snd_info_buffer *buffer) |
3315 | { | 3309 | { |
3316 | struct hdspm *hdspm = (struct hdspm *)entry->private_data; | 3310 | struct hdspm *hdspm = entry->private_data; |
3317 | 3311 | ||
3318 | int j,i; | 3312 | int j,i; |
3319 | 3313 | ||
3320 | for (i = 0; i < 256 /* 1024*64 */; i += j) | 3314 | for (i = 0; i < 256 /* 1024*64 */; i += j) { |
3321 | { | ||
3322 | snd_iprintf(buffer, "0x%08X: ", i); | 3315 | snd_iprintf(buffer, "0x%08X: ", i); |
3323 | for (j = 0; j < 16; j += 4) | 3316 | for (j = 0; j < 16; j += 4) |
3324 | snd_iprintf(buffer, "%08X ", hdspm_read(hdspm, i + j)); | 3317 | snd_iprintf(buffer, "%08X ", hdspm_read(hdspm, i + j)); |
@@ -3361,14 +3354,20 @@ static int snd_hdspm_set_defaults(struct hdspm * hdspm) | |||
3361 | /* set defaults: */ | 3354 | /* set defaults: */ |
3362 | 3355 | ||
3363 | if (hdspm->is_aes32) | 3356 | if (hdspm->is_aes32) |
3364 | hdspm->control_register = HDSPM_ClockModeMaster | /* Master Cloack Mode on */ | 3357 | hdspm->control_register = |
3365 | hdspm_encode_latency(7) | /* latency maximum = 8192 samples */ | 3358 | HDSPM_ClockModeMaster | /* Master Cloack Mode on */ |
3359 | hdspm_encode_latency(7) | /* latency maximum = | ||
3360 | * 8192 samples | ||
3361 | */ | ||
3366 | HDSPM_SyncRef0 | /* AES1 is syncclock */ | 3362 | HDSPM_SyncRef0 | /* AES1 is syncclock */ |
3367 | HDSPM_LineOut | /* Analog output in */ | 3363 | HDSPM_LineOut | /* Analog output in */ |
3368 | HDSPM_Professional; /* Professional mode */ | 3364 | HDSPM_Professional; /* Professional mode */ |
3369 | else | 3365 | else |
3370 | hdspm->control_register = HDSPM_ClockModeMaster | /* Master Cloack Mode on */ | 3366 | hdspm->control_register = |
3371 | hdspm_encode_latency(7) | /* latency maximum = 8192 samples */ | 3367 | HDSPM_ClockModeMaster | /* Master Cloack Mode on */ |
3368 | hdspm_encode_latency(7) | /* latency maximum = | ||
3369 | * 8192 samples | ||
3370 | */ | ||
3372 | HDSPM_InputCoaxial | /* Input Coax not Optical */ | 3371 | HDSPM_InputCoaxial | /* Input Coax not Optical */ |
3373 | HDSPM_SyncRef_MADI | /* Madi is syncclock */ | 3372 | HDSPM_SyncRef_MADI | /* Madi is syncclock */ |
3374 | HDSPM_LineOut | /* Analog output in */ | 3373 | HDSPM_LineOut | /* Analog output in */ |
@@ -3399,7 +3398,8 @@ static int snd_hdspm_set_defaults(struct hdspm * hdspm) | |||
3399 | 3398 | ||
3400 | if (line_outs_monitor[hdspm->dev]) { | 3399 | if (line_outs_monitor[hdspm->dev]) { |
3401 | 3400 | ||
3402 | snd_printk(KERN_INFO "HDSPM: sending all playback streams to line outs.\n"); | 3401 | snd_printk(KERN_INFO "HDSPM: " |
3402 | "sending all playback streams to line outs.\n"); | ||
3403 | 3403 | ||
3404 | for (i = 0; i < HDSPM_MIXER_CHANNELS; i++) { | 3404 | for (i = 0; i < HDSPM_MIXER_CHANNELS; i++) { |
3405 | if (hdspm_write_pb_gain(hdspm, i, i, UNITY_GAIN)) | 3405 | if (hdspm_write_pb_gain(hdspm, i, i, UNITY_GAIN)) |
@@ -3448,20 +3448,16 @@ static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id) | |||
3448 | if (audio) { | 3448 | if (audio) { |
3449 | 3449 | ||
3450 | if (hdspm->capture_substream) | 3450 | if (hdspm->capture_substream) |
3451 | snd_pcm_period_elapsed(hdspm->pcm-> | 3451 | snd_pcm_period_elapsed(hdspm->capture_substream); |
3452 | streams | ||
3453 | [SNDRV_PCM_STREAM_CAPTURE]. | ||
3454 | substream); | ||
3455 | 3452 | ||
3456 | if (hdspm->playback_substream) | 3453 | if (hdspm->playback_substream) |
3457 | snd_pcm_period_elapsed(hdspm->pcm-> | 3454 | snd_pcm_period_elapsed(hdspm->playback_substream); |
3458 | streams | ||
3459 | [SNDRV_PCM_STREAM_PLAYBACK]. | ||
3460 | substream); | ||
3461 | } | 3455 | } |
3462 | 3456 | ||
3463 | if (midi0 && midi0status) { | 3457 | if (midi0 && midi0status) { |
3464 | /* we disable interrupts for this input until processing is done */ | 3458 | /* we disable interrupts for this input until processing |
3459 | * is done | ||
3460 | */ | ||
3465 | hdspm->control_register &= ~HDSPM_Midi0InterruptEnable; | 3461 | hdspm->control_register &= ~HDSPM_Midi0InterruptEnable; |
3466 | hdspm_write(hdspm, HDSPM_controlRegister, | 3462 | hdspm_write(hdspm, HDSPM_controlRegister, |
3467 | hdspm->control_register); | 3463 | hdspm->control_register); |
@@ -3469,7 +3465,9 @@ static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id) | |||
3469 | schedule = 1; | 3465 | schedule = 1; |
3470 | } | 3466 | } |
3471 | if (midi1 && midi1status) { | 3467 | if (midi1 && midi1status) { |
3472 | /* we disable interrupts for this input until processing is done */ | 3468 | /* we disable interrupts for this input until processing |
3469 | * is done | ||
3470 | */ | ||
3473 | hdspm->control_register &= ~HDSPM_Midi1InterruptEnable; | 3471 | hdspm->control_register &= ~HDSPM_Midi1InterruptEnable; |
3474 | hdspm_write(hdspm, HDSPM_controlRegister, | 3472 | hdspm_write(hdspm, HDSPM_controlRegister, |
3475 | hdspm->control_register); | 3473 | hdspm->control_register); |
@@ -3501,16 +3499,16 @@ static char *hdspm_channel_buffer_location(struct hdspm * hdspm, | |||
3501 | snd_assert(channel >= 0 | 3499 | snd_assert(channel >= 0 |
3502 | || channel < HDSPM_MAX_CHANNELS, return NULL); | 3500 | || channel < HDSPM_MAX_CHANNELS, return NULL); |
3503 | 3501 | ||
3504 | if ((mapped_channel = hdspm->channel_map[channel]) < 0) | 3502 | mapped_channel = hdspm->channel_map[channel]; |
3503 | if (mapped_channel < 0) | ||
3505 | return NULL; | 3504 | return NULL; |
3506 | 3505 | ||
3507 | if (stream == SNDRV_PCM_STREAM_CAPTURE) { | 3506 | if (stream == SNDRV_PCM_STREAM_CAPTURE) |
3508 | return hdspm->capture_buffer + | 3507 | return hdspm->capture_buffer + |
3509 | mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES; | 3508 | mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES; |
3510 | } else { | 3509 | else |
3511 | return hdspm->playback_buffer + | 3510 | return hdspm->playback_buffer + |
3512 | mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES; | 3511 | mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES; |
3513 | } | ||
3514 | } | 3512 | } |
3515 | 3513 | ||
3516 | 3514 | ||
@@ -3525,9 +3523,9 @@ static int snd_hdspm_playback_copy(struct snd_pcm_substream *substream, | |||
3525 | snd_assert(pos + count <= HDSPM_CHANNEL_BUFFER_BYTES / 4, | 3523 | snd_assert(pos + count <= HDSPM_CHANNEL_BUFFER_BYTES / 4, |
3526 | return -EINVAL); | 3524 | return -EINVAL); |
3527 | 3525 | ||
3528 | channel_buf = hdspm_channel_buffer_location(hdspm, | 3526 | channel_buf = |
3529 | substream->pstr-> | 3527 | hdspm_channel_buffer_location(hdspm, substream->pstr->stream, |
3530 | stream, channel); | 3528 | channel); |
3531 | 3529 | ||
3532 | snd_assert(channel_buf != NULL, return -EIO); | 3530 | snd_assert(channel_buf != NULL, return -EIO); |
3533 | 3531 | ||
@@ -3544,9 +3542,9 @@ static int snd_hdspm_capture_copy(struct snd_pcm_substream *substream, | |||
3544 | snd_assert(pos + count <= HDSPM_CHANNEL_BUFFER_BYTES / 4, | 3542 | snd_assert(pos + count <= HDSPM_CHANNEL_BUFFER_BYTES / 4, |
3545 | return -EINVAL); | 3543 | return -EINVAL); |
3546 | 3544 | ||
3547 | channel_buf = hdspm_channel_buffer_location(hdspm, | 3545 | channel_buf = |
3548 | substream->pstr-> | 3546 | hdspm_channel_buffer_location(hdspm, substream->pstr->stream, |
3549 | stream, channel); | 3547 | channel); |
3550 | snd_assert(channel_buf != NULL, return -EIO); | 3548 | snd_assert(channel_buf != NULL, return -EIO); |
3551 | return copy_to_user(dst, channel_buf + pos * 4, count * 4); | 3549 | return copy_to_user(dst, channel_buf + pos * 4, count * 4); |
3552 | } | 3550 | } |
@@ -3559,8 +3557,8 @@ static int snd_hdspm_hw_silence(struct snd_pcm_substream *substream, | |||
3559 | char *channel_buf; | 3557 | char *channel_buf; |
3560 | 3558 | ||
3561 | channel_buf = | 3559 | channel_buf = |
3562 | hdspm_channel_buffer_location(hdspm, substream->pstr->stream, | 3560 | hdspm_channel_buffer_location(hdspm, substream->pstr->stream, |
3563 | channel); | 3561 | channel); |
3564 | snd_assert(channel_buf != NULL, return -EIO); | 3562 | snd_assert(channel_buf != NULL, return -EIO); |
3565 | memset(channel_buf + pos * 4, 0, count * 4); | 3563 | memset(channel_buf + pos * 4, 0, count * 4); |
3566 | return 0; | 3564 | return 0; |
@@ -3616,7 +3614,7 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream, | |||
3616 | other_pid = hdspm->playback_pid; | 3614 | other_pid = hdspm->playback_pid; |
3617 | } | 3615 | } |
3618 | 3616 | ||
3619 | if ((other_pid > 0) && (this_pid != other_pid)) { | 3617 | if (other_pid > 0 && this_pid != other_pid) { |
3620 | 3618 | ||
3621 | /* The other stream is open, and not by the same | 3619 | /* The other stream is open, and not by the same |
3622 | task as this one. Make sure that the parameters | 3620 | task as this one. Make sure that the parameters |
@@ -3633,7 +3631,7 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream, | |||
3633 | if (params_period_size(params) != hdspm->period_bytes / 4) { | 3631 | if (params_period_size(params) != hdspm->period_bytes / 4) { |
3634 | spin_unlock_irq(&hdspm->lock); | 3632 | spin_unlock_irq(&hdspm->lock); |
3635 | _snd_pcm_hw_param_setempty(params, | 3633 | _snd_pcm_hw_param_setempty(params, |
3636 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE); | 3634 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE); |
3637 | return -EBUSY; | 3635 | return -EBUSY; |
3638 | } | 3636 | } |
3639 | 3637 | ||
@@ -3644,7 +3642,8 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream, | |||
3644 | /* how to make sure that the rate matches an externally-set one ? */ | 3642 | /* how to make sure that the rate matches an externally-set one ? */ |
3645 | 3643 | ||
3646 | spin_lock_irq(&hdspm->lock); | 3644 | spin_lock_irq(&hdspm->lock); |
3647 | if ((err = hdspm_set_rate(hdspm, params_rate(params), 0)) < 0) { | 3645 | err = hdspm_set_rate(hdspm, params_rate(params), 0); |
3646 | if (err < 0) { | ||
3648 | spin_unlock_irq(&hdspm->lock); | 3647 | spin_unlock_irq(&hdspm->lock); |
3649 | _snd_pcm_hw_param_setempty(params, | 3648 | _snd_pcm_hw_param_setempty(params, |
3650 | SNDRV_PCM_HW_PARAM_RATE); | 3649 | SNDRV_PCM_HW_PARAM_RATE); |
@@ -3652,16 +3651,17 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream, | |||
3652 | } | 3651 | } |
3653 | spin_unlock_irq(&hdspm->lock); | 3652 | spin_unlock_irq(&hdspm->lock); |
3654 | 3653 | ||
3655 | if ((err = | 3654 | err = hdspm_set_interrupt_interval(hdspm, |
3656 | hdspm_set_interrupt_interval(hdspm, | 3655 | params_period_size(params)); |
3657 | params_period_size(params))) < | 3656 | if (err < 0) { |
3658 | 0) { | ||
3659 | _snd_pcm_hw_param_setempty(params, | 3657 | _snd_pcm_hw_param_setempty(params, |
3660 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE); | 3658 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE); |
3661 | return err; | 3659 | return err; |
3662 | } | 3660 | } |
3663 | 3661 | ||
3664 | /* Memory allocation, takashi's method, dont know if we should spinlock */ | 3662 | /* Memory allocation, takashi's method, dont know if we should |
3663 | * spinlock | ||
3664 | */ | ||
3665 | /* malloc all buffer even if not enabled to get sure */ | 3665 | /* malloc all buffer even if not enabled to get sure */ |
3666 | /* Update for MADI rev 204: we need to allocate for all channels, | 3666 | /* Update for MADI rev 204: we need to allocate for all channels, |
3667 | * otherwise it doesn't work at 96kHz */ | 3667 | * otherwise it doesn't work at 96kHz */ |
@@ -3746,7 +3746,8 @@ static int snd_hdspm_channel_info(struct snd_pcm_substream *substream, | |||
3746 | 3746 | ||
3747 | snd_assert(info->channel < HDSPM_MAX_CHANNELS, return -EINVAL); | 3747 | snd_assert(info->channel < HDSPM_MAX_CHANNELS, return -EINVAL); |
3748 | 3748 | ||
3749 | if ((mapped_channel = hdspm->channel_map[info->channel]) < 0) | 3749 | mapped_channel = hdspm->channel_map[info->channel]; |
3750 | if (mapped_channel < 0) | ||
3750 | return -EINVAL; | 3751 | return -EINVAL; |
3751 | 3752 | ||
3752 | info->offset = mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES; | 3753 | info->offset = mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES; |
@@ -3760,15 +3761,13 @@ static int snd_hdspm_ioctl(struct snd_pcm_substream *substream, | |||
3760 | { | 3761 | { |
3761 | switch (cmd) { | 3762 | switch (cmd) { |
3762 | case SNDRV_PCM_IOCTL1_RESET: | 3763 | case SNDRV_PCM_IOCTL1_RESET: |
3763 | { | 3764 | return snd_hdspm_reset(substream); |
3764 | return snd_hdspm_reset(substream); | ||
3765 | } | ||
3766 | 3765 | ||
3767 | case SNDRV_PCM_IOCTL1_CHANNEL_INFO: | 3766 | case SNDRV_PCM_IOCTL1_CHANNEL_INFO: |
3768 | { | 3767 | { |
3769 | struct snd_pcm_channel_info *info = arg; | 3768 | struct snd_pcm_channel_info *info = arg; |
3770 | return snd_hdspm_channel_info(substream, info); | 3769 | return snd_hdspm_channel_info(substream, info); |
3771 | } | 3770 | } |
3772 | default: | 3771 | default: |
3773 | break; | 3772 | break; |
3774 | } | 3773 | } |
@@ -3979,9 +3978,12 @@ static int snd_hdspm_hw_rule_channels(struct snd_pcm_hw_params *params, | |||
3979 | } | 3978 | } |
3980 | 3979 | ||
3981 | 3980 | ||
3982 | static unsigned int hdspm_aes32_sample_rates[] = { 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000 }; | 3981 | static unsigned int hdspm_aes32_sample_rates[] = { |
3982 | 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000 | ||
3983 | }; | ||
3983 | 3984 | ||
3984 | static struct snd_pcm_hw_constraint_list hdspm_hw_constraints_aes32_sample_rates = { | 3985 | static struct snd_pcm_hw_constraint_list |
3986 | hdspm_hw_constraints_aes32_sample_rates = { | ||
3985 | .count = ARRAY_SIZE(hdspm_aes32_sample_rates), | 3987 | .count = ARRAY_SIZE(hdspm_aes32_sample_rates), |
3986 | .list = hdspm_aes32_sample_rates, | 3988 | .list = hdspm_aes32_sample_rates, |
3987 | .mask = 0 | 3989 | .mask = 0 |
@@ -4107,7 +4109,7 @@ static int snd_hdspm_hwdep_dummy_op(struct snd_hwdep * hw, struct file *file) | |||
4107 | static int snd_hdspm_hwdep_ioctl(struct snd_hwdep * hw, struct file *file, | 4109 | static int snd_hdspm_hwdep_ioctl(struct snd_hwdep * hw, struct file *file, |
4108 | unsigned int cmd, unsigned long arg) | 4110 | unsigned int cmd, unsigned long arg) |
4109 | { | 4111 | { |
4110 | struct hdspm *hdspm = (struct hdspm *) hw->private_data; | 4112 | struct hdspm *hdspm = hw->private_data; |
4111 | struct hdspm_mixer_ioctl mixer; | 4113 | struct hdspm_mixer_ioctl mixer; |
4112 | struct hdspm_config_info info; | 4114 | struct hdspm_config_info info; |
4113 | struct hdspm_version hdspm_version; | 4115 | struct hdspm_version hdspm_version; |
@@ -4115,11 +4117,12 @@ static int snd_hdspm_hwdep_ioctl(struct snd_hwdep * hw, struct file *file, | |||
4115 | 4117 | ||
4116 | switch (cmd) { | 4118 | switch (cmd) { |
4117 | 4119 | ||
4118 | |||
4119 | case SNDRV_HDSPM_IOCTL_GET_PEAK_RMS: | 4120 | case SNDRV_HDSPM_IOCTL_GET_PEAK_RMS: |
4120 | if (copy_from_user(&rms, (void __user *)arg, sizeof(rms))) | 4121 | if (copy_from_user(&rms, (void __user *)arg, sizeof(rms))) |
4121 | return -EFAULT; | 4122 | return -EFAULT; |
4122 | /* maybe there is a chance to memorymap in future so dont touch just copy */ | 4123 | /* maybe there is a chance to memorymap in future |
4124 | * so dont touch just copy | ||
4125 | */ | ||
4123 | if(copy_to_user_fromio((void __user *)rms.peak, | 4126 | if(copy_to_user_fromio((void __user *)rms.peak, |
4124 | hdspm->iobase+HDSPM_MADI_peakrmsbase, | 4127 | hdspm->iobase+HDSPM_MADI_peakrmsbase, |
4125 | sizeof(struct hdspm_peak_rms)) != 0 ) | 4128 | sizeof(struct hdspm_peak_rms)) != 0 ) |
@@ -4131,21 +4134,16 @@ static int snd_hdspm_hwdep_ioctl(struct snd_hwdep * hw, struct file *file, | |||
4131 | case SNDRV_HDSPM_IOCTL_GET_CONFIG_INFO: | 4134 | case SNDRV_HDSPM_IOCTL_GET_CONFIG_INFO: |
4132 | 4135 | ||
4133 | spin_lock_irq(&hdspm->lock); | 4136 | spin_lock_irq(&hdspm->lock); |
4134 | info.pref_sync_ref = | 4137 | info.pref_sync_ref = hdspm_pref_sync_ref(hdspm); |
4135 | (unsigned char) hdspm_pref_sync_ref(hdspm); | 4138 | info.wordclock_sync_check = hdspm_wc_sync_check(hdspm); |
4136 | info.wordclock_sync_check = | ||
4137 | (unsigned char) hdspm_wc_sync_check(hdspm); | ||
4138 | 4139 | ||
4139 | info.system_sample_rate = hdspm->system_sample_rate; | 4140 | info.system_sample_rate = hdspm->system_sample_rate; |
4140 | info.autosync_sample_rate = | 4141 | info.autosync_sample_rate = |
4141 | hdspm_external_sample_rate(hdspm); | 4142 | hdspm_external_sample_rate(hdspm); |
4142 | info.system_clock_mode = | 4143 | info.system_clock_mode = hdspm_system_clock_mode(hdspm); |
4143 | (unsigned char) hdspm_system_clock_mode(hdspm); | 4144 | info.clock_source = hdspm_clock_source(hdspm); |
4144 | info.clock_source = | 4145 | info.autosync_ref = hdspm_autosync_ref(hdspm); |
4145 | (unsigned char) hdspm_clock_source(hdspm); | 4146 | info.line_out = hdspm_line_out(hdspm); |
4146 | info.autosync_ref = | ||
4147 | (unsigned char) hdspm_autosync_ref(hdspm); | ||
4148 | info.line_out = (unsigned char) hdspm_line_out(hdspm); | ||
4149 | info.passthru = 0; | 4147 | info.passthru = 0; |
4150 | spin_unlock_irq(&hdspm->lock); | 4148 | spin_unlock_irq(&hdspm->lock); |
4151 | if (copy_to_user((void __user *) arg, &info, sizeof(info))) | 4149 | if (copy_to_user((void __user *) arg, &info, sizeof(info))) |
@@ -4162,8 +4160,8 @@ static int snd_hdspm_hwdep_ioctl(struct snd_hwdep * hw, struct file *file, | |||
4162 | case SNDRV_HDSPM_IOCTL_GET_MIXER: | 4160 | case SNDRV_HDSPM_IOCTL_GET_MIXER: |
4163 | if (copy_from_user(&mixer, (void __user *)arg, sizeof(mixer))) | 4161 | if (copy_from_user(&mixer, (void __user *)arg, sizeof(mixer))) |
4164 | return -EFAULT; | 4162 | return -EFAULT; |
4165 | if (copy_to_user | 4163 | if (copy_to_user((void __user *)mixer.mixer, hdspm->mixer, |
4166 | ((void __user *)mixer.mixer, hdspm->mixer, sizeof(struct hdspm_mixer))) | 4164 | sizeof(struct hdspm_mixer))) |
4167 | return -EFAULT; | 4165 | return -EFAULT; |
4168 | break; | 4166 | break; |
4169 | 4167 | ||
@@ -4206,7 +4204,8 @@ static int __devinit snd_hdspm_create_hwdep(struct snd_card *card, | |||
4206 | struct snd_hwdep *hw; | 4204 | struct snd_hwdep *hw; |
4207 | int err; | 4205 | int err; |
4208 | 4206 | ||
4209 | if ((err = snd_hwdep_new(card, "HDSPM hwdep", 0, &hw)) < 0) | 4207 | err = snd_hwdep_new(card, "HDSPM hwdep", 0, &hw); |
4208 | if (err < 0) | ||
4210 | return err; | 4209 | return err; |
4211 | 4210 | ||
4212 | hdspm->hwdep = hw; | 4211 | hdspm->hwdep = hw; |
@@ -4232,15 +4231,15 @@ static int __devinit snd_hdspm_preallocate_memory(struct hdspm * hdspm) | |||
4232 | 4231 | ||
4233 | pcm = hdspm->pcm; | 4232 | pcm = hdspm->pcm; |
4234 | 4233 | ||
4235 | /* wanted = HDSPM_DMA_AREA_BYTES + 4096;*/ /* dont know why, but it works */ | ||
4236 | wanted = HDSPM_DMA_AREA_BYTES; | 4234 | wanted = HDSPM_DMA_AREA_BYTES; |
4237 | 4235 | ||
4238 | if ((err = | 4236 | err = |
4239 | snd_pcm_lib_preallocate_pages_for_all(pcm, | 4237 | snd_pcm_lib_preallocate_pages_for_all(pcm, |
4240 | SNDRV_DMA_TYPE_DEV_SG, | 4238 | SNDRV_DMA_TYPE_DEV_SG, |
4241 | snd_dma_pci_data(hdspm->pci), | 4239 | snd_dma_pci_data(hdspm->pci), |
4242 | wanted, | 4240 | wanted, |
4243 | wanted)) < 0) { | 4241 | wanted); |
4242 | if (err < 0) { | ||
4244 | snd_printdd("Could not preallocate %zd Bytes\n", wanted); | 4243 | snd_printdd("Could not preallocate %zd Bytes\n", wanted); |
4245 | 4244 | ||
4246 | return err; | 4245 | return err; |
@@ -4256,8 +4255,7 @@ static void hdspm_set_sgbuf(struct hdspm * hdspm, struct snd_sg_buf *sgbuf, | |||
4256 | int i; | 4255 | int i; |
4257 | for (i = 0; i < (channels * 16); i++) | 4256 | for (i = 0; i < (channels * 16); i++) |
4258 | hdspm_write(hdspm, reg + 4 * i, | 4257 | hdspm_write(hdspm, reg + 4 * i, |
4259 | snd_pcm_sgbuf_get_addr(sgbuf, | 4258 | snd_pcm_sgbuf_get_addr(sgbuf, (size_t) 4096 * i)); |
4260 | (size_t) 4096 * i)); | ||
4261 | } | 4259 | } |
4262 | 4260 | ||
4263 | /* ------------- ALSA Devices ---------------------------- */ | 4261 | /* ------------- ALSA Devices ---------------------------- */ |
@@ -4267,7 +4265,8 @@ static int __devinit snd_hdspm_create_pcm(struct snd_card *card, | |||
4267 | struct snd_pcm *pcm; | 4265 | struct snd_pcm *pcm; |
4268 | int err; | 4266 | int err; |
4269 | 4267 | ||
4270 | if ((err = snd_pcm_new(card, hdspm->card_name, 0, 1, 1, &pcm)) < 0) | 4268 | err = snd_pcm_new(card, hdspm->card_name, 0, 1, 1, &pcm); |
4269 | if (err < 0) | ||
4271 | return err; | 4270 | return err; |
4272 | 4271 | ||
4273 | hdspm->pcm = pcm; | 4272 | hdspm->pcm = pcm; |
@@ -4281,7 +4280,8 @@ static int __devinit snd_hdspm_create_pcm(struct snd_card *card, | |||
4281 | 4280 | ||
4282 | pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX; | 4281 | pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX; |
4283 | 4282 | ||
4284 | if ((err = snd_hdspm_preallocate_memory(hdspm)) < 0) | 4283 | err = snd_hdspm_preallocate_memory(hdspm); |
4284 | if (err < 0) | ||
4285 | return err; | 4285 | return err; |
4286 | 4286 | ||
4287 | return 0; | 4287 | return 0; |
@@ -4299,19 +4299,24 @@ static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card, | |||
4299 | int err; | 4299 | int err; |
4300 | 4300 | ||
4301 | snd_printdd("Create card...\n"); | 4301 | snd_printdd("Create card...\n"); |
4302 | if ((err = snd_hdspm_create_pcm(card, hdspm)) < 0) | 4302 | err = snd_hdspm_create_pcm(card, hdspm); |
4303 | if (err < 0) | ||
4303 | return err; | 4304 | return err; |
4304 | 4305 | ||
4305 | if ((err = snd_hdspm_create_midi(card, hdspm, 0)) < 0) | 4306 | err = snd_hdspm_create_midi(card, hdspm, 0); |
4307 | if (err < 0) | ||
4306 | return err; | 4308 | return err; |
4307 | 4309 | ||
4308 | if ((err = snd_hdspm_create_midi(card, hdspm, 1)) < 0) | 4310 | err = snd_hdspm_create_midi(card, hdspm, 1); |
4311 | if (err < 0) | ||
4309 | return err; | 4312 | return err; |
4310 | 4313 | ||
4311 | if ((err = snd_hdspm_create_controls(card, hdspm)) < 0) | 4314 | err = snd_hdspm_create_controls(card, hdspm); |
4315 | if (err < 0) | ||
4312 | return err; | 4316 | return err; |
4313 | 4317 | ||
4314 | if ((err = snd_hdspm_create_hwdep(card, hdspm)) < 0) | 4318 | err = snd_hdspm_create_hwdep(card, hdspm); |
4319 | if (err < 0) | ||
4315 | return err; | 4320 | return err; |
4316 | 4321 | ||
4317 | snd_printdd("proc init...\n"); | 4322 | snd_printdd("proc init...\n"); |
@@ -4326,7 +4331,8 @@ static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card, | |||
4326 | hdspm->playback_substream = NULL; | 4331 | hdspm->playback_substream = NULL; |
4327 | 4332 | ||
4328 | snd_printdd("Set defaults...\n"); | 4333 | snd_printdd("Set defaults...\n"); |
4329 | if ((err = snd_hdspm_set_defaults(hdspm)) < 0) | 4334 | err = snd_hdspm_set_defaults(hdspm); |
4335 | if (err < 0) | ||
4330 | return err; | 4336 | return err; |
4331 | 4337 | ||
4332 | snd_printdd("Update mixer controls...\n"); | 4338 | snd_printdd("Update mixer controls...\n"); |
@@ -4334,7 +4340,8 @@ static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card, | |||
4334 | 4340 | ||
4335 | snd_printdd("Initializeing complete ???\n"); | 4341 | snd_printdd("Initializeing complete ???\n"); |
4336 | 4342 | ||
4337 | if ((err = snd_card_register(card)) < 0) { | 4343 | err = snd_card_register(card); |
4344 | if (err < 0) { | ||
4338 | snd_printk(KERN_ERR "HDSPM: error registering card\n"); | 4345 | snd_printk(KERN_ERR "HDSPM: error registering card\n"); |
4339 | return err; | 4346 | return err; |
4340 | } | 4347 | } |
@@ -4344,36 +4351,18 @@ static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card, | |||
4344 | return 0; | 4351 | return 0; |
4345 | } | 4352 | } |
4346 | 4353 | ||
4347 | static int __devinit snd_hdspm_create(struct snd_card *card, struct hdspm * hdspm, | 4354 | static int __devinit snd_hdspm_create(struct snd_card *card, |
4355 | struct hdspm *hdspm, | ||
4348 | int precise_ptr, int enable_monitor) | 4356 | int precise_ptr, int enable_monitor) |
4349 | { | 4357 | { |
4350 | struct pci_dev *pci = hdspm->pci; | 4358 | struct pci_dev *pci = hdspm->pci; |
4351 | int err; | 4359 | int err; |
4352 | int i; | ||
4353 | |||
4354 | unsigned long io_extent; | 4360 | unsigned long io_extent; |
4355 | 4361 | ||
4356 | hdspm->irq = -1; | 4362 | hdspm->irq = -1; |
4357 | hdspm->irq_count = 0; | 4363 | |
4358 | |||
4359 | hdspm->midi[0].rmidi = NULL; | ||
4360 | hdspm->midi[1].rmidi = NULL; | ||
4361 | hdspm->midi[0].input = NULL; | ||
4362 | hdspm->midi[1].input = NULL; | ||
4363 | hdspm->midi[0].output = NULL; | ||
4364 | hdspm->midi[1].output = NULL; | ||
4365 | spin_lock_init(&hdspm->midi[0].lock); | 4364 | spin_lock_init(&hdspm->midi[0].lock); |
4366 | spin_lock_init(&hdspm->midi[1].lock); | 4365 | spin_lock_init(&hdspm->midi[1].lock); |
4367 | hdspm->iobase = NULL; | ||
4368 | hdspm->control_register = 0; | ||
4369 | hdspm->control2_register = 0; | ||
4370 | |||
4371 | hdspm->playback_buffer = NULL; | ||
4372 | hdspm->capture_buffer = NULL; | ||
4373 | |||
4374 | for (i = 0; i < HDSPM_MAX_CHANNELS; ++i) | ||
4375 | hdspm->playback_mixer_ctls[i] = NULL; | ||
4376 | hdspm->mixer = NULL; | ||
4377 | 4366 | ||
4378 | hdspm->card = card; | 4367 | hdspm->card = card; |
4379 | 4368 | ||
@@ -4396,12 +4385,14 @@ static int __devinit snd_hdspm_create(struct snd_card *card, struct hdspm * hdsp | |||
4396 | hdspm->card_name = "RME HDSPM MADI"; | 4385 | hdspm->card_name = "RME HDSPM MADI"; |
4397 | } | 4386 | } |
4398 | 4387 | ||
4399 | if ((err = pci_enable_device(pci)) < 0) | 4388 | err = pci_enable_device(pci); |
4389 | if (err < 0) | ||
4400 | return err; | 4390 | return err; |
4401 | 4391 | ||
4402 | pci_set_master(hdspm->pci); | 4392 | pci_set_master(hdspm->pci); |
4403 | 4393 | ||
4404 | if ((err = pci_request_regions(pci, "hdspm")) < 0) | 4394 | err = pci_request_regions(pci, "hdspm"); |
4395 | if (err < 0) | ||
4405 | return err; | 4396 | return err; |
4406 | 4397 | ||
4407 | hdspm->port = pci_resource_start(pci, 0); | 4398 | hdspm->port = pci_resource_start(pci, 0); |
@@ -4411,8 +4402,10 @@ static int __devinit snd_hdspm_create(struct snd_card *card, struct hdspm * hdsp | |||
4411 | hdspm->port, hdspm->port + io_extent - 1); | 4402 | hdspm->port, hdspm->port + io_extent - 1); |
4412 | 4403 | ||
4413 | 4404 | ||
4414 | if ((hdspm->iobase = ioremap_nocache(hdspm->port, io_extent)) == NULL) { | 4405 | hdspm->iobase = ioremap_nocache(hdspm->port, io_extent); |
4415 | snd_printk(KERN_ERR "HDSPM: unable to remap region 0x%lx-0x%lx\n", | 4406 | if (!hdspm->iobase) { |
4407 | snd_printk(KERN_ERR "HDSPM: " | ||
4408 | "unable to remap region 0x%lx-0x%lx\n", | ||
4416 | hdspm->port, hdspm->port + io_extent - 1); | 4409 | hdspm->port, hdspm->port + io_extent - 1); |
4417 | return -EBUSY; | 4410 | return -EBUSY; |
4418 | } | 4411 | } |
@@ -4435,9 +4428,10 @@ static int __devinit snd_hdspm_create(struct snd_card *card, struct hdspm * hdsp | |||
4435 | 4428 | ||
4436 | snd_printdd("kmalloc Mixer memory of %zd Bytes\n", | 4429 | snd_printdd("kmalloc Mixer memory of %zd Bytes\n", |
4437 | sizeof(struct hdspm_mixer)); | 4430 | sizeof(struct hdspm_mixer)); |
4438 | if ((hdspm->mixer = kmalloc(sizeof(struct hdspm_mixer), GFP_KERNEL)) | 4431 | hdspm->mixer = kzalloc(sizeof(struct hdspm_mixer), GFP_KERNEL); |
4439 | == NULL) { | 4432 | if (!hdspm->mixer) { |
4440 | snd_printk(KERN_ERR "HDSPM: unable to kmalloc Mixer memory of %d Bytes\n", | 4433 | snd_printk(KERN_ERR "HDSPM: " |
4434 | "unable to kmalloc Mixer memory of %d Bytes\n", | ||
4441 | (int)sizeof(struct hdspm_mixer)); | 4435 | (int)sizeof(struct hdspm_mixer)); |
4442 | return err; | 4436 | return err; |
4443 | } | 4437 | } |
@@ -4447,7 +4441,8 @@ static int __devinit snd_hdspm_create(struct snd_card *card, struct hdspm * hdsp | |||
4447 | hdspm->qs_channels = MADI_QS_CHANNELS; | 4441 | hdspm->qs_channels = MADI_QS_CHANNELS; |
4448 | 4442 | ||
4449 | snd_printdd("create alsa devices.\n"); | 4443 | snd_printdd("create alsa devices.\n"); |
4450 | if ((err = snd_hdspm_create_alsa_devices(card, hdspm)) < 0) | 4444 | err = snd_hdspm_create_alsa_devices(card, hdspm); |
4445 | if (err < 0) | ||
4451 | return err; | 4446 | return err; |
4452 | 4447 | ||
4453 | snd_hdspm_initialize_midi_flush(hdspm); | 4448 | snd_hdspm_initialize_midi_flush(hdspm); |
@@ -4462,9 +4457,8 @@ static int snd_hdspm_free(struct hdspm * hdspm) | |||
4462 | 4457 | ||
4463 | /* stop th audio, and cancel all interrupts */ | 4458 | /* stop th audio, and cancel all interrupts */ |
4464 | hdspm->control_register &= | 4459 | hdspm->control_register &= |
4465 | ~(HDSPM_Start | HDSPM_AudioInterruptEnable | 4460 | ~(HDSPM_Start | HDSPM_AudioInterruptEnable | |
4466 | | HDSPM_Midi0InterruptEnable | | 4461 | HDSPM_Midi0InterruptEnable | HDSPM_Midi1InterruptEnable); |
4467 | HDSPM_Midi1InterruptEnable); | ||
4468 | hdspm_write(hdspm, HDSPM_controlRegister, | 4462 | hdspm_write(hdspm, HDSPM_controlRegister, |
4469 | hdspm->control_register); | 4463 | hdspm->control_register); |
4470 | } | 4464 | } |
@@ -4472,7 +4466,6 @@ static int snd_hdspm_free(struct hdspm * hdspm) | |||
4472 | if (hdspm->irq >= 0) | 4466 | if (hdspm->irq >= 0) |
4473 | free_irq(hdspm->irq, (void *) hdspm); | 4467 | free_irq(hdspm->irq, (void *) hdspm); |
4474 | 4468 | ||
4475 | |||
4476 | kfree(hdspm->mixer); | 4469 | kfree(hdspm->mixer); |
4477 | 4470 | ||
4478 | if (hdspm->iobase) | 4471 | if (hdspm->iobase) |
@@ -4487,7 +4480,7 @@ static int snd_hdspm_free(struct hdspm * hdspm) | |||
4487 | 4480 | ||
4488 | static void snd_hdspm_card_free(struct snd_card *card) | 4481 | static void snd_hdspm_card_free(struct snd_card *card) |
4489 | { | 4482 | { |
4490 | struct hdspm *hdspm = (struct hdspm *) card->private_data; | 4483 | struct hdspm *hdspm = card->private_data; |
4491 | 4484 | ||
4492 | if (hdspm) | 4485 | if (hdspm) |
4493 | snd_hdspm_free(hdspm); | 4486 | snd_hdspm_free(hdspm); |
@@ -4508,20 +4501,21 @@ static int __devinit snd_hdspm_probe(struct pci_dev *pci, | |||
4508 | return -ENOENT; | 4501 | return -ENOENT; |
4509 | } | 4502 | } |
4510 | 4503 | ||
4511 | if (!(card = snd_card_new(index[dev], id[dev], | 4504 | card = snd_card_new(index[dev], id[dev], |
4512 | THIS_MODULE, sizeof(struct hdspm)))) | 4505 | THIS_MODULE, sizeof(struct hdspm)); |
4506 | if (!card) | ||
4513 | return -ENOMEM; | 4507 | return -ENOMEM; |
4514 | 4508 | ||
4515 | hdspm = (struct hdspm *) card->private_data; | 4509 | hdspm = card->private_data; |
4516 | card->private_free = snd_hdspm_card_free; | 4510 | card->private_free = snd_hdspm_card_free; |
4517 | hdspm->dev = dev; | 4511 | hdspm->dev = dev; |
4518 | hdspm->pci = pci; | 4512 | hdspm->pci = pci; |
4519 | 4513 | ||
4520 | snd_card_set_dev(card, &pci->dev); | 4514 | snd_card_set_dev(card, &pci->dev); |
4521 | 4515 | ||
4522 | if ((err = | 4516 | err = snd_hdspm_create(card, hdspm, precise_ptr[dev], |
4523 | snd_hdspm_create(card, hdspm, precise_ptr[dev], | 4517 | enable_monitor[dev]); |
4524 | enable_monitor[dev])) < 0) { | 4518 | if (err < 0) { |
4525 | snd_card_free(card); | 4519 | snd_card_free(card); |
4526 | return err; | 4520 | return err; |
4527 | } | 4521 | } |
@@ -4530,7 +4524,8 @@ static int __devinit snd_hdspm_probe(struct pci_dev *pci, | |||
4530 | sprintf(card->longname, "%s at 0x%lx, irq %d", hdspm->card_name, | 4524 | sprintf(card->longname, "%s at 0x%lx, irq %d", hdspm->card_name, |
4531 | hdspm->port, hdspm->irq); | 4525 | hdspm->port, hdspm->irq); |
4532 | 4526 | ||
4533 | if ((err = snd_card_register(card)) < 0) { | 4527 | err = snd_card_register(card); |
4528 | if (err < 0) { | ||
4534 | snd_card_free(card); | 4529 | snd_card_free(card); |
4535 | return err; | 4530 | return err; |
4536 | } | 4531 | } |
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c index 2de27405a0bd..34f96f12e5bf 100644 --- a/sound/pci/rme9652/rme9652.c +++ b/sound/pci/rme9652/rme9652.c | |||
@@ -1067,14 +1067,7 @@ static int rme9652_set_spdif_output(struct snd_rme9652 *rme9652, int out) | |||
1067 | return 0; | 1067 | return 0; |
1068 | } | 1068 | } |
1069 | 1069 | ||
1070 | static int snd_rme9652_info_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1070 | #define snd_rme9652_info_spdif_out snd_ctl_boolean_mono_info |
1071 | { | ||
1072 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1073 | uinfo->count = 1; | ||
1074 | uinfo->value.integer.min = 0; | ||
1075 | uinfo->value.integer.max = 1; | ||
1076 | return 0; | ||
1077 | } | ||
1078 | 1071 | ||
1079 | static int snd_rme9652_get_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1072 | static int snd_rme9652_get_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1080 | { | 1073 | { |
@@ -1338,14 +1331,7 @@ static int snd_rme9652_put_thru(struct snd_kcontrol *kcontrol, struct snd_ctl_el | |||
1338 | .put = snd_rme9652_put_passthru, \ | 1331 | .put = snd_rme9652_put_passthru, \ |
1339 | .get = snd_rme9652_get_passthru } | 1332 | .get = snd_rme9652_get_passthru } |
1340 | 1333 | ||
1341 | static int snd_rme9652_info_passthru(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1334 | #define snd_rme9652_info_passthru snd_ctl_boolean_mono_info |
1342 | { | ||
1343 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1344 | uinfo->count = 1; | ||
1345 | uinfo->value.integer.min = 0; | ||
1346 | uinfo->value.integer.max = 1; | ||
1347 | return 0; | ||
1348 | } | ||
1349 | 1335 | ||
1350 | static int snd_rme9652_get_passthru(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1336 | static int snd_rme9652_get_passthru(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1351 | { | 1337 | { |
@@ -1445,14 +1431,7 @@ static int snd_rme9652_get_adat_sync(struct snd_kcontrol *kcontrol, struct snd_c | |||
1445 | .info = snd_rme9652_info_tc_valid, \ | 1431 | .info = snd_rme9652_info_tc_valid, \ |
1446 | .get = snd_rme9652_get_tc_valid } | 1432 | .get = snd_rme9652_get_tc_valid } |
1447 | 1433 | ||
1448 | static int snd_rme9652_info_tc_valid(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1434 | #define snd_rme9652_info_tc_valid snd_ctl_boolean_mono_info |
1449 | { | ||
1450 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1451 | uinfo->count = 1; | ||
1452 | uinfo->value.integer.min = 0; | ||
1453 | uinfo->value.integer.max = 1; | ||
1454 | return 0; | ||
1455 | } | ||
1456 | 1435 | ||
1457 | static int snd_rme9652_get_tc_valid(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1436 | static int snd_rme9652_get_tc_valid(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1458 | { | 1437 | { |
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index 9f25d93cbec2..44a7f5fad573 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for S3 SonicVibes soundcard | 2 | * Driver for S3 SonicVibes soundcard |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * BUGS: | 5 | * BUGS: |
6 | * It looks like 86c617 rev 3 doesn't supports DDMA buffers above 16MB? | 6 | * It looks like 86c617 rev 3 doesn't supports DDMA buffers above 16MB? |
@@ -42,7 +42,7 @@ | |||
42 | 42 | ||
43 | #include <asm/io.h> | 43 | #include <asm/io.h> |
44 | 44 | ||
45 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 45 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
46 | MODULE_DESCRIPTION("S3 SonicVibes PCI"); | 46 | MODULE_DESCRIPTION("S3 SonicVibes PCI"); |
47 | MODULE_LICENSE("GPL"); | 47 | MODULE_LICENSE("GPL"); |
48 | MODULE_SUPPORTED_DEVICE("{{S3,SonicVibes PCI}}"); | 48 | MODULE_SUPPORTED_DEVICE("{{S3,SonicVibes PCI}}"); |
diff --git a/sound/pci/trident/Makefile b/sound/pci/trident/Makefile index 65bc5b703239..65f2c218324c 100644 --- a/sound/pci/trident/Makefile +++ b/sound/pci/trident/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-trident-objs := trident.o trident_main.o trident_memory.o | 6 | snd-trident-objs := trident.o trident_main.o trident_memory.o |
diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c index 9145f7c57fb0..84884567df6a 100644 --- a/sound/pci/trident/trident.c +++ b/sound/pci/trident/trident.c | |||
@@ -30,7 +30,7 @@ | |||
30 | #include <sound/trident.h> | 30 | #include <sound/trident.h> |
31 | #include <sound/initval.h> | 31 | #include <sound/initval.h> |
32 | 32 | ||
33 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, <audio@tridentmicro.com>"); | 33 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, <audio@tridentmicro.com>"); |
34 | MODULE_DESCRIPTION("Trident 4D-WaveDX/NX & SiS SI7018"); | 34 | MODULE_DESCRIPTION("Trident 4D-WaveDX/NX & SiS SI7018"); |
35 | MODULE_LICENSE("GPL"); | 35 | MODULE_LICENSE("GPL"); |
36 | MODULE_SUPPORTED_DEVICE("{{Trident,4DWave DX}," | 36 | MODULE_SUPPORTED_DEVICE("{{Trident,4DWave DX}," |
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index 7ca606272460..a235e034a690 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Maintained by Jaroslav Kysela <perex@suse.cz> | 2 | * Maintained by Jaroslav Kysela <perex@perex.cz> |
3 | * Originated by audio@tridentmicro.com | 3 | * Originated by audio@tridentmicro.com |
4 | * Fri Feb 19 15:55:28 MST 1999 | 4 | * Fri Feb 19 15:55:28 MST 1999 |
5 | * Routines for control of Trident 4DWave (DX and NX) chip | 5 | * Routines for control of Trident 4DWave (DX and NX) chip |
@@ -2317,15 +2317,7 @@ int __devinit snd_trident_spdif_pcm(struct snd_trident * trident, | |||
2317 | Description: enable/disable S/PDIF out from ac97 mixer | 2317 | Description: enable/disable S/PDIF out from ac97 mixer |
2318 | ---------------------------------------------------------------------------*/ | 2318 | ---------------------------------------------------------------------------*/ |
2319 | 2319 | ||
2320 | static int snd_trident_spdif_control_info(struct snd_kcontrol *kcontrol, | 2320 | #define snd_trident_spdif_control_info snd_ctl_boolean_mono_info |
2321 | struct snd_ctl_elem_info *uinfo) | ||
2322 | { | ||
2323 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
2324 | uinfo->count = 1; | ||
2325 | uinfo->value.integer.min = 0; | ||
2326 | uinfo->value.integer.max = 1; | ||
2327 | return 0; | ||
2328 | } | ||
2329 | 2321 | ||
2330 | static int snd_trident_spdif_control_get(struct snd_kcontrol *kcontrol, | 2322 | static int snd_trident_spdif_control_get(struct snd_kcontrol *kcontrol, |
2331 | struct snd_ctl_elem_value *ucontrol) | 2323 | struct snd_ctl_elem_value *ucontrol) |
@@ -2545,15 +2537,7 @@ static struct snd_kcontrol_new snd_trident_spdif_stream __devinitdata = | |||
2545 | Description: enable/disable rear path for ac97 | 2537 | Description: enable/disable rear path for ac97 |
2546 | ---------------------------------------------------------------------------*/ | 2538 | ---------------------------------------------------------------------------*/ |
2547 | 2539 | ||
2548 | static int snd_trident_ac97_control_info(struct snd_kcontrol *kcontrol, | 2540 | #define snd_trident_ac97_control_info snd_ctl_boolean_mono_info |
2549 | struct snd_ctl_elem_info *uinfo) | ||
2550 | { | ||
2551 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
2552 | uinfo->count = 1; | ||
2553 | uinfo->value.integer.min = 0; | ||
2554 | uinfo->value.integer.max = 1; | ||
2555 | return 0; | ||
2556 | } | ||
2557 | 2541 | ||
2558 | static int snd_trident_ac97_control_get(struct snd_kcontrol *kcontrol, | 2542 | static int snd_trident_ac97_control_get(struct snd_kcontrol *kcontrol, |
2559 | struct snd_ctl_elem_value *ucontrol) | 2543 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/pci/trident/trident_memory.c b/sound/pci/trident/trident_memory.c index aff3f874131c..847b8c6d5c0a 100644 --- a/sound/pci/trident/trident_memory.c +++ b/sound/pci/trident/trident_memory.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Copyright (c) by Takashi Iwai <tiwai@suse.de> | 3 | * Copyright (c) by Takashi Iwai <tiwai@suse.de> |
4 | * Copyright (c) by Scott McNab <sdm@fractalgraphics.com.au> | 4 | * Copyright (c) by Scott McNab <sdm@fractalgraphics.com.au> |
5 | * | 5 | * |
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 6ea09df0c73a..cf62d2ab8d7c 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * VT82C686A/B/C, VT8233A/C, VT8235 | 4 | * VT82C686A/B/C, VT8233A/C, VT8235 |
5 | * | 5 | * |
6 | * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz> | 6 | * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz> |
7 | * Tjeerd.Mulder <Tjeerd.Mulder@fujitsu-siemens.com> | 7 | * Tjeerd.Mulder <Tjeerd.Mulder@fujitsu-siemens.com> |
8 | * 2002 Takashi Iwai <tiwai@suse.de> | 8 | * 2002 Takashi Iwai <tiwai@suse.de> |
9 | * | 9 | * |
@@ -68,7 +68,7 @@ | |||
68 | #define POINTER_DEBUG | 68 | #define POINTER_DEBUG |
69 | #endif | 69 | #endif |
70 | 70 | ||
71 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 71 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
72 | MODULE_DESCRIPTION("VIA VT82xx audio"); | 72 | MODULE_DESCRIPTION("VIA VT82xx audio"); |
73 | MODULE_LICENSE("GPL"); | 73 | MODULE_LICENSE("GPL"); |
74 | MODULE_SUPPORTED_DEVICE("{{VIA,VT82C686A/B/C,pci},{VIA,VT8233A/C,8235}}"); | 74 | MODULE_SUPPORTED_DEVICE("{{VIA,VT82C686A/B/C,pci},{VIA,VT8233A/C,8235}}"); |
@@ -1572,15 +1572,7 @@ static struct snd_kcontrol_new snd_via8233_capture_source __devinitdata = { | |||
1572 | .put = snd_via8233_capture_source_put, | 1572 | .put = snd_via8233_capture_source_put, |
1573 | }; | 1573 | }; |
1574 | 1574 | ||
1575 | static int snd_via8233_dxs3_spdif_info(struct snd_kcontrol *kcontrol, | 1575 | #define snd_via8233_dxs3_spdif_info snd_ctl_boolean_mono_info |
1576 | struct snd_ctl_elem_info *uinfo) | ||
1577 | { | ||
1578 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1579 | uinfo->count = 1; | ||
1580 | uinfo->value.integer.min = 0; | ||
1581 | uinfo->value.integer.max = 1; | ||
1582 | return 0; | ||
1583 | } | ||
1584 | 1576 | ||
1585 | static int snd_via8233_dxs3_spdif_get(struct snd_kcontrol *kcontrol, | 1577 | static int snd_via8233_dxs3_spdif_get(struct snd_kcontrol *kcontrol, |
1586 | struct snd_ctl_elem_value *ucontrol) | 1578 | struct snd_ctl_elem_value *ucontrol) |
@@ -2098,7 +2090,7 @@ static int snd_via82xx_chip_init(struct via82xx *chip) | |||
2098 | pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval); | 2090 | pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval); |
2099 | if (pval & VIA_ACLINK_C00_READY) /* primary codec ready */ | 2091 | if (pval & VIA_ACLINK_C00_READY) /* primary codec ready */ |
2100 | break; | 2092 | break; |
2101 | schedule_timeout(1); | 2093 | schedule_timeout_uninterruptible(1); |
2102 | } while (time_before(jiffies, end_time)); | 2094 | } while (time_before(jiffies, end_time)); |
2103 | 2095 | ||
2104 | if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY) | 2096 | if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY) |
@@ -2117,7 +2109,7 @@ static int snd_via82xx_chip_init(struct via82xx *chip) | |||
2117 | chip->ac97_secondary = 1; | 2109 | chip->ac97_secondary = 1; |
2118 | goto __ac97_ok2; | 2110 | goto __ac97_ok2; |
2119 | } | 2111 | } |
2120 | schedule_timeout(1); | 2112 | schedule_timeout_uninterruptible(1); |
2121 | } while (time_before(jiffies, end_time)); | 2113 | } while (time_before(jiffies, end_time)); |
2122 | /* This is ok, the most of motherboards have only one codec */ | 2114 | /* This is ok, the most of motherboards have only one codec */ |
2123 | 2115 | ||
@@ -2371,6 +2363,7 @@ static struct snd_pci_quirk dxs_whitelist[] __devinitdata = { | |||
2371 | SND_PCI_QUIRK(0x1071, 0, "Diverse Notebook", VIA_DXS_NO_VRA), | 2363 | SND_PCI_QUIRK(0x1071, 0, "Diverse Notebook", VIA_DXS_NO_VRA), |
2372 | SND_PCI_QUIRK(0x10cf, 0x118e, "FSC Laptop", VIA_DXS_ENABLE), | 2364 | SND_PCI_QUIRK(0x10cf, 0x118e, "FSC Laptop", VIA_DXS_ENABLE), |
2373 | SND_PCI_QUIRK(0x1106, 0, "ASRock", VIA_DXS_SRC), | 2365 | SND_PCI_QUIRK(0x1106, 0, "ASRock", VIA_DXS_SRC), |
2366 | SND_PCI_QUIRK(0x1297, 0xa231, "Shuttle AK31v2", VIA_DXS_SRC), | ||
2374 | SND_PCI_QUIRK(0x1297, 0xa232, "Shuttle", VIA_DXS_ENABLE), | 2367 | SND_PCI_QUIRK(0x1297, 0xa232, "Shuttle", VIA_DXS_ENABLE), |
2375 | SND_PCI_QUIRK(0x1297, 0xc160, "Shuttle Sk41G", VIA_DXS_ENABLE), | 2368 | SND_PCI_QUIRK(0x1297, 0xc160, "Shuttle Sk41G", VIA_DXS_ENABLE), |
2376 | SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte GA-7VAXP", VIA_DXS_ENABLE), | 2369 | SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte GA-7VAXP", VIA_DXS_ENABLE), |
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index 72425e73abae..57fb9ae22f93 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * VT82C686A/B/C, VT8233A/C, VT8235 | 4 | * VT82C686A/B/C, VT8233A/C, VT8235 |
5 | * | 5 | * |
6 | * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz> | 6 | * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz> |
7 | * Tjeerd.Mulder <Tjeerd.Mulder@fujitsu-siemens.com> | 7 | * Tjeerd.Mulder <Tjeerd.Mulder@fujitsu-siemens.com> |
8 | * 2002 Takashi Iwai <tiwai@suse.de> | 8 | * 2002 Takashi Iwai <tiwai@suse.de> |
9 | * | 9 | * |
@@ -50,7 +50,7 @@ | |||
50 | #define POINTER_DEBUG | 50 | #define POINTER_DEBUG |
51 | #endif | 51 | #endif |
52 | 52 | ||
53 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 53 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
54 | MODULE_DESCRIPTION("VIA VT82xx modem"); | 54 | MODULE_DESCRIPTION("VIA VT82xx modem"); |
55 | MODULE_LICENSE("GPL"); | 55 | MODULE_LICENSE("GPL"); |
56 | MODULE_SUPPORTED_DEVICE("{{VIA,VT82C686A/B/C modem,pci}}"); | 56 | MODULE_SUPPORTED_DEVICE("{{VIA,VT82C686A/B/C modem,pci}}"); |
@@ -983,7 +983,7 @@ static int snd_via82xx_chip_init(struct via82xx_modem *chip) | |||
983 | pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval); | 983 | pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval); |
984 | if (pval & VIA_ACLINK_C00_READY) /* primary codec ready */ | 984 | if (pval & VIA_ACLINK_C00_READY) /* primary codec ready */ |
985 | break; | 985 | break; |
986 | schedule_timeout(1); | 986 | schedule_timeout_uninterruptible(1); |
987 | } while (time_before(jiffies, end_time)); | 987 | } while (time_before(jiffies, end_time)); |
988 | 988 | ||
989 | if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY) | 989 | if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY) |
@@ -1001,7 +1001,7 @@ static int snd_via82xx_chip_init(struct via82xx_modem *chip) | |||
1001 | chip->ac97_secondary = 1; | 1001 | chip->ac97_secondary = 1; |
1002 | goto __ac97_ok2; | 1002 | goto __ac97_ok2; |
1003 | } | 1003 | } |
1004 | schedule_timeout(1); | 1004 | schedule_timeout_uninterruptible(1); |
1005 | } while (time_before(jiffies, end_time)); | 1005 | } while (time_before(jiffies, end_time)); |
1006 | /* This is ok, the most of motherboards have only one codec */ | 1006 | /* This is ok, the most of motherboards have only one codec */ |
1007 | 1007 | ||
diff --git a/sound/pci/vx222/Makefile b/sound/pci/vx222/Makefile index 058c8bff7c11..a4d08d4de354 100644 --- a/sound/pci/vx222/Makefile +++ b/sound/pci/vx222/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-vx222-objs := vx222.o vx222_ops.o | 6 | snd-vx222-objs := vx222.o vx222_ops.o |
diff --git a/sound/pci/ymfpci/Makefile b/sound/pci/ymfpci/Makefile index 8790c5f3ed02..bd3d514ed76b 100644 --- a/sound/pci/ymfpci/Makefile +++ b/sound/pci/ymfpci/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-ymfpci-objs := ymfpci.o ymfpci_main.o | 6 | snd-ymfpci-objs := ymfpci.o ymfpci_main.o |
diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c index fd9b7b83a884..5c4256a4d4b9 100644 --- a/sound/pci/ymfpci/ymfpci.c +++ b/sound/pci/ymfpci/ymfpci.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * The driver for the Yamaha's DS1/DS1E cards | 2 | * The driver for the Yamaha's DS1/DS1E cards |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -30,7 +30,7 @@ | |||
30 | #include <sound/opl3.h> | 30 | #include <sound/opl3.h> |
31 | #include <sound/initval.h> | 31 | #include <sound/initval.h> |
32 | 32 | ||
33 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 33 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
34 | MODULE_DESCRIPTION("Yamaha DS-1 PCI"); | 34 | MODULE_DESCRIPTION("Yamaha DS-1 PCI"); |
35 | MODULE_LICENSE("GPL"); | 35 | MODULE_LICENSE("GPL"); |
36 | MODULE_SUPPORTED_DEVICE("{{Yamaha,YMF724}," | 36 | MODULE_SUPPORTED_DEVICE("{{Yamaha,YMF724}," |
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index ab7a81c35705..1fe39ed28765 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Routines for control of YMF724/740/744/754 chips | 3 | * Routines for control of YMF724/740/744/754 chips |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
@@ -84,7 +84,6 @@ static int snd_ymfpci_codec_ready(struct snd_ymfpci *chip, int secondary) | |||
84 | do { | 84 | do { |
85 | if ((snd_ymfpci_readw(chip, reg) & 0x8000) == 0) | 85 | if ((snd_ymfpci_readw(chip, reg) & 0x8000) == 0) |
86 | return 0; | 86 | return 0; |
87 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
88 | schedule_timeout_uninterruptible(1); | 87 | schedule_timeout_uninterruptible(1); |
89 | } while (time_before(jiffies, end_time)); | 88 | } while (time_before(jiffies, end_time)); |
90 | snd_printk(KERN_ERR "codec_ready: codec %i is not ready [0x%x]\n", secondary, snd_ymfpci_readw(chip, reg)); | 89 | snd_printk(KERN_ERR "codec_ready: codec %i is not ready [0x%x]\n", secondary, snd_ymfpci_readw(chip, reg)); |
@@ -171,17 +170,6 @@ static u32 snd_ymfpci_calc_lpfQ(u32 rate) | |||
171 | return val[0]; | 170 | return val[0]; |
172 | } | 171 | } |
173 | 172 | ||
174 | static void snd_ymfpci_pcm_441_volume_set(struct snd_ymfpci_pcm *ypcm) | ||
175 | { | ||
176 | unsigned int value; | ||
177 | struct snd_ymfpci_pcm_mixer *mixer; | ||
178 | |||
179 | mixer = &ypcm->chip->pcm_mixer[ypcm->substream->number]; | ||
180 | value = min_t(unsigned int, mixer->left, 0x7fff) >> 1; | ||
181 | value |= (min_t(unsigned int, mixer->right, 0x7fff) >> 1) << 16; | ||
182 | snd_ymfpci_writel(ypcm->chip, YDSXGR_BUF441OUTVOL, value); | ||
183 | } | ||
184 | |||
185 | /* | 173 | /* |
186 | * Hardware start management | 174 | * Hardware start management |
187 | */ | 175 | */ |
@@ -389,6 +377,7 @@ static int snd_ymfpci_playback_trigger(struct snd_pcm_substream *substream, | |||
389 | { | 377 | { |
390 | struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); | 378 | struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); |
391 | struct snd_ymfpci_pcm *ypcm = substream->runtime->private_data; | 379 | struct snd_ymfpci_pcm *ypcm = substream->runtime->private_data; |
380 | struct snd_kcontrol *kctl = NULL; | ||
392 | int result = 0; | 381 | int result = 0; |
393 | 382 | ||
394 | spin_lock(&chip->reg_lock); | 383 | spin_lock(&chip->reg_lock); |
@@ -406,6 +395,11 @@ static int snd_ymfpci_playback_trigger(struct snd_pcm_substream *substream, | |||
406 | ypcm->running = 1; | 395 | ypcm->running = 1; |
407 | break; | 396 | break; |
408 | case SNDRV_PCM_TRIGGER_STOP: | 397 | case SNDRV_PCM_TRIGGER_STOP: |
398 | if (substream->pcm == chip->pcm && !ypcm->use_441_slot) { | ||
399 | kctl = chip->pcm_mixer[substream->number].ctl; | ||
400 | kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; | ||
401 | } | ||
402 | /* fall through */ | ||
409 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 403 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
410 | case SNDRV_PCM_TRIGGER_SUSPEND: | 404 | case SNDRV_PCM_TRIGGER_SUSPEND: |
411 | chip->ctrl_playback[ypcm->voices[0]->number + 1] = 0; | 405 | chip->ctrl_playback[ypcm->voices[0]->number + 1] = 0; |
@@ -419,6 +413,8 @@ static int snd_ymfpci_playback_trigger(struct snd_pcm_substream *substream, | |||
419 | } | 413 | } |
420 | __unlock: | 414 | __unlock: |
421 | spin_unlock(&chip->reg_lock); | 415 | spin_unlock(&chip->reg_lock); |
416 | if (kctl) | ||
417 | snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO, &kctl->id); | ||
422 | return result; | 418 | return result; |
423 | } | 419 | } |
424 | static int snd_ymfpci_capture_trigger(struct snd_pcm_substream *substream, | 420 | static int snd_ymfpci_capture_trigger(struct snd_pcm_substream *substream, |
@@ -526,7 +522,6 @@ static void snd_ymfpci_pcm_init_voice(struct snd_ymfpci_pcm *ypcm, unsigned int | |||
526 | ypcm->chip->src441_used = voice->number; | 522 | ypcm->chip->src441_used = voice->number; |
527 | ypcm->use_441_slot = 1; | 523 | ypcm->use_441_slot = 1; |
528 | format |= 0x10000000; | 524 | format |= 0x10000000; |
529 | snd_ymfpci_pcm_441_volume_set(ypcm); | ||
530 | } | 525 | } |
531 | if (ypcm->chip->src441_used == voice->number && | 526 | if (ypcm->chip->src441_used == voice->number && |
532 | (format & 0x10000000) == 0) { | 527 | (format & 0x10000000) == 0) { |
@@ -667,6 +662,7 @@ static int snd_ymfpci_playback_prepare(struct snd_pcm_substream *substream) | |||
667 | struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); | 662 | struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); |
668 | struct snd_pcm_runtime *runtime = substream->runtime; | 663 | struct snd_pcm_runtime *runtime = substream->runtime; |
669 | struct snd_ymfpci_pcm *ypcm = runtime->private_data; | 664 | struct snd_ymfpci_pcm *ypcm = runtime->private_data; |
665 | struct snd_kcontrol *kctl; | ||
670 | unsigned int nvoice; | 666 | unsigned int nvoice; |
671 | 667 | ||
672 | ypcm->period_size = runtime->period_size; | 668 | ypcm->period_size = runtime->period_size; |
@@ -676,6 +672,12 @@ static int snd_ymfpci_playback_prepare(struct snd_pcm_substream *substream) | |||
676 | for (nvoice = 0; nvoice < runtime->channels; nvoice++) | 672 | for (nvoice = 0; nvoice < runtime->channels; nvoice++) |
677 | snd_ymfpci_pcm_init_voice(ypcm, nvoice, runtime, | 673 | snd_ymfpci_pcm_init_voice(ypcm, nvoice, runtime, |
678 | substream->pcm == chip->pcm); | 674 | substream->pcm == chip->pcm); |
675 | |||
676 | if (substream->pcm == chip->pcm && !ypcm->use_441_slot) { | ||
677 | kctl = chip->pcm_mixer[substream->number].ctl; | ||
678 | kctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; | ||
679 | snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO, &kctl->id); | ||
680 | } | ||
679 | return 0; | 681 | return 0; |
680 | } | 682 | } |
681 | 683 | ||
@@ -926,7 +928,6 @@ static int snd_ymfpci_playback_open(struct snd_pcm_substream *substream) | |||
926 | struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); | 928 | struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); |
927 | struct snd_pcm_runtime *runtime = substream->runtime; | 929 | struct snd_pcm_runtime *runtime = substream->runtime; |
928 | struct snd_ymfpci_pcm *ypcm; | 930 | struct snd_ymfpci_pcm *ypcm; |
929 | struct snd_kcontrol *kctl; | ||
930 | int err; | 931 | int err; |
931 | 932 | ||
932 | if ((err = snd_ymfpci_playback_open_1(substream)) < 0) | 933 | if ((err = snd_ymfpci_playback_open_1(substream)) < 0) |
@@ -941,10 +942,6 @@ static int snd_ymfpci_playback_open(struct snd_pcm_substream *substream) | |||
941 | chip->rear_opened++; | 942 | chip->rear_opened++; |
942 | } | 943 | } |
943 | spin_unlock_irq(&chip->reg_lock); | 944 | spin_unlock_irq(&chip->reg_lock); |
944 | |||
945 | kctl = chip->pcm_mixer[substream->number].ctl; | ||
946 | kctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; | ||
947 | snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO, &kctl->id); | ||
948 | return 0; | 945 | return 0; |
949 | } | 946 | } |
950 | 947 | ||
@@ -1039,7 +1036,6 @@ static int snd_ymfpci_playback_close(struct snd_pcm_substream *substream) | |||
1039 | { | 1036 | { |
1040 | struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); | 1037 | struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); |
1041 | struct snd_ymfpci_pcm *ypcm = substream->runtime->private_data; | 1038 | struct snd_ymfpci_pcm *ypcm = substream->runtime->private_data; |
1042 | struct snd_kcontrol *kctl; | ||
1043 | 1039 | ||
1044 | spin_lock_irq(&chip->reg_lock); | 1040 | spin_lock_irq(&chip->reg_lock); |
1045 | if (ypcm->output_rear && chip->rear_opened > 0) { | 1041 | if (ypcm->output_rear && chip->rear_opened > 0) { |
@@ -1047,9 +1043,6 @@ static int snd_ymfpci_playback_close(struct snd_pcm_substream *substream) | |||
1047 | ymfpci_close_extension(chip); | 1043 | ymfpci_close_extension(chip); |
1048 | } | 1044 | } |
1049 | spin_unlock_irq(&chip->reg_lock); | 1045 | spin_unlock_irq(&chip->reg_lock); |
1050 | kctl = chip->pcm_mixer[substream->number].ctl; | ||
1051 | kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; | ||
1052 | snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO, &kctl->id); | ||
1053 | return snd_ymfpci_playback_close_1(substream); | 1046 | return snd_ymfpci_playback_close_1(substream); |
1054 | } | 1047 | } |
1055 | 1048 | ||
@@ -1443,22 +1436,7 @@ static struct snd_kcontrol_new snd_ymfpci_drec_source __devinitdata = { | |||
1443 | .get = snd_ymfpci_get_single, .put = snd_ymfpci_put_single, \ | 1436 | .get = snd_ymfpci_get_single, .put = snd_ymfpci_put_single, \ |
1444 | .private_value = ((reg) | ((shift) << 16)) } | 1437 | .private_value = ((reg) | ((shift) << 16)) } |
1445 | 1438 | ||
1446 | static int snd_ymfpci_info_single(struct snd_kcontrol *kcontrol, | 1439 | #define snd_ymfpci_info_single snd_ctl_boolean_mono_info |
1447 | struct snd_ctl_elem_info *uinfo) | ||
1448 | { | ||
1449 | int reg = kcontrol->private_value & 0xffff; | ||
1450 | |||
1451 | switch (reg) { | ||
1452 | case YDSXGR_SPDIFOUTCTRL: break; | ||
1453 | case YDSXGR_SPDIFINCTRL: break; | ||
1454 | default: return -EINVAL; | ||
1455 | } | ||
1456 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1457 | uinfo->count = 1; | ||
1458 | uinfo->value.integer.min = 0; | ||
1459 | uinfo->value.integer.max = 1; | ||
1460 | return 0; | ||
1461 | } | ||
1462 | 1440 | ||
1463 | static int snd_ymfpci_get_single(struct snd_kcontrol *kcontrol, | 1441 | static int snd_ymfpci_get_single(struct snd_kcontrol *kcontrol, |
1464 | struct snd_ctl_elem_value *ucontrol) | 1442 | struct snd_ctl_elem_value *ucontrol) |
@@ -1567,17 +1545,30 @@ static int snd_ymfpci_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
1567 | return change; | 1545 | return change; |
1568 | } | 1546 | } |
1569 | 1547 | ||
1548 | static int snd_ymfpci_put_nativedacvol(struct snd_kcontrol *kcontrol, | ||
1549 | struct snd_ctl_elem_value *ucontrol) | ||
1550 | { | ||
1551 | struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol); | ||
1552 | unsigned int reg = YDSXGR_NATIVEDACOUTVOL; | ||
1553 | unsigned int reg2 = YDSXGR_BUF441OUTVOL; | ||
1554 | int change; | ||
1555 | unsigned int value, oval; | ||
1556 | |||
1557 | value = ucontrol->value.integer.value[0] & 0x3fff; | ||
1558 | value |= (ucontrol->value.integer.value[1] & 0x3fff) << 16; | ||
1559 | spin_lock_irq(&chip->reg_lock); | ||
1560 | oval = snd_ymfpci_readl(chip, reg); | ||
1561 | change = value != oval; | ||
1562 | snd_ymfpci_writel(chip, reg, value); | ||
1563 | snd_ymfpci_writel(chip, reg2, value); | ||
1564 | spin_unlock_irq(&chip->reg_lock); | ||
1565 | return change; | ||
1566 | } | ||
1567 | |||
1570 | /* | 1568 | /* |
1571 | * 4ch duplication | 1569 | * 4ch duplication |
1572 | */ | 1570 | */ |
1573 | static int snd_ymfpci_info_dup4ch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1571 | #define snd_ymfpci_info_dup4ch snd_ctl_boolean_mono_info |
1574 | { | ||
1575 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1576 | uinfo->count = 1; | ||
1577 | uinfo->value.integer.min = 0; | ||
1578 | uinfo->value.integer.max = 1; | ||
1579 | return 0; | ||
1580 | } | ||
1581 | 1572 | ||
1582 | static int snd_ymfpci_get_dup4ch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1573 | static int snd_ymfpci_get_dup4ch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1583 | { | 1574 | { |
@@ -1598,7 +1589,17 @@ static int snd_ymfpci_put_dup4ch(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
1598 | 1589 | ||
1599 | 1590 | ||
1600 | static struct snd_kcontrol_new snd_ymfpci_controls[] __devinitdata = { | 1591 | static struct snd_kcontrol_new snd_ymfpci_controls[] __devinitdata = { |
1601 | YMFPCI_DOUBLE("Wave Playback Volume", 0, YDSXGR_NATIVEDACOUTVOL), | 1592 | { |
1593 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1594 | .name = "Wave Playback Volume", | ||
1595 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
1596 | SNDRV_CTL_ELEM_ACCESS_TLV_READ, | ||
1597 | .info = snd_ymfpci_info_double, | ||
1598 | .get = snd_ymfpci_get_double, | ||
1599 | .put = snd_ymfpci_put_nativedacvol, | ||
1600 | .private_value = YDSXGR_NATIVEDACOUTVOL, | ||
1601 | .tlv = { .p = db_scale_native }, | ||
1602 | }, | ||
1602 | YMFPCI_DOUBLE("Wave Capture Volume", 0, YDSXGR_NATIVEDACLOOPVOL), | 1603 | YMFPCI_DOUBLE("Wave Capture Volume", 0, YDSXGR_NATIVEDACLOOPVOL), |
1603 | YMFPCI_DOUBLE("Digital Capture Volume", 0, YDSXGR_NATIVEDACINVOL), | 1604 | YMFPCI_DOUBLE("Digital Capture Volume", 0, YDSXGR_NATIVEDACINVOL), |
1604 | YMFPCI_DOUBLE("Digital Capture Volume", 1, YDSXGR_NATIVEADCINVOL), | 1605 | YMFPCI_DOUBLE("Digital Capture Volume", 1, YDSXGR_NATIVEADCINVOL), |
@@ -1665,14 +1666,7 @@ static int snd_ymfpci_set_gpio_out(struct snd_ymfpci *chip, int pin, int enable) | |||
1665 | return 0; | 1666 | return 0; |
1666 | } | 1667 | } |
1667 | 1668 | ||
1668 | static int snd_ymfpci_gpio_sw_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1669 | #define snd_ymfpci_gpio_sw_info snd_ctl_boolean_mono_info |
1669 | { | ||
1670 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1671 | uinfo->count = 1; | ||
1672 | uinfo->value.integer.min = 0; | ||
1673 | uinfo->value.integer.max = 1; | ||
1674 | return 0; | ||
1675 | } | ||
1676 | 1670 | ||
1677 | static int snd_ymfpci_gpio_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1671 | static int snd_ymfpci_gpio_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1678 | { | 1672 | { |
@@ -1748,8 +1742,6 @@ static int snd_ymfpci_pcm_vol_put(struct snd_kcontrol *kcontrol, | |||
1748 | struct snd_ymfpci_pcm *ypcm = substream->runtime->private_data; | 1742 | struct snd_ymfpci_pcm *ypcm = substream->runtime->private_data; |
1749 | if (!ypcm->use_441_slot) | 1743 | if (!ypcm->use_441_slot) |
1750 | ypcm->update_pcm_vol = 2; | 1744 | ypcm->update_pcm_vol = 2; |
1751 | else | ||
1752 | snd_ymfpci_pcm_441_volume_set(ypcm); | ||
1753 | } | 1745 | } |
1754 | spin_unlock_irqrestore(&chip->voice_lock, flags); | 1746 | spin_unlock_irqrestore(&chip->voice_lock, flags); |
1755 | return 1; | 1747 | return 1; |
diff --git a/sound/pcmcia/Makefile b/sound/pcmcia/Makefile index b6656d48becd..beef2e33b718 100644 --- a/sound/pcmcia/Makefile +++ b/sound/pcmcia/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | obj-$(CONFIG_SND) += vx/ pdaudiocf/ | 6 | obj-$(CONFIG_SND) += vx/ pdaudiocf/ |
diff --git a/sound/pcmcia/pdaudiocf/Makefile b/sound/pcmcia/pdaudiocf/Makefile index 6e194f9b50e3..e892d7299abf 100644 --- a/sound/pcmcia/pdaudiocf/Makefile +++ b/sound/pcmcia/pdaudiocf/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2004 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2004 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-pdaudiocf-objs := pdaudiocf.o pdaudiocf_core.o pdaudiocf_irq.o pdaudiocf_pcm.o | 6 | snd-pdaudiocf-objs := pdaudiocf.o pdaudiocf_core.o pdaudiocf_irq.o pdaudiocf_pcm.o |
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c index 2d40cc72f236..de683b08fe03 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for Sound Core PDAudioCF soundcard | 2 | * Driver for Sound Core PDAudioCF soundcard |
3 | * | 3 | * |
4 | * Copyright (c) 2003 by Jaroslav Kysela <perex@suse.cz> | 4 | * Copyright (c) 2003 by Jaroslav Kysela <perex@perex.cz> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
@@ -33,7 +33,7 @@ | |||
33 | 33 | ||
34 | #define CARD_NAME "PDAudio-CF" | 34 | #define CARD_NAME "PDAudio-CF" |
35 | 35 | ||
36 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 36 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
37 | MODULE_DESCRIPTION("Sound Core " CARD_NAME); | 37 | MODULE_DESCRIPTION("Sound Core " CARD_NAME); |
38 | MODULE_LICENSE("GPL"); | 38 | MODULE_LICENSE("GPL"); |
39 | MODULE_SUPPORTED_DEVICE("{{Sound Core," CARD_NAME "}}"); | 39 | MODULE_SUPPORTED_DEVICE("{{Sound Core," CARD_NAME "}}"); |
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.h b/sound/pcmcia/pdaudiocf/pdaudiocf.h index 206e2f5a113f..b0601838112d 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf.h +++ b/sound/pcmcia/pdaudiocf/pdaudiocf.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for Sound Cors PDAudioCF soundcard | 2 | * Driver for Sound Cors PDAudioCF soundcard |
3 | * | 3 | * |
4 | * Copyright (c) 2003 by Jaroslav Kysela <perex@suse.cz> | 4 | * Copyright (c) 2003 by Jaroslav Kysela <perex@perex.cz> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c index 1dfe29b863d3..484c8f9a6f1c 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for Sound Core PDAudioCF soundcard | 2 | * Driver for Sound Core PDAudioCF soundcard |
3 | * | 3 | * |
4 | * Copyright (c) 2003 by Jaroslav Kysela <perex@suse.cz> | 4 | * Copyright (c) 2003 by Jaroslav Kysela <perex@perex.cz> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c b/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c index 5bd69206ba65..54543369949e 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for Sound Core PDAudioCF soundcard | 2 | * Driver for Sound Core PDAudioCF soundcard |
3 | * | 3 | * |
4 | * Copyright (c) 2003 by Jaroslav Kysela <perex@suse.cz> | 4 | * Copyright (c) 2003 by Jaroslav Kysela <perex@perex.cz> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c index 7f2a4de1d35d..10afcb262d5c 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * PCM part | 4 | * PCM part |
5 | * | 5 | * |
6 | * Copyright (c) 2003 by Jaroslav Kysela <perex@suse.cz> | 6 | * Copyright (c) 2003 by Jaroslav Kysela <perex@perex.cz> |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
diff --git a/sound/pcmcia/vx/Makefile b/sound/pcmcia/vx/Makefile index 54971f01e968..2bb42ea12f3a 100644 --- a/sound/pcmcia/vx/Makefile +++ b/sound/pcmcia/vx/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-vxpocket-objs := vxpocket.o vxp_ops.o vxp_mixer.o | 6 | snd-vxpocket-objs := vxpocket.o vxp_ops.o vxp_mixer.o |
diff --git a/sound/pcmcia/vx/vxp_mixer.c b/sound/pcmcia/vx/vxp_mixer.c index 2b1f996c898d..1eff158b8687 100644 --- a/sound/pcmcia/vx/vxp_mixer.c +++ b/sound/pcmcia/vx/vxp_mixer.c | |||
@@ -80,14 +80,7 @@ static struct snd_kcontrol_new vx_control_mic_level = { | |||
80 | /* | 80 | /* |
81 | * mic boost level control (for VXP440) | 81 | * mic boost level control (for VXP440) |
82 | */ | 82 | */ |
83 | static int vx_mic_boost_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 83 | #define vx_mic_boost_info snd_ctl_boolean_mono_info |
84 | { | ||
85 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
86 | uinfo->count = 1; | ||
87 | uinfo->value.integer.min = 0; | ||
88 | uinfo->value.integer.max = 1; | ||
89 | return 0; | ||
90 | } | ||
91 | 84 | ||
92 | static int vx_mic_boost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 85 | static int vx_mic_boost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
93 | { | 86 | { |
diff --git a/sound/ppc/Makefile b/sound/ppc/Makefile index eacee2d0675c..679c45a8da2c 100644 --- a/sound/ppc/Makefile +++ b/sound/ppc/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-powermac-objs := powermac.o pmac.o awacs.o burgundy.o daca.o tumbler.o keywest.o beep.o | 6 | snd-powermac-objs := powermac.o pmac.o awacs.o burgundy.o daca.o tumbler.o keywest.o beep.o |
diff --git a/sound/ppc/daca.c b/sound/ppc/daca.c index 57202b0f033e..c5a1f0be6a4d 100644 --- a/sound/ppc/daca.c +++ b/sound/ppc/daca.c | |||
@@ -91,15 +91,7 @@ static int daca_set_volume(struct pmac_daca *mix) | |||
91 | 91 | ||
92 | 92 | ||
93 | /* deemphasis switch */ | 93 | /* deemphasis switch */ |
94 | static int daca_info_deemphasis(struct snd_kcontrol *kcontrol, | 94 | #define daca_info_deemphasis snd_ctl_boolean_mono_info |
95 | struct snd_ctl_elem_info *uinfo) | ||
96 | { | ||
97 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
98 | uinfo->count = 1; | ||
99 | uinfo->value.integer.min = 0; | ||
100 | uinfo->value.integer.max = 1; | ||
101 | return 0; | ||
102 | } | ||
103 | 95 | ||
104 | static int daca_get_deemphasis(struct snd_kcontrol *kcontrol, | 96 | static int daca_get_deemphasis(struct snd_kcontrol *kcontrol, |
105 | struct snd_ctl_elem_value *ucontrol) | 97 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c index 7a22f0f3784a..4f9b19c90a43 100644 --- a/sound/ppc/pmac.c +++ b/sound/ppc/pmac.c | |||
@@ -490,35 +490,14 @@ static int snd_pmac_pcm_open(struct snd_pmac *chip, struct pmac_stream *rec, | |||
490 | struct snd_pcm_substream *subs) | 490 | struct snd_pcm_substream *subs) |
491 | { | 491 | { |
492 | struct snd_pcm_runtime *runtime = subs->runtime; | 492 | struct snd_pcm_runtime *runtime = subs->runtime; |
493 | int i, j, fflags; | 493 | int i; |
494 | static int typical_freqs[] = { | ||
495 | 44100, | ||
496 | 22050, | ||
497 | 11025, | ||
498 | 0, | ||
499 | }; | ||
500 | static int typical_freq_flags[] = { | ||
501 | SNDRV_PCM_RATE_44100, | ||
502 | SNDRV_PCM_RATE_22050, | ||
503 | SNDRV_PCM_RATE_11025, | ||
504 | 0, | ||
505 | }; | ||
506 | 494 | ||
507 | /* look up frequency table and fill bit mask */ | 495 | /* look up frequency table and fill bit mask */ |
508 | runtime->hw.rates = 0; | 496 | runtime->hw.rates = 0; |
509 | fflags = chip->freqs_ok; | 497 | for (i = 0; i < chip->num_freqs; i++) |
510 | for (i = 0; typical_freqs[i]; i++) { | 498 | if (chip->freqs_ok & (1 << i)) |
511 | for (j = 0; j < chip->num_freqs; j++) { | 499 | runtime->hw.rates |= |
512 | if ((chip->freqs_ok & (1 << j)) && | 500 | snd_pcm_rate_to_rate_bit(chip->freq_table[i]); |
513 | chip->freq_table[j] == typical_freqs[i]) { | ||
514 | runtime->hw.rates |= typical_freq_flags[i]; | ||
515 | fflags &= ~(1 << j); | ||
516 | break; | ||
517 | } | ||
518 | } | ||
519 | } | ||
520 | if (fflags) /* rest */ | ||
521 | runtime->hw.rates |= SNDRV_PCM_RATE_KNOT; | ||
522 | 501 | ||
523 | /* check for minimum and maximum rates */ | 502 | /* check for minimum and maximum rates */ |
524 | for (i = 0; i < chip->num_freqs; i++) { | 503 | for (i = 0; i < chip->num_freqs; i++) { |
@@ -551,9 +530,6 @@ static int snd_pmac_pcm_open(struct snd_pmac *chip, struct pmac_stream *rec, | |||
551 | 530 | ||
552 | runtime->hw.periods_max = rec->cmd.size - 1; | 531 | runtime->hw.periods_max = rec->cmd.size - 1; |
553 | 532 | ||
554 | if (chip->can_duplex) | ||
555 | snd_pcm_set_sync(subs); | ||
556 | |||
557 | /* constraints to fix choppy sound */ | 533 | /* constraints to fix choppy sound */ |
558 | snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); | 534 | snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); |
559 | return 0; | 535 | return 0; |
@@ -1035,29 +1011,6 @@ static int __init snd_pmac_detect(struct snd_pmac *chip) | |||
1035 | return 0; | 1011 | return 0; |
1036 | } | 1012 | } |
1037 | 1013 | ||
1038 | /* | ||
1039 | * exported - boolean info callbacks for ease of programming | ||
1040 | */ | ||
1041 | int snd_pmac_boolean_stereo_info(struct snd_kcontrol *kcontrol, | ||
1042 | struct snd_ctl_elem_info *uinfo) | ||
1043 | { | ||
1044 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1045 | uinfo->count = 2; | ||
1046 | uinfo->value.integer.min = 0; | ||
1047 | uinfo->value.integer.max = 1; | ||
1048 | return 0; | ||
1049 | } | ||
1050 | |||
1051 | int snd_pmac_boolean_mono_info(struct snd_kcontrol *kcontrol, | ||
1052 | struct snd_ctl_elem_info *uinfo) | ||
1053 | { | ||
1054 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1055 | uinfo->count = 1; | ||
1056 | uinfo->value.integer.min = 0; | ||
1057 | uinfo->value.integer.max = 1; | ||
1058 | return 0; | ||
1059 | } | ||
1060 | |||
1061 | #ifdef PMAC_SUPPORT_AUTOMUTE | 1014 | #ifdef PMAC_SUPPORT_AUTOMUTE |
1062 | /* | 1015 | /* |
1063 | * auto-mute | 1016 | * auto-mute |
diff --git a/sound/ppc/pmac.h b/sound/ppc/pmac.h index 8394e66ceb00..25c512c2d74d 100644 --- a/sound/ppc/pmac.h +++ b/sound/ppc/pmac.h | |||
@@ -202,8 +202,8 @@ int snd_pmac_keywest_init(struct pmac_keywest *i2c); | |||
202 | void snd_pmac_keywest_cleanup(struct pmac_keywest *i2c); | 202 | void snd_pmac_keywest_cleanup(struct pmac_keywest *i2c); |
203 | 203 | ||
204 | /* misc */ | 204 | /* misc */ |
205 | int snd_pmac_boolean_stereo_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); | 205 | #define snd_pmac_boolean_stereo_info snd_ctl_boolean_stereo_info |
206 | int snd_pmac_boolean_mono_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); | 206 | #define snd_pmac_boolean_mono_info snd_ctl_boolean_mono_info |
207 | 207 | ||
208 | int snd_pmac_add_automute(struct snd_pmac *chip); | 208 | int snd_pmac_add_automute(struct snd_pmac *chip); |
209 | 209 | ||
diff --git a/sound/ppc/snd_ps3.c b/sound/ppc/snd_ps3.c index 1aa0b467599f..27b61899fe84 100644 --- a/sound/ppc/snd_ps3.c +++ b/sound/ppc/snd_ps3.c | |||
@@ -33,7 +33,6 @@ | |||
33 | #include <linux/dmapool.h> | 33 | #include <linux/dmapool.h> |
34 | #include <linux/dma-mapping.h> | 34 | #include <linux/dma-mapping.h> |
35 | #include <asm/firmware.h> | 35 | #include <asm/firmware.h> |
36 | #include <linux/io.h> | ||
37 | #include <asm/dma.h> | 36 | #include <asm/dma.h> |
38 | #include <asm/lv1call.h> | 37 | #include <asm/lv1call.h> |
39 | #include <asm/ps3.h> | 38 | #include <asm/ps3.h> |
diff --git a/sound/sh/aica.c b/sound/sh/aica.c index 739786529ca5..131ec4812288 100644 --- a/sound/sh/aica.c +++ b/sound/sh/aica.c | |||
@@ -451,15 +451,7 @@ static int __init snd_aicapcmchip(struct snd_card_aica | |||
451 | } | 451 | } |
452 | 452 | ||
453 | /* Mixer controls */ | 453 | /* Mixer controls */ |
454 | static int aica_pcmswitch_info(struct snd_kcontrol *kcontrol, | 454 | #define aica_pcmswitch_info snd_ctl_boolean_mono_info |
455 | struct snd_ctl_elem_info *uinfo) | ||
456 | { | ||
457 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
458 | uinfo->count = 1; | ||
459 | uinfo->value.integer.min = 0; | ||
460 | uinfo->value.integer.max = 1; | ||
461 | return 0; | ||
462 | } | ||
463 | 455 | ||
464 | static int aica_pcmswitch_get(struct snd_kcontrol *kcontrol, | 456 | static int aica_pcmswitch_get(struct snd_kcontrol *kcontrol, |
465 | struct snd_ctl_elem_value *ucontrol) | 457 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index e5fb437b86e8..78248808a9d8 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -17,3 +17,23 @@ config SND_SOC_WM8753 | |||
17 | config SND_SOC_WM9712 | 17 | config SND_SOC_WM9712 |
18 | tristate | 18 | tristate |
19 | depends on SND_SOC | 19 | depends on SND_SOC |
20 | |||
21 | # Cirrus Logic CS4270 Codec | ||
22 | config SND_SOC_CS4270 | ||
23 | tristate | ||
24 | depends on SND_SOC | ||
25 | |||
26 | # Cirrus Logic CS4270 Codec Hardware Mute Support | ||
27 | # Select if you have external muting circuitry attached to your CS4270. | ||
28 | config SND_SOC_CS4270_HWMUTE | ||
29 | bool | ||
30 | depends on SND_SOC_CS4270 | ||
31 | |||
32 | # Cirrus Logic CS4270 Codec VD = 3.3V Errata | ||
33 | # Select if you are affected by the errata where the part will not function | ||
34 | # if MCLK divide-by-1.5 is selected and VD is set to 3.3V. The driver will | ||
35 | # not select any sample rates that require MCLK to be divided by 1.5. | ||
36 | config SND_SOC_CS4270_VD33_ERRATA | ||
37 | bool | ||
38 | depends on SND_SOC_CS4270 | ||
39 | |||
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index e39a747a17cf..7ad78e36d506 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
@@ -3,9 +3,11 @@ snd-soc-wm8731-objs := wm8731.o | |||
3 | snd-soc-wm8750-objs := wm8750.o | 3 | snd-soc-wm8750-objs := wm8750.o |
4 | snd-soc-wm8753-objs := wm8753.o | 4 | snd-soc-wm8753-objs := wm8753.o |
5 | snd-soc-wm9712-objs := wm9712.o | 5 | snd-soc-wm9712-objs := wm9712.o |
6 | snd-soc-cs4270-objs := cs4270.o | ||
6 | 7 | ||
7 | obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o | 8 | obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o |
8 | obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o | 9 | obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o |
9 | obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o | 10 | obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o |
10 | obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o | 11 | obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o |
11 | obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o | 12 | obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o |
13 | obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o | ||
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c new file mode 100644 index 000000000000..5d601ad6da70 --- /dev/null +++ b/sound/soc/codecs/cs4270.c | |||
@@ -0,0 +1,805 @@ | |||
1 | /* | ||
2 | * CS4270 ALSA SoC (ASoC) codec driver | ||
3 | * | ||
4 | * Author: Timur Tabi <timur@freescale.com> | ||
5 | * | ||
6 | * Copyright 2007 Freescale Semiconductor, Inc. This file is licensed under | ||
7 | * the terms of the GNU General Public License version 2. This program | ||
8 | * is licensed "as is" without any warranty of any kind, whether express | ||
9 | * or implied. | ||
10 | * | ||
11 | * This is an ASoC device driver for the Cirrus Logic CS4270 codec. | ||
12 | * | ||
13 | * Current features/limitations: | ||
14 | * | ||
15 | * 1) Software mode is supported. Stand-alone mode is automatically | ||
16 | * selected if I2C is disabled or if a CS4270 is not found on the I2C | ||
17 | * bus. However, stand-alone mode is only partially implemented because | ||
18 | * there is no mechanism yet for this driver and the machine driver to | ||
19 | * communicate the values of the M0, M1, MCLK1, and MCLK2 pins. | ||
20 | * 2) Only I2C is supported, not SPI | ||
21 | * 3) Only Master mode is supported, not Slave. | ||
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 | */ | ||
28 | |||
29 | #include <linux/module.h> | ||
30 | #include <linux/platform_device.h> | ||
31 | #include <sound/driver.h> | ||
32 | #include <sound/core.h> | ||
33 | #include <sound/soc.h> | ||
34 | #include <sound/initval.h> | ||
35 | #include <linux/i2c.h> | ||
36 | |||
37 | #include "cs4270.h" | ||
38 | |||
39 | /* If I2C is defined, then we support software mode. However, if we're | ||
40 | not compiled as module but I2C is, then we can't use I2C calls. */ | ||
41 | #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) | ||
42 | #define USE_I2C | ||
43 | #endif | ||
44 | |||
45 | /* Private data for the CS4270 */ | ||
46 | struct cs4270_private { | ||
47 | unsigned int mclk; /* Input frequency of the MCLK pin */ | ||
48 | unsigned int mode; /* The mode (I2S or left-justified) */ | ||
49 | }; | ||
50 | |||
51 | /* The number of MCLK/LRCK ratios supported by the CS4270 */ | ||
52 | #define NUM_MCLK_RATIOS 9 | ||
53 | |||
54 | /* The actual MCLK/LRCK ratios, in increasing numerical order */ | ||
55 | static unsigned int mclk_ratios[NUM_MCLK_RATIOS] = | ||
56 | {64, 96, 128, 192, 256, 384, 512, 768, 1024}; | ||
57 | |||
58 | /* | ||
59 | * Determine the CS4270 samples rates. | ||
60 | * | ||
61 | * 'freq' is the input frequency to MCLK. The other parameters are ignored. | ||
62 | * | ||
63 | * The value of MCLK is used to determine which sample rates are supported | ||
64 | * by the CS4270. The ratio of MCLK / Fs must be equal to one of nine | ||
65 | * support values: 64, 96, 128, 192, 256, 384, 512, 768, and 1024. | ||
66 | * | ||
67 | * This function calculates the nine ratios and determines which ones match | ||
68 | * a standard sample rate. If there's a match, then it is added to the list | ||
69 | * of support sample rates. | ||
70 | * | ||
71 | * This function must be called by the machine driver's 'startup' function, | ||
72 | * otherwise the list of supported sample rates will not be available in | ||
73 | * time for ALSA. | ||
74 | * | ||
75 | * Note that in stand-alone mode, the sample rate is determined by input | ||
76 | * pins M0, M1, MDIV1, and MDIV2. Also in stand-alone mode, divide-by-3 | ||
77 | * is not a programmable option. However, divide-by-3 is not an available | ||
78 | * option in stand-alone mode. This cases two problems: a ratio of 768 is | ||
79 | * not available (it requires divide-by-3) and B) ratios 192 and 384 can | ||
80 | * only be selected with divide-by-1.5, but there is an errate that make | ||
81 | * this selection difficult. | ||
82 | * | ||
83 | * In addition, there is no mechanism for communicating with the machine | ||
84 | * driver what the input settings can be. This would need to be implemented | ||
85 | * for stand-alone mode to work. | ||
86 | */ | ||
87 | static int cs4270_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai, | ||
88 | int clk_id, unsigned int freq, int dir) | ||
89 | { | ||
90 | struct snd_soc_codec *codec = codec_dai->codec; | ||
91 | struct cs4270_private *cs4270 = codec->private_data; | ||
92 | unsigned int rates = 0; | ||
93 | unsigned int rate_min = -1; | ||
94 | unsigned int rate_max = 0; | ||
95 | unsigned int i; | ||
96 | |||
97 | cs4270->mclk = freq; | ||
98 | |||
99 | for (i = 0; i < NUM_MCLK_RATIOS; i++) { | ||
100 | unsigned int rate = freq / mclk_ratios[i]; | ||
101 | rates |= snd_pcm_rate_to_rate_bit(rate); | ||
102 | if (rate < rate_min) | ||
103 | rate_min = rate; | ||
104 | if (rate > rate_max) | ||
105 | rate_max = rate; | ||
106 | } | ||
107 | /* FIXME: soc should support a rate list */ | ||
108 | rates &= ~SNDRV_PCM_RATE_KNOT; | ||
109 | |||
110 | if (!rates) { | ||
111 | printk(KERN_ERR "cs4270: could not find a valid sample rate\n"); | ||
112 | return -EINVAL; | ||
113 | } | ||
114 | |||
115 | codec_dai->playback.rates = rates; | ||
116 | codec_dai->playback.rate_min = rate_min; | ||
117 | codec_dai->playback.rate_max = rate_max; | ||
118 | |||
119 | codec_dai->capture.rates = rates; | ||
120 | codec_dai->capture.rate_min = rate_min; | ||
121 | codec_dai->capture.rate_max = rate_max; | ||
122 | |||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | /* | ||
127 | * Configure the codec for the selected audio format | ||
128 | * | ||
129 | * This function takes a bitmask of SND_SOC_DAIFMT_x bits and programs the | ||
130 | * codec accordingly. | ||
131 | * | ||
132 | * Currently, this function only supports SND_SOC_DAIFMT_I2S and | ||
133 | * SND_SOC_DAIFMT_LEFT_J. The CS4270 codec also supports right-justified | ||
134 | * data for playback only, but ASoC currently does not support different | ||
135 | * formats for playback vs. record. | ||
136 | */ | ||
137 | static int cs4270_set_dai_fmt(struct snd_soc_codec_dai *codec_dai, | ||
138 | unsigned int format) | ||
139 | { | ||
140 | struct snd_soc_codec *codec = codec_dai->codec; | ||
141 | struct cs4270_private *cs4270 = codec->private_data; | ||
142 | int ret = 0; | ||
143 | |||
144 | switch (format & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
145 | case SND_SOC_DAIFMT_I2S: | ||
146 | case SND_SOC_DAIFMT_LEFT_J: | ||
147 | cs4270->mode = format & SND_SOC_DAIFMT_FORMAT_MASK; | ||
148 | break; | ||
149 | default: | ||
150 | printk(KERN_ERR "cs4270: invalid DAI format\n"); | ||
151 | ret = -EINVAL; | ||
152 | } | ||
153 | |||
154 | return ret; | ||
155 | } | ||
156 | |||
157 | /* | ||
158 | * The codec isn't really big-endian or little-endian, since the I2S | ||
159 | * interface requires data to be sent serially with the MSbit first. | ||
160 | * However, to support BE and LE I2S devices, we specify both here. That | ||
161 | * way, ALSA will always match the bit patterns. | ||
162 | */ | ||
163 | #define CS4270_FORMATS (SNDRV_PCM_FMTBIT_S8 | \ | ||
164 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \ | ||
165 | SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE | \ | ||
166 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE | \ | ||
167 | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE | \ | ||
168 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE) | ||
169 | |||
170 | #ifdef USE_I2C | ||
171 | |||
172 | /* CS4270 registers addresses */ | ||
173 | #define CS4270_CHIPID 0x01 /* Chip ID */ | ||
174 | #define CS4270_PWRCTL 0x02 /* Power Control */ | ||
175 | #define CS4270_MODE 0x03 /* Mode Control */ | ||
176 | #define CS4270_FORMAT 0x04 /* Serial Format, ADC/DAC Control */ | ||
177 | #define CS4270_TRANS 0x05 /* Transition Control */ | ||
178 | #define CS4270_MUTE 0x06 /* Mute Control */ | ||
179 | #define CS4270_VOLA 0x07 /* DAC Channel A Volume Control */ | ||
180 | #define CS4270_VOLB 0x08 /* DAC Channel B Volume Control */ | ||
181 | |||
182 | #define CS4270_FIRSTREG 0x01 | ||
183 | #define CS4270_LASTREG 0x08 | ||
184 | #define CS4270_NUMREGS (CS4270_LASTREG - CS4270_FIRSTREG + 1) | ||
185 | |||
186 | /* Bit masks for the CS4270 registers */ | ||
187 | #define CS4270_CHIPID_ID 0xF0 | ||
188 | #define CS4270_CHIPID_REV 0x0F | ||
189 | #define CS4270_PWRCTL_FREEZE 0x80 | ||
190 | #define CS4270_PWRCTL_PDN_ADC 0x20 | ||
191 | #define CS4270_PWRCTL_PDN_DAC 0x02 | ||
192 | #define CS4270_PWRCTL_PDN 0x01 | ||
193 | #define CS4270_MODE_SPEED_MASK 0x30 | ||
194 | #define CS4270_MODE_1X 0x00 | ||
195 | #define CS4270_MODE_2X 0x10 | ||
196 | #define CS4270_MODE_4X 0x20 | ||
197 | #define CS4270_MODE_SLAVE 0x30 | ||
198 | #define CS4270_MODE_DIV_MASK 0x0E | ||
199 | #define CS4270_MODE_DIV1 0x00 | ||
200 | #define CS4270_MODE_DIV15 0x02 | ||
201 | #define CS4270_MODE_DIV2 0x04 | ||
202 | #define CS4270_MODE_DIV3 0x06 | ||
203 | #define CS4270_MODE_DIV4 0x08 | ||
204 | #define CS4270_MODE_POPGUARD 0x01 | ||
205 | #define CS4270_FORMAT_FREEZE_A 0x80 | ||
206 | #define CS4270_FORMAT_FREEZE_B 0x40 | ||
207 | #define CS4270_FORMAT_LOOPBACK 0x20 | ||
208 | #define CS4270_FORMAT_DAC_MASK 0x18 | ||
209 | #define CS4270_FORMAT_DAC_LJ 0x00 | ||
210 | #define CS4270_FORMAT_DAC_I2S 0x08 | ||
211 | #define CS4270_FORMAT_DAC_RJ16 0x18 | ||
212 | #define CS4270_FORMAT_DAC_RJ24 0x10 | ||
213 | #define CS4270_FORMAT_ADC_MASK 0x01 | ||
214 | #define CS4270_FORMAT_ADC_LJ 0x00 | ||
215 | #define CS4270_FORMAT_ADC_I2S 0x01 | ||
216 | #define CS4270_TRANS_ONE_VOL 0x80 | ||
217 | #define CS4270_TRANS_SOFT 0x40 | ||
218 | #define CS4270_TRANS_ZERO 0x20 | ||
219 | #define CS4270_TRANS_INV_ADC_A 0x08 | ||
220 | #define CS4270_TRANS_INV_ADC_B 0x10 | ||
221 | #define CS4270_TRANS_INV_DAC_A 0x02 | ||
222 | #define CS4270_TRANS_INV_DAC_B 0x04 | ||
223 | #define CS4270_TRANS_DEEMPH 0x01 | ||
224 | #define CS4270_MUTE_AUTO 0x20 | ||
225 | #define CS4270_MUTE_ADC_A 0x08 | ||
226 | #define CS4270_MUTE_ADC_B 0x10 | ||
227 | #define CS4270_MUTE_POLARITY 0x04 | ||
228 | #define CS4270_MUTE_DAC_A 0x01 | ||
229 | #define CS4270_MUTE_DAC_B 0x02 | ||
230 | |||
231 | /* | ||
232 | * A list of addresses on which this CS4270 could use. I2C addresses are | ||
233 | * 7 bits. For the CS4270, the upper four bits are always 1001, and the | ||
234 | * lower three bits are determined via the AD2, AD1, and AD0 pins | ||
235 | * (respectively). | ||
236 | */ | ||
237 | static unsigned short normal_i2c[] = { | ||
238 | 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, I2C_CLIENT_END | ||
239 | }; | ||
240 | I2C_CLIENT_INSMOD; | ||
241 | |||
242 | /* | ||
243 | * Pre-fill the CS4270 register cache. | ||
244 | * | ||
245 | * We use the auto-increment feature of the CS4270 to read all registers in | ||
246 | * one shot. | ||
247 | */ | ||
248 | static int cs4270_fill_cache(struct snd_soc_codec *codec) | ||
249 | { | ||
250 | u8 *cache = codec->reg_cache; | ||
251 | struct i2c_client *i2c_client = codec->control_data; | ||
252 | s32 length; | ||
253 | |||
254 | length = i2c_smbus_read_i2c_block_data(i2c_client, | ||
255 | CS4270_FIRSTREG | 0x80, CS4270_NUMREGS, cache); | ||
256 | |||
257 | if (length != CS4270_NUMREGS) { | ||
258 | printk(KERN_ERR "cs4270: I2C read failure, addr=0x%x\n", | ||
259 | i2c_client->addr); | ||
260 | return -EIO; | ||
261 | } | ||
262 | |||
263 | return 0; | ||
264 | } | ||
265 | |||
266 | /* | ||
267 | * Read from the CS4270 register cache. | ||
268 | * | ||
269 | * This CS4270 registers are cached to avoid excessive I2C I/O operations. | ||
270 | * After the initial read to pre-fill the cache, the CS4270 never updates | ||
271 | * the register values, so we won't have a cache coherncy problem. | ||
272 | */ | ||
273 | static unsigned int cs4270_read_reg_cache(struct snd_soc_codec *codec, | ||
274 | unsigned int reg) | ||
275 | { | ||
276 | u8 *cache = codec->reg_cache; | ||
277 | |||
278 | if ((reg < CS4270_FIRSTREG) || (reg > CS4270_LASTREG)) | ||
279 | return -EIO; | ||
280 | |||
281 | return cache[reg - CS4270_FIRSTREG]; | ||
282 | } | ||
283 | |||
284 | /* | ||
285 | * Write to a CS4270 register via the I2C bus. | ||
286 | * | ||
287 | * This function writes the given value to the given CS4270 register, and | ||
288 | * also updates the register cache. | ||
289 | * | ||
290 | * Note that we don't use the hw_write function pointer of snd_soc_codec. | ||
291 | * That's because it's too clunky: the hw_write_t prototype does not match | ||
292 | * i2c_smbus_write_byte_data(), and it's just another layer of overhead. | ||
293 | */ | ||
294 | static int cs4270_i2c_write(struct snd_soc_codec *codec, unsigned int reg, | ||
295 | unsigned int value) | ||
296 | { | ||
297 | u8 *cache = codec->reg_cache; | ||
298 | |||
299 | if ((reg < CS4270_FIRSTREG) || (reg > CS4270_LASTREG)) | ||
300 | return -EIO; | ||
301 | |||
302 | /* Only perform an I2C operation if the new value is different */ | ||
303 | if (cache[reg - CS4270_FIRSTREG] != value) { | ||
304 | struct i2c_client *client = codec->control_data; | ||
305 | if (i2c_smbus_write_byte_data(client, reg, value)) { | ||
306 | printk(KERN_ERR "cs4270: I2C write failed\n"); | ||
307 | return -EIO; | ||
308 | } | ||
309 | |||
310 | /* We've written to the hardware, so update the cache */ | ||
311 | cache[reg - CS4270_FIRSTREG] = value; | ||
312 | } | ||
313 | |||
314 | return 0; | ||
315 | } | ||
316 | |||
317 | /* | ||
318 | * Clock Ratio Selection for Master Mode with I2C enabled | ||
319 | * | ||
320 | * The data for this chart is taken from Table 5 of the CS4270 reference | ||
321 | * manual. | ||
322 | * | ||
323 | * This table is used to determine how to program the Mode Control register. | ||
324 | * It is also used by cs4270_set_dai_sysclk() to tell ALSA which sampling | ||
325 | * rates the CS4270 currently supports. | ||
326 | * | ||
327 | * Each element in this array corresponds to the ratios in mclk_ratios[]. | ||
328 | * These two arrays need to be in sync. | ||
329 | * | ||
330 | * 'speed_mode' is the corresponding bit pattern to be written to the | ||
331 | * MODE bits of the Mode Control Register | ||
332 | * | ||
333 | * 'mclk' is the corresponding bit pattern to be wirten to the MCLK bits of | ||
334 | * the Mode Control Register. | ||
335 | * | ||
336 | * In situations where a single ratio is represented by multiple speed | ||
337 | * modes, we favor the slowest speed. E.g, for a ratio of 128, we pick | ||
338 | * double-speed instead of quad-speed. However, the CS4270 errata states | ||
339 | * that Divide-By-1.5 can cause failures, so we avoid that mode where | ||
340 | * possible. | ||
341 | * | ||
342 | * ERRATA: There is an errata for the CS4270 where divide-by-1.5 does not | ||
343 | * work if VD = 3.3V. If this effects you, select the | ||
344 | * CONFIG_SND_SOC_CS4270_VD33_ERRATA Kconfig option, and the driver will | ||
345 | * never select any sample rates that require divide-by-1.5. | ||
346 | */ | ||
347 | static struct { | ||
348 | u8 speed_mode; | ||
349 | u8 mclk; | ||
350 | } cs4270_mode_ratios[NUM_MCLK_RATIOS] = { | ||
351 | {CS4270_MODE_4X, CS4270_MODE_DIV1}, /* 64 */ | ||
352 | #ifndef CONFIG_SND_SOC_CS4270_VD33_ERRATA | ||
353 | {CS4270_MODE_4X, CS4270_MODE_DIV15}, /* 96 */ | ||
354 | #endif | ||
355 | {CS4270_MODE_2X, CS4270_MODE_DIV1}, /* 128 */ | ||
356 | {CS4270_MODE_4X, CS4270_MODE_DIV3}, /* 192 */ | ||
357 | {CS4270_MODE_1X, CS4270_MODE_DIV1}, /* 256 */ | ||
358 | {CS4270_MODE_2X, CS4270_MODE_DIV3}, /* 384 */ | ||
359 | {CS4270_MODE_1X, CS4270_MODE_DIV2}, /* 512 */ | ||
360 | {CS4270_MODE_1X, CS4270_MODE_DIV3}, /* 768 */ | ||
361 | {CS4270_MODE_1X, CS4270_MODE_DIV4} /* 1024 */ | ||
362 | }; | ||
363 | |||
364 | /* | ||
365 | * Program the CS4270 with the given hardware parameters. | ||
366 | * | ||
367 | * The .dai_ops functions are used to provide board-specific data, like | ||
368 | * input frequencies, to this driver. This function takes that information, | ||
369 | * combines it with the hardware parameters provided, and programs the | ||
370 | * hardware accordingly. | ||
371 | */ | ||
372 | static int cs4270_hw_params(struct snd_pcm_substream *substream, | ||
373 | struct snd_pcm_hw_params *params) | ||
374 | { | ||
375 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
376 | struct snd_soc_device *socdev = rtd->socdev; | ||
377 | struct snd_soc_codec *codec = socdev->codec; | ||
378 | struct cs4270_private *cs4270 = codec->private_data; | ||
379 | unsigned int ret = 0; | ||
380 | unsigned int i; | ||
381 | unsigned int rate; | ||
382 | unsigned int ratio; | ||
383 | int reg; | ||
384 | |||
385 | /* Figure out which MCLK/LRCK ratio to use */ | ||
386 | |||
387 | rate = params_rate(params); /* Sampling rate, in Hz */ | ||
388 | ratio = cs4270->mclk / rate; /* MCLK/LRCK ratio */ | ||
389 | |||
390 | for (i = 0; i < NUM_MCLK_RATIOS; i++) { | ||
391 | if (mclk_ratios[i] == ratio) | ||
392 | break; | ||
393 | } | ||
394 | |||
395 | if (i == NUM_MCLK_RATIOS) { | ||
396 | /* We did not find a matching ratio */ | ||
397 | printk(KERN_ERR "cs4270: could not find matching ratio\n"); | ||
398 | return -EINVAL; | ||
399 | } | ||
400 | |||
401 | /* Freeze and power-down the codec */ | ||
402 | |||
403 | ret = snd_soc_write(codec, CS4270_PWRCTL, CS4270_PWRCTL_FREEZE | | ||
404 | CS4270_PWRCTL_PDN_ADC | CS4270_PWRCTL_PDN_DAC | | ||
405 | CS4270_PWRCTL_PDN); | ||
406 | if (ret < 0) { | ||
407 | printk(KERN_ERR "cs4270: I2C write failed\n"); | ||
408 | return ret; | ||
409 | } | ||
410 | |||
411 | /* Program the mode control register */ | ||
412 | |||
413 | reg = snd_soc_read(codec, CS4270_MODE); | ||
414 | reg &= ~(CS4270_MODE_SPEED_MASK | CS4270_MODE_DIV_MASK); | ||
415 | reg |= cs4270_mode_ratios[i].speed_mode | cs4270_mode_ratios[i].mclk; | ||
416 | |||
417 | ret = snd_soc_write(codec, CS4270_MODE, reg); | ||
418 | if (ret < 0) { | ||
419 | printk(KERN_ERR "cs4270: I2C write failed\n"); | ||
420 | return ret; | ||
421 | } | ||
422 | |||
423 | /* Program the format register */ | ||
424 | |||
425 | reg = snd_soc_read(codec, CS4270_FORMAT); | ||
426 | reg &= ~(CS4270_FORMAT_DAC_MASK | CS4270_FORMAT_ADC_MASK); | ||
427 | |||
428 | switch (cs4270->mode) { | ||
429 | case SND_SOC_DAIFMT_I2S: | ||
430 | reg |= CS4270_FORMAT_DAC_I2S | CS4270_FORMAT_ADC_I2S; | ||
431 | break; | ||
432 | case SND_SOC_DAIFMT_LEFT_J: | ||
433 | reg |= CS4270_FORMAT_DAC_LJ | CS4270_FORMAT_ADC_LJ; | ||
434 | break; | ||
435 | default: | ||
436 | printk(KERN_ERR "cs4270: unknown format\n"); | ||
437 | return -EINVAL; | ||
438 | } | ||
439 | |||
440 | ret = snd_soc_write(codec, CS4270_FORMAT, reg); | ||
441 | if (ret < 0) { | ||
442 | printk(KERN_ERR "cs4270: I2C write failed\n"); | ||
443 | return ret; | ||
444 | } | ||
445 | |||
446 | /* Disable auto-mute. This feature appears to be buggy, because in | ||
447 | some situations, auto-mute will not deactivate when it should. */ | ||
448 | |||
449 | reg = snd_soc_read(codec, CS4270_MUTE); | ||
450 | reg &= ~CS4270_MUTE_AUTO; | ||
451 | ret = snd_soc_write(codec, CS4270_MUTE, reg); | ||
452 | if (ret < 0) { | ||
453 | printk(KERN_ERR "cs4270: I2C write failed\n"); | ||
454 | return ret; | ||
455 | } | ||
456 | |||
457 | /* Thaw and power-up the codec */ | ||
458 | |||
459 | ret = snd_soc_write(codec, CS4270_PWRCTL, 0); | ||
460 | if (ret < 0) { | ||
461 | printk(KERN_ERR "cs4270: I2C write failed\n"); | ||
462 | return ret; | ||
463 | } | ||
464 | |||
465 | return ret; | ||
466 | } | ||
467 | |||
468 | #ifdef CONFIG_SND_SOC_CS4270_HWMUTE | ||
469 | |||
470 | /* | ||
471 | * Set the CS4270 external mute | ||
472 | * | ||
473 | * This function toggles the mute bits in the MUTE register. The CS4270's | ||
474 | * mute capability is intended for external muting circuitry, so if the | ||
475 | * board does not have the MUTEA or MUTEB pins connected to such circuitry, | ||
476 | * then this function will do nothing. | ||
477 | */ | ||
478 | static int cs4270_mute(struct snd_soc_codec_dai *dai, int mute) | ||
479 | { | ||
480 | struct snd_soc_codec *codec = dai->codec; | ||
481 | int reg6; | ||
482 | |||
483 | reg6 = snd_soc_read(codec, CS4270_MUTE); | ||
484 | |||
485 | if (mute) | ||
486 | reg6 |= CS4270_MUTE_ADC_A | CS4270_MUTE_ADC_B | | ||
487 | CS4270_MUTE_DAC_A | CS4270_MUTE_DAC_B; | ||
488 | else | ||
489 | reg6 &= ~(CS4270_MUTE_ADC_A | CS4270_MUTE_ADC_B | | ||
490 | CS4270_MUTE_DAC_A | CS4270_MUTE_DAC_B); | ||
491 | |||
492 | return snd_soc_write(codec, CS4270_MUTE, reg6); | ||
493 | } | ||
494 | |||
495 | #endif | ||
496 | |||
497 | static int cs4270_i2c_probe(struct i2c_adapter *adap, int addr, int kind); | ||
498 | |||
499 | /* | ||
500 | * Notify the driver that a new I2C bus has been found. | ||
501 | * | ||
502 | * This function is called for each I2C bus in the system. The function | ||
503 | * then asks the I2C subsystem to probe that bus at the addresses on which | ||
504 | * our device (the CS4270) could exist. If a device is found at one of | ||
505 | * those addresses, then our probe function (cs4270_i2c_probe) is called. | ||
506 | */ | ||
507 | static int cs4270_i2c_attach(struct i2c_adapter *adapter) | ||
508 | { | ||
509 | return i2c_probe(adapter, &addr_data, cs4270_i2c_probe); | ||
510 | } | ||
511 | |||
512 | static int cs4270_i2c_detach(struct i2c_client *client) | ||
513 | { | ||
514 | struct snd_soc_codec *codec = i2c_get_clientdata(client); | ||
515 | |||
516 | i2c_detach_client(client); | ||
517 | codec->control_data = NULL; | ||
518 | |||
519 | kfree(codec->reg_cache); | ||
520 | codec->reg_cache = NULL; | ||
521 | |||
522 | kfree(client); | ||
523 | return 0; | ||
524 | } | ||
525 | |||
526 | /* A list of non-DAPM controls that the CS4270 supports */ | ||
527 | static const struct snd_kcontrol_new cs4270_snd_controls[] = { | ||
528 | SOC_DOUBLE_R("Master Playback Volume", | ||
529 | CS4270_VOLA, CS4270_VOLB, 0, 0xFF, 1) | ||
530 | }; | ||
531 | |||
532 | static struct i2c_driver cs4270_i2c_driver = { | ||
533 | .driver = { | ||
534 | .name = "CS4270 I2C", | ||
535 | .owner = THIS_MODULE, | ||
536 | }, | ||
537 | .id = I2C_DRIVERID_CS4270, | ||
538 | .attach_adapter = cs4270_i2c_attach, | ||
539 | .detach_client = cs4270_i2c_detach, | ||
540 | }; | ||
541 | |||
542 | /* | ||
543 | * Global variable to store socdev for i2c probe function. | ||
544 | * | ||
545 | * If struct i2c_driver had a private_data field, we wouldn't need to use | ||
546 | * cs4270_socdec. This is the only way to pass the socdev structure to | ||
547 | * cs4270_i2c_probe(). | ||
548 | * | ||
549 | * The real solution to cs4270_socdev is to create a mechanism | ||
550 | * that maps I2C addresses to snd_soc_device structures. Perhaps the | ||
551 | * creation of the snd_soc_device object should be moved out of | ||
552 | * cs4270_probe() and into cs4270_i2c_probe(), but that would make this | ||
553 | * driver dependent on I2C. The CS4270 supports "stand-alone" mode, whereby | ||
554 | * the chip is *not* connected to the I2C bus, but is instead configured via | ||
555 | * input pins. | ||
556 | */ | ||
557 | static struct snd_soc_device *cs4270_socdev; | ||
558 | |||
559 | /* | ||
560 | * Initialize the I2C interface of the CS4270 | ||
561 | * | ||
562 | * This function is called for whenever the I2C subsystem finds a device | ||
563 | * at a particular address. | ||
564 | * | ||
565 | * Note: snd_soc_new_pcms() must be called before this function can be called, | ||
566 | * because of snd_ctl_add(). | ||
567 | */ | ||
568 | static int cs4270_i2c_probe(struct i2c_adapter *adapter, int addr, int kind) | ||
569 | { | ||
570 | struct snd_soc_device *socdev = cs4270_socdev; | ||
571 | struct snd_soc_codec *codec = socdev->codec; | ||
572 | struct i2c_client *i2c_client = NULL; | ||
573 | int i; | ||
574 | int ret = 0; | ||
575 | |||
576 | /* Probing all possible addresses has one drawback: if there are | ||
577 | multiple CS4270s on the bus, then you cannot specify which | ||
578 | socdev is matched with which CS4270. For now, we just reject | ||
579 | this I2C device if the socdev already has one attached. */ | ||
580 | if (codec->control_data) | ||
581 | return -ENODEV; | ||
582 | |||
583 | /* Note: codec_dai->codec is NULL here */ | ||
584 | |||
585 | i2c_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); | ||
586 | if (!i2c_client) { | ||
587 | printk(KERN_ERR "cs4270: could not allocate I2C client\n"); | ||
588 | return -ENOMEM; | ||
589 | } | ||
590 | |||
591 | codec->reg_cache = kzalloc(CS4270_NUMREGS, GFP_KERNEL); | ||
592 | if (!codec->reg_cache) { | ||
593 | printk(KERN_ERR "cs4270: could not allocate register cache\n"); | ||
594 | ret = -ENOMEM; | ||
595 | goto error; | ||
596 | } | ||
597 | |||
598 | i2c_set_clientdata(i2c_client, codec); | ||
599 | strcpy(i2c_client->name, "CS4270"); | ||
600 | |||
601 | i2c_client->driver = &cs4270_i2c_driver; | ||
602 | i2c_client->adapter = adapter; | ||
603 | i2c_client->addr = addr; | ||
604 | |||
605 | /* Verify that we have a CS4270 */ | ||
606 | |||
607 | ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID); | ||
608 | if (ret < 0) { | ||
609 | printk(KERN_ERR "cs4270: failed to read I2C\n"); | ||
610 | goto error; | ||
611 | } | ||
612 | /* The top four bits of the chip ID should be 1100. */ | ||
613 | if ((ret & 0xF0) != 0xC0) { | ||
614 | /* The device at this address is not a CS4270 codec */ | ||
615 | ret = -ENODEV; | ||
616 | goto error; | ||
617 | } | ||
618 | |||
619 | printk(KERN_INFO "cs4270: found device at I2C address %X\n", addr); | ||
620 | printk(KERN_INFO "cs4270: hardware revision %X\n", ret & 0xF); | ||
621 | |||
622 | /* Tell the I2C layer a new client has arrived */ | ||
623 | |||
624 | ret = i2c_attach_client(i2c_client); | ||
625 | if (ret) { | ||
626 | printk(KERN_ERR "cs4270: could not attach codec, " | ||
627 | "I2C address %x, error code %i\n", addr, ret); | ||
628 | goto error; | ||
629 | } | ||
630 | |||
631 | codec->control_data = i2c_client; | ||
632 | codec->read = cs4270_read_reg_cache; | ||
633 | codec->write = cs4270_i2c_write; | ||
634 | codec->reg_cache_size = CS4270_NUMREGS; | ||
635 | |||
636 | /* The I2C interface is set up, so pre-fill our register cache */ | ||
637 | |||
638 | ret = cs4270_fill_cache(codec); | ||
639 | if (ret < 0) { | ||
640 | printk(KERN_ERR "cs4270: failed to fill register cache\n"); | ||
641 | goto error; | ||
642 | } | ||
643 | |||
644 | /* Add the non-DAPM controls */ | ||
645 | |||
646 | for (i = 0; i < ARRAY_SIZE(cs4270_snd_controls); i++) { | ||
647 | struct snd_kcontrol *kctrl = | ||
648 | snd_soc_cnew(&cs4270_snd_controls[i], codec, NULL); | ||
649 | |||
650 | ret = snd_ctl_add(codec->card, kctrl); | ||
651 | if (ret < 0) | ||
652 | goto error; | ||
653 | } | ||
654 | |||
655 | return 0; | ||
656 | |||
657 | error: | ||
658 | if (codec->control_data) { | ||
659 | i2c_detach_client(i2c_client); | ||
660 | codec->control_data = NULL; | ||
661 | } | ||
662 | |||
663 | kfree(codec->reg_cache); | ||
664 | codec->reg_cache = NULL; | ||
665 | codec->reg_cache_size = 0; | ||
666 | |||
667 | kfree(i2c_client); | ||
668 | |||
669 | return ret; | ||
670 | } | ||
671 | |||
672 | #endif | ||
673 | |||
674 | struct snd_soc_codec_dai cs4270_dai = { | ||
675 | .name = "CS4270", | ||
676 | .playback = { | ||
677 | .stream_name = "Playback", | ||
678 | .channels_min = 1, | ||
679 | .channels_max = 2, | ||
680 | .rates = 0, | ||
681 | .formats = CS4270_FORMATS, | ||
682 | }, | ||
683 | .capture = { | ||
684 | .stream_name = "Capture", | ||
685 | .channels_min = 1, | ||
686 | .channels_max = 2, | ||
687 | .rates = 0, | ||
688 | .formats = CS4270_FORMATS, | ||
689 | }, | ||
690 | .dai_ops = { | ||
691 | .set_sysclk = cs4270_set_dai_sysclk, | ||
692 | .set_fmt = cs4270_set_dai_fmt, | ||
693 | } | ||
694 | }; | ||
695 | EXPORT_SYMBOL_GPL(cs4270_dai); | ||
696 | |||
697 | /* | ||
698 | * ASoC probe function | ||
699 | * | ||
700 | * This function is called when the machine driver calls | ||
701 | * platform_device_add(). | ||
702 | */ | ||
703 | static int cs4270_probe(struct platform_device *pdev) | ||
704 | { | ||
705 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
706 | struct snd_soc_codec *codec; | ||
707 | int ret = 0; | ||
708 | |||
709 | printk(KERN_INFO "CS4270 ALSA SoC Codec\n"); | ||
710 | |||
711 | /* Allocate enough space for the snd_soc_codec structure | ||
712 | and our private data together. */ | ||
713 | codec = kzalloc(ALIGN(sizeof(struct snd_soc_codec), 4) + | ||
714 | sizeof(struct cs4270_private), GFP_KERNEL); | ||
715 | if (!codec) { | ||
716 | printk(KERN_ERR "cs4270: Could not allocate codec structure\n"); | ||
717 | return -ENOMEM; | ||
718 | } | ||
719 | |||
720 | mutex_init(&codec->mutex); | ||
721 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
722 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
723 | |||
724 | codec->name = "CS4270"; | ||
725 | codec->owner = THIS_MODULE; | ||
726 | codec->dai = &cs4270_dai; | ||
727 | codec->num_dai = 1; | ||
728 | codec->private_data = codec + ALIGN(sizeof(struct snd_soc_codec), 4); | ||
729 | |||
730 | socdev->codec = codec; | ||
731 | |||
732 | /* Register PCMs */ | ||
733 | |||
734 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
735 | if (ret < 0) { | ||
736 | printk(KERN_ERR "cs4270: failed to create PCMs\n"); | ||
737 | return ret; | ||
738 | } | ||
739 | |||
740 | #ifdef USE_I2C | ||
741 | cs4270_socdev = socdev; | ||
742 | |||
743 | ret = i2c_add_driver(&cs4270_i2c_driver); | ||
744 | if (ret) { | ||
745 | printk(KERN_ERR "cs4270: failed to attach driver"); | ||
746 | snd_soc_free_pcms(socdev); | ||
747 | return ret; | ||
748 | } | ||
749 | |||
750 | /* Did we find a CS4270 on the I2C bus? */ | ||
751 | if (codec->control_data) { | ||
752 | /* Initialize codec ops */ | ||
753 | cs4270_dai.ops.hw_params = cs4270_hw_params; | ||
754 | #ifdef CONFIG_SND_SOC_CS4270_HWMUTE | ||
755 | cs4270_dai.dai_ops.digital_mute = cs4270_mute; | ||
756 | #endif | ||
757 | } else | ||
758 | printk(KERN_INFO "cs4270: no I2C device found, " | ||
759 | "using stand-alone mode\n"); | ||
760 | #else | ||
761 | printk(KERN_INFO "cs4270: I2C disabled, using stand-alone mode\n"); | ||
762 | #endif | ||
763 | |||
764 | ret = snd_soc_register_card(socdev); | ||
765 | if (ret < 0) { | ||
766 | printk(KERN_ERR "cs4270: failed to register card\n"); | ||
767 | snd_soc_free_pcms(socdev); | ||
768 | return ret; | ||
769 | } | ||
770 | |||
771 | return ret; | ||
772 | } | ||
773 | |||
774 | static int cs4270_remove(struct platform_device *pdev) | ||
775 | { | ||
776 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
777 | |||
778 | snd_soc_free_pcms(socdev); | ||
779 | |||
780 | #ifdef USE_I2C | ||
781 | if (socdev->codec->control_data) | ||
782 | i2c_del_driver(&cs4270_i2c_driver); | ||
783 | #endif | ||
784 | |||
785 | kfree(socdev->codec); | ||
786 | socdev->codec = NULL; | ||
787 | |||
788 | return 0; | ||
789 | } | ||
790 | |||
791 | /* | ||
792 | * ASoC codec device structure | ||
793 | * | ||
794 | * Assign this variable to the codec_dev field of the machine driver's | ||
795 | * snd_soc_device structure. | ||
796 | */ | ||
797 | struct snd_soc_codec_device soc_codec_device_cs4270 = { | ||
798 | .probe = cs4270_probe, | ||
799 | .remove = cs4270_remove | ||
800 | }; | ||
801 | EXPORT_SYMBOL_GPL(soc_codec_device_cs4270); | ||
802 | |||
803 | MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); | ||
804 | MODULE_DESCRIPTION("Cirrus Logic CS4270 ALSA SoC Codec Driver"); | ||
805 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/cs4270.h b/sound/soc/codecs/cs4270.h new file mode 100644 index 000000000000..0ced49b7804d --- /dev/null +++ b/sound/soc/codecs/cs4270.h | |||
@@ -0,0 +1,28 @@ | |||
1 | /* | ||
2 | * Cirrus Logic CS4270 ALSA SoC Codec Driver | ||
3 | * | ||
4 | * Author: Timur Tabi <timur@freescale.com> | ||
5 | * | ||
6 | * Copyright 2007 Freescale Semiconductor, Inc. This file is licensed under | ||
7 | * the terms of the GNU General Public License version 2. This program | ||
8 | * is licensed "as is" without any warranty of any kind, whether express | ||
9 | * or implied. | ||
10 | */ | ||
11 | |||
12 | #ifndef _CS4270_H | ||
13 | #define _CS4270_H | ||
14 | |||
15 | /* | ||
16 | * The ASoC codec DAI structure for the CS4270. Assign this structure to | ||
17 | * the .codec_dai field of your machine driver's snd_soc_dai_link structure. | ||
18 | */ | ||
19 | extern struct snd_soc_codec_dai cs4270_dai; | ||
20 | |||
21 | /* | ||
22 | * The ASoC codec device structure for the CS4270. Assign this structure | ||
23 | * to the .codec_dev field of your machine driver's snd_soc_device | ||
24 | * structure. | ||
25 | */ | ||
26 | extern struct snd_soc_codec_device soc_codec_device_cs4270; | ||
27 | |||
28 | #endif | ||
diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c index 80e82109fef7..4dd8f35312b3 100644 --- a/sound/soc/pxa/spitz.c +++ b/sound/soc/pxa/spitz.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #include <asm/arch/hardware.h> | 34 | #include <asm/arch/hardware.h> |
35 | #include <asm/arch/akita.h> | 35 | #include <asm/arch/akita.h> |
36 | #include <asm/arch/spitz.h> | 36 | #include <asm/arch/spitz.h> |
37 | #include <asm/mach-types.h> | ||
38 | #include "../codecs/wm8750.h" | 37 | #include "../codecs/wm8750.h" |
39 | #include "pxa2xx-pcm.h" | 38 | #include "pxa2xx-pcm.h" |
40 | #include "pxa2xx-i2s.h" | 39 | #include "pxa2xx-i2s.h" |
diff --git a/sound/soc/s3c24xx/Kconfig b/sound/soc/s3c24xx/Kconfig index e97c68306a9a..5632a2e1518d 100644 --- a/sound/soc/s3c24xx/Kconfig +++ b/sound/soc/s3c24xx/Kconfig | |||
@@ -18,7 +18,7 @@ config SND_S3C2443_SOC_AC97 | |||
18 | 18 | ||
19 | config SND_S3C24XX_SOC_NEO1973_WM8753 | 19 | config SND_S3C24XX_SOC_NEO1973_WM8753 |
20 | tristate "SoC I2S Audio support for NEO1973 - WM8753" | 20 | tristate "SoC I2S Audio support for NEO1973 - WM8753" |
21 | depends on SND_S3C24XX_SOC && MACH_GTA01 | 21 | depends on SND_S3C24XX_SOC && MACH_NEO1973_GTA01 |
22 | select SND_S3C24XX_SOC_I2S | 22 | select SND_S3C24XX_SOC_I2S |
23 | select SND_SOC_WM8753 | 23 | select SND_SOC_WM8753 |
24 | help | 24 | help |
diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.c b/sound/soc/s3c24xx/s3c24xx-i2s.c index 39f02462e07d..cd89c4105fcd 100644 --- a/sound/soc/s3c24xx/s3c24xx-i2s.c +++ b/sound/soc/s3c24xx/s3c24xx-i2s.c | |||
@@ -385,6 +385,7 @@ static int s3c24xx_i2s_probe(struct platform_device *pdev) | |||
385 | s3c24xx_i2s.iis_clk=clk_get(&pdev->dev, "iis"); | 385 | s3c24xx_i2s.iis_clk=clk_get(&pdev->dev, "iis"); |
386 | if (s3c24xx_i2s.iis_clk == NULL) { | 386 | if (s3c24xx_i2s.iis_clk == NULL) { |
387 | DBG("failed to get iis_clock\n"); | 387 | DBG("failed to get iis_clock\n"); |
388 | iounmap(s3c24xx_i2s.regs); | ||
388 | return -ENODEV; | 389 | return -ENODEV; |
389 | } | 390 | } |
390 | clk_enable(s3c24xx_i2s.iis_clk); | 391 | clk_enable(s3c24xx_i2s.iis_clk); |
diff --git a/sound/soc/s3c24xx/s3c24xx-pcm.c b/sound/soc/s3c24xx/s3c24xx-pcm.c index bfbdc3cbd43b..4107a87d4de3 100644 --- a/sound/soc/s3c24xx/s3c24xx-pcm.c +++ b/sound/soc/s3c24xx/s3c24xx-pcm.c | |||
@@ -158,18 +158,22 @@ static int s3c24xx_pcm_hw_params(struct snd_pcm_substream *substream, | |||
158 | if (!dma) | 158 | if (!dma) |
159 | return 0; | 159 | return 0; |
160 | 160 | ||
161 | /* prepare DMA */ | 161 | /* this may get called several times by oss emulation |
162 | prtd->params = dma; | 162 | * with different params -HW */ |
163 | if (prtd->params == NULL) { | ||
164 | /* prepare DMA */ | ||
165 | prtd->params = dma; | ||
163 | 166 | ||
164 | DBG("params %p, client %p, channel %d\n", prtd->params, | 167 | DBG("params %p, client %p, channel %d\n", prtd->params, |
165 | prtd->params->client, prtd->params->channel); | 168 | prtd->params->client, prtd->params->channel); |
166 | 169 | ||
167 | ret = s3c2410_dma_request(prtd->params->channel, | 170 | ret = s3c2410_dma_request(prtd->params->channel, |
168 | prtd->params->client, NULL); | 171 | prtd->params->client, NULL); |
169 | 172 | ||
170 | if (ret) { | 173 | if (ret) { |
171 | DBG(KERN_ERR "failed to get dma channel\n"); | 174 | DBG(KERN_ERR "failed to get dma channel\n"); |
172 | return ret; | 175 | return ret; |
176 | } | ||
173 | } | 177 | } |
174 | 178 | ||
175 | /* channel needs configuring for mem=>device, increment memory addr, | 179 | /* channel needs configuring for mem=>device, increment memory addr, |
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 92d5d917b73b..91651bdfa761 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -1362,26 +1362,6 @@ int snd_soc_info_volsw_ext(struct snd_kcontrol *kcontrol, | |||
1362 | EXPORT_SYMBOL_GPL(snd_soc_info_volsw_ext); | 1362 | EXPORT_SYMBOL_GPL(snd_soc_info_volsw_ext); |
1363 | 1363 | ||
1364 | /** | 1364 | /** |
1365 | * snd_soc_info_bool_ext - external single boolean mixer info callback | ||
1366 | * @kcontrol: mixer control | ||
1367 | * @uinfo: control element information | ||
1368 | * | ||
1369 | * Callback to provide information about a single boolean external mixer control. | ||
1370 | * | ||
1371 | * Returns 0 for success. | ||
1372 | */ | ||
1373 | int snd_soc_info_bool_ext(struct snd_kcontrol *kcontrol, | ||
1374 | struct snd_ctl_elem_info *uinfo) | ||
1375 | { | ||
1376 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1377 | uinfo->count = 1; | ||
1378 | uinfo->value.integer.min = 0; | ||
1379 | uinfo->value.integer.max = 1; | ||
1380 | return 0; | ||
1381 | } | ||
1382 | EXPORT_SYMBOL_GPL(snd_soc_info_bool_ext); | ||
1383 | |||
1384 | /** | ||
1385 | * snd_soc_info_volsw - single mixer info callback | 1365 | * snd_soc_info_volsw - single mixer info callback |
1386 | * @kcontrol: mixer control | 1366 | * @kcontrol: mixer control |
1387 | * @uinfo: control element information | 1367 | * @uinfo: control element information |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 96bce55572a0..b3193e687db7 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -63,7 +63,7 @@ | |||
63 | #define POP_DEBUG 0 | 63 | #define POP_DEBUG 0 |
64 | #if POP_DEBUG | 64 | #if POP_DEBUG |
65 | #define POP_TIME 500 /* 500 msecs - change if pop debug is too fast */ | 65 | #define POP_TIME 500 /* 500 msecs - change if pop debug is too fast */ |
66 | #define pop_wait(time) schedule_timeout_interruptible(msecs_to_jiffies(time)) | 66 | #define pop_wait(time) schedule_timeout_uninterruptible(msecs_to_jiffies(time)) |
67 | #define pop_dbg(format, arg...) printk(format, ## arg); pop_wait(POP_TIME) | 67 | #define pop_dbg(format, arg...) printk(format, ## arg); pop_wait(POP_TIME) |
68 | #else | 68 | #else |
69 | #define pop_dbg(format, arg...) | 69 | #define pop_dbg(format, arg...) |
diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c index f2950cab74a6..9785382a5f39 100644 --- a/sound/sparc/cs4231.c +++ b/sound/sparc/cs4231.c | |||
@@ -3,9 +3,9 @@ | |||
3 | * Copyright (C) 2002 David S. Miller <davem@redhat.com> | 3 | * Copyright (C) 2002 David S. Miller <davem@redhat.com> |
4 | * | 4 | * |
5 | * Based entirely upon drivers/sbus/audio/cs4231.c which is: | 5 | * Based entirely upon drivers/sbus/audio/cs4231.c which is: |
6 | * Copyright (C) 1996, 1997, 1998, 1998 Derrick J Brashear (shadow@andrew.cmu.edu) | 6 | * Copyright (C) 1996, 1997, 1998 Derrick J Brashear (shadow@andrew.cmu.edu) |
7 | * and also sound/isa/cs423x/cs4231_lib.c which is: | 7 | * and also sound/isa/cs423x/cs4231_lib.c which is: |
8 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 8 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
@@ -15,6 +15,9 @@ | |||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
17 | #include <linux/moduleparam.h> | 17 | #include <linux/moduleparam.h> |
18 | #include <linux/irq.h> | ||
19 | #include <linux/io.h> | ||
20 | |||
18 | 21 | ||
19 | #include <sound/driver.h> | 22 | #include <sound/driver.h> |
20 | #include <sound/core.h> | 23 | #include <sound/core.h> |
@@ -25,29 +28,21 @@ | |||
25 | #include <sound/initval.h> | 28 | #include <sound/initval.h> |
26 | #include <sound/pcm_params.h> | 29 | #include <sound/pcm_params.h> |
27 | 30 | ||
28 | #include <asm/io.h> | ||
29 | #include <asm/irq.h> | ||
30 | |||
31 | #ifdef CONFIG_SBUS | 31 | #ifdef CONFIG_SBUS |
32 | #define SBUS_SUPPORT | 32 | #define SBUS_SUPPORT |
33 | #endif | ||
34 | |||
35 | #ifdef SBUS_SUPPORT | ||
36 | #include <asm/sbus.h> | 33 | #include <asm/sbus.h> |
37 | #endif | 34 | #endif |
38 | 35 | ||
39 | #if defined(CONFIG_PCI) && defined(CONFIG_SPARC64) | 36 | #if defined(CONFIG_PCI) && defined(CONFIG_SPARC64) |
40 | #define EBUS_SUPPORT | 37 | #define EBUS_SUPPORT |
41 | #endif | ||
42 | |||
43 | #ifdef EBUS_SUPPORT | ||
44 | #include <linux/pci.h> | 38 | #include <linux/pci.h> |
45 | #include <asm/ebus.h> | 39 | #include <asm/ebus.h> |
46 | #endif | 40 | #endif |
47 | 41 | ||
48 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ | 42 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ |
49 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ | 43 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ |
50 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ | 44 | /* Enable this card */ |
45 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; | ||
51 | 46 | ||
52 | module_param_array(index, int, NULL, 0444); | 47 | module_param_array(index, int, NULL, 0444); |
53 | MODULE_PARM_DESC(index, "Index value for Sun CS4231 soundcard."); | 48 | MODULE_PARM_DESC(index, "Index value for Sun CS4231 soundcard."); |
@@ -62,19 +57,22 @@ MODULE_SUPPORTED_DEVICE("{{Sun,CS4231}}"); | |||
62 | 57 | ||
63 | #ifdef SBUS_SUPPORT | 58 | #ifdef SBUS_SUPPORT |
64 | struct sbus_dma_info { | 59 | struct sbus_dma_info { |
65 | spinlock_t lock; | 60 | spinlock_t lock; /* DMA access lock */ |
66 | int dir; | 61 | int dir; |
67 | void __iomem *regs; | 62 | void __iomem *regs; |
68 | }; | 63 | }; |
69 | #endif | 64 | #endif |
70 | 65 | ||
71 | struct snd_cs4231; | 66 | struct snd_cs4231; |
72 | struct cs4231_dma_control { | 67 | struct cs4231_dma_control { |
73 | void (*prepare)(struct cs4231_dma_control *dma_cont, int dir); | 68 | void (*prepare)(struct cs4231_dma_control *dma_cont, |
74 | void (*enable)(struct cs4231_dma_control *dma_cont, int on); | 69 | int dir); |
75 | int (*request)(struct cs4231_dma_control *dma_cont, dma_addr_t bus_addr, size_t len); | 70 | void (*enable)(struct cs4231_dma_control *dma_cont, int on); |
76 | unsigned int (*address)(struct cs4231_dma_control *dma_cont); | 71 | int (*request)(struct cs4231_dma_control *dma_cont, |
77 | void (*preallocate)(struct snd_cs4231 *chip, struct snd_pcm *pcm); | 72 | dma_addr_t bus_addr, size_t len); |
73 | unsigned int (*address)(struct cs4231_dma_control *dma_cont); | ||
74 | void (*preallocate)(struct snd_cs4231 *chip, | ||
75 | struct snd_pcm *pcm); | ||
78 | #ifdef EBUS_SUPPORT | 76 | #ifdef EBUS_SUPPORT |
79 | struct ebus_dma_info ebus_info; | 77 | struct ebus_dma_info ebus_info; |
80 | #endif | 78 | #endif |
@@ -84,7 +82,7 @@ struct cs4231_dma_control { | |||
84 | }; | 82 | }; |
85 | 83 | ||
86 | struct snd_cs4231 { | 84 | struct snd_cs4231 { |
87 | spinlock_t lock; | 85 | spinlock_t lock; /* registers access lock */ |
88 | void __iomem *port; | 86 | void __iomem *port; |
89 | 87 | ||
90 | struct cs4231_dma_control p_dma; | 88 | struct cs4231_dma_control p_dma; |
@@ -108,13 +106,14 @@ struct snd_cs4231 { | |||
108 | #define CS4231_MODE_PLAY 0x0001 | 106 | #define CS4231_MODE_PLAY 0x0001 |
109 | #define CS4231_MODE_RECORD 0x0002 | 107 | #define CS4231_MODE_RECORD 0x0002 |
110 | #define CS4231_MODE_TIMER 0x0004 | 108 | #define CS4231_MODE_TIMER 0x0004 |
111 | #define CS4231_MODE_OPEN (CS4231_MODE_PLAY|CS4231_MODE_RECORD|CS4231_MODE_TIMER) | 109 | #define CS4231_MODE_OPEN (CS4231_MODE_PLAY | CS4231_MODE_RECORD | \ |
110 | CS4231_MODE_TIMER) | ||
112 | 111 | ||
113 | unsigned char image[32]; /* registers image */ | 112 | unsigned char image[32]; /* registers image */ |
114 | int mce_bit; | 113 | int mce_bit; |
115 | int calibrate_mute; | 114 | int calibrate_mute; |
116 | struct mutex mce_mutex; | 115 | struct mutex mce_mutex; /* mutex for mce register */ |
117 | struct mutex open_mutex; | 116 | struct mutex open_mutex; /* mutex for ALSA open/close */ |
118 | 117 | ||
119 | union { | 118 | union { |
120 | #ifdef SBUS_SUPPORT | 119 | #ifdef SBUS_SUPPORT |
@@ -136,129 +135,10 @@ static struct snd_cs4231 *cs4231_list; | |||
136 | */ | 135 | */ |
137 | 136 | ||
138 | /* IO ports */ | 137 | /* IO ports */ |
139 | 138 | #include <sound/cs4231-regs.h> | |
140 | #define CS4231P(chip, x) ((chip)->port + c_d_c_CS4231##x) | ||
141 | 139 | ||
142 | /* XXX offsets are different than PC ISA chips... */ | 140 | /* XXX offsets are different than PC ISA chips... */ |
143 | #define c_d_c_CS4231REGSEL 0x0 | 141 | #define CS4231U(chip, x) ((chip)->port + ((c_d_c_CS4231##x) << 2)) |
144 | #define c_d_c_CS4231REG 0x4 | ||
145 | #define c_d_c_CS4231STATUS 0x8 | ||
146 | #define c_d_c_CS4231PIO 0xc | ||
147 | |||
148 | /* codec registers */ | ||
149 | |||
150 | #define CS4231_LEFT_INPUT 0x00 /* left input control */ | ||
151 | #define CS4231_RIGHT_INPUT 0x01 /* right input control */ | ||
152 | #define CS4231_AUX1_LEFT_INPUT 0x02 /* left AUX1 input control */ | ||
153 | #define CS4231_AUX1_RIGHT_INPUT 0x03 /* right AUX1 input control */ | ||
154 | #define CS4231_AUX2_LEFT_INPUT 0x04 /* left AUX2 input control */ | ||
155 | #define CS4231_AUX2_RIGHT_INPUT 0x05 /* right AUX2 input control */ | ||
156 | #define CS4231_LEFT_OUTPUT 0x06 /* left output control register */ | ||
157 | #define CS4231_RIGHT_OUTPUT 0x07 /* right output control register */ | ||
158 | #define CS4231_PLAYBK_FORMAT 0x08 /* clock and data format - playback - bits 7-0 MCE */ | ||
159 | #define CS4231_IFACE_CTRL 0x09 /* interface control - bits 7-2 MCE */ | ||
160 | #define CS4231_PIN_CTRL 0x0a /* pin control */ | ||
161 | #define CS4231_TEST_INIT 0x0b /* test and initialization */ | ||
162 | #define CS4231_MISC_INFO 0x0c /* miscellaneaous information */ | ||
163 | #define CS4231_LOOPBACK 0x0d /* loopback control */ | ||
164 | #define CS4231_PLY_UPR_CNT 0x0e /* playback upper base count */ | ||
165 | #define CS4231_PLY_LWR_CNT 0x0f /* playback lower base count */ | ||
166 | #define CS4231_ALT_FEATURE_1 0x10 /* alternate #1 feature enable */ | ||
167 | #define CS4231_ALT_FEATURE_2 0x11 /* alternate #2 feature enable */ | ||
168 | #define CS4231_LEFT_LINE_IN 0x12 /* left line input control */ | ||
169 | #define CS4231_RIGHT_LINE_IN 0x13 /* right line input control */ | ||
170 | #define CS4231_TIMER_LOW 0x14 /* timer low byte */ | ||
171 | #define CS4231_TIMER_HIGH 0x15 /* timer high byte */ | ||
172 | #define CS4231_LEFT_MIC_INPUT 0x16 /* left MIC input control register (InterWave only) */ | ||
173 | #define CS4231_RIGHT_MIC_INPUT 0x17 /* right MIC input control register (InterWave only) */ | ||
174 | #define CS4236_EXT_REG 0x17 /* extended register access */ | ||
175 | #define CS4231_IRQ_STATUS 0x18 /* irq status register */ | ||
176 | #define CS4231_LINE_LEFT_OUTPUT 0x19 /* left line output control register (InterWave only) */ | ||
177 | #define CS4231_VERSION 0x19 /* CS4231(A) - version values */ | ||
178 | #define CS4231_MONO_CTRL 0x1a /* mono input/output control */ | ||
179 | #define CS4231_LINE_RIGHT_OUTPUT 0x1b /* right line output control register (InterWave only) */ | ||
180 | #define CS4235_LEFT_MASTER 0x1b /* left master output control */ | ||
181 | #define CS4231_REC_FORMAT 0x1c /* clock and data format - record - bits 7-0 MCE */ | ||
182 | #define CS4231_PLY_VAR_FREQ 0x1d /* playback variable frequency */ | ||
183 | #define CS4235_RIGHT_MASTER 0x1d /* right master output control */ | ||
184 | #define CS4231_REC_UPR_CNT 0x1e /* record upper count */ | ||
185 | #define CS4231_REC_LWR_CNT 0x1f /* record lower count */ | ||
186 | |||
187 | /* definitions for codec register select port - CODECP( REGSEL ) */ | ||
188 | |||
189 | #define CS4231_INIT 0x80 /* CODEC is initializing */ | ||
190 | #define CS4231_MCE 0x40 /* mode change enable */ | ||
191 | #define CS4231_TRD 0x20 /* transfer request disable */ | ||
192 | |||
193 | /* definitions for codec status register - CODECP( STATUS ) */ | ||
194 | |||
195 | #define CS4231_GLOBALIRQ 0x01 /* IRQ is active */ | ||
196 | |||
197 | /* definitions for codec irq status - CS4231_IRQ_STATUS */ | ||
198 | |||
199 | #define CS4231_PLAYBACK_IRQ 0x10 | ||
200 | #define CS4231_RECORD_IRQ 0x20 | ||
201 | #define CS4231_TIMER_IRQ 0x40 | ||
202 | #define CS4231_ALL_IRQS 0x70 | ||
203 | #define CS4231_REC_UNDERRUN 0x08 | ||
204 | #define CS4231_REC_OVERRUN 0x04 | ||
205 | #define CS4231_PLY_OVERRUN 0x02 | ||
206 | #define CS4231_PLY_UNDERRUN 0x01 | ||
207 | |||
208 | /* definitions for CS4231_LEFT_INPUT and CS4231_RIGHT_INPUT registers */ | ||
209 | |||
210 | #define CS4231_ENABLE_MIC_GAIN 0x20 | ||
211 | |||
212 | #define CS4231_MIXS_LINE 0x00 | ||
213 | #define CS4231_MIXS_AUX1 0x40 | ||
214 | #define CS4231_MIXS_MIC 0x80 | ||
215 | #define CS4231_MIXS_ALL 0xc0 | ||
216 | |||
217 | /* definitions for clock and data format register - CS4231_PLAYBK_FORMAT */ | ||
218 | |||
219 | #define CS4231_LINEAR_8 0x00 /* 8-bit unsigned data */ | ||
220 | #define CS4231_ALAW_8 0x60 /* 8-bit A-law companded */ | ||
221 | #define CS4231_ULAW_8 0x20 /* 8-bit U-law companded */ | ||
222 | #define CS4231_LINEAR_16 0x40 /* 16-bit twos complement data - little endian */ | ||
223 | #define CS4231_LINEAR_16_BIG 0xc0 /* 16-bit twos complement data - big endian */ | ||
224 | #define CS4231_ADPCM_16 0xa0 /* 16-bit ADPCM */ | ||
225 | #define CS4231_STEREO 0x10 /* stereo mode */ | ||
226 | /* bits 3-1 define frequency divisor */ | ||
227 | #define CS4231_XTAL1 0x00 /* 24.576 crystal */ | ||
228 | #define CS4231_XTAL2 0x01 /* 16.9344 crystal */ | ||
229 | |||
230 | /* definitions for interface control register - CS4231_IFACE_CTRL */ | ||
231 | |||
232 | #define CS4231_RECORD_PIO 0x80 /* record PIO enable */ | ||
233 | #define CS4231_PLAYBACK_PIO 0x40 /* playback PIO enable */ | ||
234 | #define CS4231_CALIB_MODE 0x18 /* calibration mode bits */ | ||
235 | #define CS4231_AUTOCALIB 0x08 /* auto calibrate */ | ||
236 | #define CS4231_SINGLE_DMA 0x04 /* use single DMA channel */ | ||
237 | #define CS4231_RECORD_ENABLE 0x02 /* record enable */ | ||
238 | #define CS4231_PLAYBACK_ENABLE 0x01 /* playback enable */ | ||
239 | |||
240 | /* definitions for pin control register - CS4231_PIN_CTRL */ | ||
241 | |||
242 | #define CS4231_IRQ_ENABLE 0x02 /* enable IRQ */ | ||
243 | #define CS4231_XCTL1 0x40 /* external control #1 */ | ||
244 | #define CS4231_XCTL0 0x80 /* external control #0 */ | ||
245 | |||
246 | /* definitions for test and init register - CS4231_TEST_INIT */ | ||
247 | |||
248 | #define CS4231_CALIB_IN_PROGRESS 0x20 /* auto calibrate in progress */ | ||
249 | #define CS4231_DMA_REQUEST 0x10 /* DMA request in progress */ | ||
250 | |||
251 | /* definitions for misc control register - CS4231_MISC_INFO */ | ||
252 | |||
253 | #define CS4231_MODE2 0x40 /* MODE 2 */ | ||
254 | #define CS4231_IW_MODE3 0x6c /* MODE 3 - InterWave enhanced mode */ | ||
255 | #define CS4231_4236_MODE3 0xe0 /* MODE 3 - CS4236+ enhanced mode */ | ||
256 | |||
257 | /* definitions for alternate feature 1 register - CS4231_ALT_FEATURE_1 */ | ||
258 | |||
259 | #define CS4231_DACZ 0x01 /* zero DAC when underrun */ | ||
260 | #define CS4231_TIMER_ENABLE 0x40 /* codec timer enable */ | ||
261 | #define CS4231_OLB 0x80 /* output level bit */ | ||
262 | 142 | ||
263 | /* SBUS DMA register defines. */ | 143 | /* SBUS DMA register defines. */ |
264 | 144 | ||
@@ -339,7 +219,7 @@ static unsigned int rates[14] = { | |||
339 | }; | 219 | }; |
340 | 220 | ||
341 | static struct snd_pcm_hw_constraint_list hw_constraints_rates = { | 221 | static struct snd_pcm_hw_constraint_list hw_constraints_rates = { |
342 | .count = 14, | 222 | .count = ARRAY_SIZE(rates), |
343 | .list = rates, | 223 | .list = rates, |
344 | }; | 224 | }; |
345 | 225 | ||
@@ -389,116 +269,89 @@ static unsigned char snd_cs4231_original_image[32] = | |||
389 | static u8 __cs4231_readb(struct snd_cs4231 *cp, void __iomem *reg_addr) | 269 | static u8 __cs4231_readb(struct snd_cs4231 *cp, void __iomem *reg_addr) |
390 | { | 270 | { |
391 | #ifdef EBUS_SUPPORT | 271 | #ifdef EBUS_SUPPORT |
392 | if (cp->flags & CS4231_FLAG_EBUS) { | 272 | if (cp->flags & CS4231_FLAG_EBUS) |
393 | return readb(reg_addr); | 273 | return readb(reg_addr); |
394 | } else { | 274 | else |
395 | #endif | 275 | #endif |
396 | #ifdef SBUS_SUPPORT | 276 | #ifdef SBUS_SUPPORT |
397 | return sbus_readb(reg_addr); | 277 | return sbus_readb(reg_addr); |
398 | #endif | 278 | #endif |
399 | #ifdef EBUS_SUPPORT | ||
400 | } | ||
401 | #endif | ||
402 | } | 279 | } |
403 | 280 | ||
404 | static void __cs4231_writeb(struct snd_cs4231 *cp, u8 val, void __iomem *reg_addr) | 281 | static void __cs4231_writeb(struct snd_cs4231 *cp, u8 val, |
282 | void __iomem *reg_addr) | ||
405 | { | 283 | { |
406 | #ifdef EBUS_SUPPORT | 284 | #ifdef EBUS_SUPPORT |
407 | if (cp->flags & CS4231_FLAG_EBUS) { | 285 | if (cp->flags & CS4231_FLAG_EBUS) |
408 | return writeb(val, reg_addr); | 286 | return writeb(val, reg_addr); |
409 | } else { | 287 | else |
410 | #endif | 288 | #endif |
411 | #ifdef SBUS_SUPPORT | 289 | #ifdef SBUS_SUPPORT |
412 | return sbus_writeb(val, reg_addr); | 290 | return sbus_writeb(val, reg_addr); |
413 | #endif | 291 | #endif |
414 | #ifdef EBUS_SUPPORT | ||
415 | } | ||
416 | #endif | ||
417 | } | 292 | } |
418 | 293 | ||
419 | /* | 294 | /* |
420 | * Basic I/O functions | 295 | * Basic I/O functions |
421 | */ | 296 | */ |
422 | 297 | ||
423 | static void snd_cs4231_outm(struct snd_cs4231 *chip, unsigned char reg, | 298 | static void snd_cs4231_ready(struct snd_cs4231 *chip) |
424 | unsigned char mask, unsigned char value) | ||
425 | { | 299 | { |
426 | int timeout; | 300 | int timeout; |
427 | unsigned char tmp; | ||
428 | 301 | ||
429 | for (timeout = 250; | 302 | for (timeout = 250; timeout > 0; timeout--) { |
430 | timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT); | 303 | int val = __cs4231_readb(chip, CS4231U(chip, REGSEL)); |
431 | timeout--) | 304 | if ((val & CS4231_INIT) == 0) |
432 | udelay(100); | 305 | break; |
433 | #ifdef CONFIG_SND_DEBUG | 306 | udelay(100); |
434 | if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) | ||
435 | snd_printdd("outm: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); | ||
436 | #endif | ||
437 | if (chip->calibrate_mute) { | ||
438 | chip->image[reg] &= mask; | ||
439 | chip->image[reg] |= value; | ||
440 | } else { | ||
441 | __cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL)); | ||
442 | mb(); | ||
443 | tmp = (chip->image[reg] & mask) | value; | ||
444 | __cs4231_writeb(chip, tmp, CS4231P(chip, REG)); | ||
445 | chip->image[reg] = tmp; | ||
446 | mb(); | ||
447 | } | 307 | } |
448 | } | 308 | } |
449 | 309 | ||
450 | static void snd_cs4231_dout(struct snd_cs4231 *chip, unsigned char reg, unsigned char value) | 310 | static void snd_cs4231_dout(struct snd_cs4231 *chip, unsigned char reg, |
311 | unsigned char value) | ||
451 | { | 312 | { |
452 | int timeout; | 313 | snd_cs4231_ready(chip); |
453 | |||
454 | for (timeout = 250; | ||
455 | timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT); | ||
456 | timeout--) | ||
457 | udelay(100); | ||
458 | #ifdef CONFIG_SND_DEBUG | 314 | #ifdef CONFIG_SND_DEBUG |
459 | if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) | 315 | if (__cs4231_readb(chip, CS4231U(chip, REGSEL)) & CS4231_INIT) |
460 | snd_printdd("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); | 316 | snd_printdd("out: auto calibration time out - reg = 0x%x, " |
317 | "value = 0x%x\n", | ||
318 | reg, value); | ||
461 | #endif | 319 | #endif |
462 | __cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL)); | 320 | __cs4231_writeb(chip, chip->mce_bit | reg, CS4231U(chip, REGSEL)); |
463 | __cs4231_writeb(chip, value, CS4231P(chip, REG)); | 321 | wmb(); |
322 | __cs4231_writeb(chip, value, CS4231U(chip, REG)); | ||
464 | mb(); | 323 | mb(); |
465 | } | 324 | } |
466 | 325 | ||
467 | static void snd_cs4231_out(struct snd_cs4231 *chip, unsigned char reg, unsigned char value) | 326 | static inline void snd_cs4231_outm(struct snd_cs4231 *chip, unsigned char reg, |
327 | unsigned char mask, unsigned char value) | ||
468 | { | 328 | { |
469 | int timeout; | 329 | unsigned char tmp = (chip->image[reg] & mask) | value; |
470 | 330 | ||
471 | for (timeout = 250; | 331 | chip->image[reg] = tmp; |
472 | timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT); | 332 | if (!chip->calibrate_mute) |
473 | timeout--) | 333 | snd_cs4231_dout(chip, reg, tmp); |
474 | udelay(100); | 334 | } |
475 | #ifdef CONFIG_SND_DEBUG | 335 | |
476 | if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) | 336 | static void snd_cs4231_out(struct snd_cs4231 *chip, unsigned char reg, |
477 | snd_printdd("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); | 337 | unsigned char value) |
478 | #endif | 338 | { |
479 | __cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL)); | 339 | snd_cs4231_dout(chip, reg, value); |
480 | __cs4231_writeb(chip, value, CS4231P(chip, REG)); | ||
481 | chip->image[reg] = value; | 340 | chip->image[reg] = value; |
482 | mb(); | 341 | mb(); |
483 | } | 342 | } |
484 | 343 | ||
485 | static unsigned char snd_cs4231_in(struct snd_cs4231 *chip, unsigned char reg) | 344 | static unsigned char snd_cs4231_in(struct snd_cs4231 *chip, unsigned char reg) |
486 | { | 345 | { |
487 | int timeout; | 346 | snd_cs4231_ready(chip); |
488 | unsigned char ret; | ||
489 | |||
490 | for (timeout = 250; | ||
491 | timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT); | ||
492 | timeout--) | ||
493 | udelay(100); | ||
494 | #ifdef CONFIG_SND_DEBUG | 347 | #ifdef CONFIG_SND_DEBUG |
495 | if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) | 348 | if (__cs4231_readb(chip, CS4231U(chip, REGSEL)) & CS4231_INIT) |
496 | snd_printdd("in: auto calibration time out - reg = 0x%x\n", reg); | 349 | snd_printdd("in: auto calibration time out - reg = 0x%x\n", |
350 | reg); | ||
497 | #endif | 351 | #endif |
498 | __cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL)); | 352 | __cs4231_writeb(chip, chip->mce_bit | reg, CS4231U(chip, REGSEL)); |
499 | mb(); | 353 | mb(); |
500 | ret = __cs4231_readb(chip, CS4231P(chip, REG)); | 354 | return __cs4231_readb(chip, CS4231U(chip, REG)); |
501 | return ret; | ||
502 | } | 355 | } |
503 | 356 | ||
504 | /* | 357 | /* |
@@ -509,15 +362,17 @@ static void snd_cs4231_busy_wait(struct snd_cs4231 *chip) | |||
509 | { | 362 | { |
510 | int timeout; | 363 | int timeout; |
511 | 364 | ||
512 | /* huh.. looks like this sequence is proper for CS4231A chip (GUS MAX) */ | 365 | /* looks like this sequence is proper for CS4231A chip (GUS MAX) */ |
513 | for (timeout = 5; timeout > 0; timeout--) | 366 | for (timeout = 5; timeout > 0; timeout--) |
514 | __cs4231_readb(chip, CS4231P(chip, REGSEL)); | 367 | __cs4231_readb(chip, CS4231U(chip, REGSEL)); |
515 | 368 | ||
516 | /* end of cleanup sequence */ | 369 | /* end of cleanup sequence */ |
517 | for (timeout = 500; | 370 | for (timeout = 500; timeout > 0; timeout--) { |
518 | timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT); | 371 | int val = __cs4231_readb(chip, CS4231U(chip, REGSEL)); |
519 | timeout--) | 372 | if ((val & CS4231_INIT) == 0) |
520 | udelay(1000); | 373 | break; |
374 | msleep(1); | ||
375 | } | ||
521 | } | 376 | } |
522 | 377 | ||
523 | static void snd_cs4231_mce_up(struct snd_cs4231 *chip) | 378 | static void snd_cs4231_mce_up(struct snd_cs4231 *chip) |
@@ -526,74 +381,81 @@ static void snd_cs4231_mce_up(struct snd_cs4231 *chip) | |||
526 | int timeout; | 381 | int timeout; |
527 | 382 | ||
528 | spin_lock_irqsave(&chip->lock, flags); | 383 | spin_lock_irqsave(&chip->lock, flags); |
529 | for (timeout = 250; timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT); timeout--) | 384 | snd_cs4231_ready(chip); |
530 | udelay(100); | ||
531 | #ifdef CONFIG_SND_DEBUG | 385 | #ifdef CONFIG_SND_DEBUG |
532 | if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) | 386 | if (__cs4231_readb(chip, CS4231U(chip, REGSEL)) & CS4231_INIT) |
533 | snd_printdd("mce_up - auto calibration time out (0)\n"); | 387 | snd_printdd("mce_up - auto calibration time out (0)\n"); |
534 | #endif | 388 | #endif |
535 | chip->mce_bit |= CS4231_MCE; | 389 | chip->mce_bit |= CS4231_MCE; |
536 | timeout = __cs4231_readb(chip, CS4231P(chip, REGSEL)); | 390 | timeout = __cs4231_readb(chip, CS4231U(chip, REGSEL)); |
537 | if (timeout == 0x80) | 391 | if (timeout == 0x80) |
538 | snd_printdd("mce_up [%p]: serious init problem - codec still busy\n", chip->port); | 392 | snd_printdd("mce_up [%p]: serious init problem - " |
393 | "codec still busy\n", | ||
394 | chip->port); | ||
539 | if (!(timeout & CS4231_MCE)) | 395 | if (!(timeout & CS4231_MCE)) |
540 | __cs4231_writeb(chip, chip->mce_bit | (timeout & 0x1f), CS4231P(chip, REGSEL)); | 396 | __cs4231_writeb(chip, chip->mce_bit | (timeout & 0x1f), |
397 | CS4231U(chip, REGSEL)); | ||
541 | spin_unlock_irqrestore(&chip->lock, flags); | 398 | spin_unlock_irqrestore(&chip->lock, flags); |
542 | } | 399 | } |
543 | 400 | ||
544 | static void snd_cs4231_mce_down(struct snd_cs4231 *chip) | 401 | static void snd_cs4231_mce_down(struct snd_cs4231 *chip) |
545 | { | 402 | { |
546 | unsigned long flags; | 403 | unsigned long flags; |
404 | unsigned long end_time; | ||
547 | int timeout; | 405 | int timeout; |
548 | 406 | ||
549 | spin_lock_irqsave(&chip->lock, flags); | 407 | spin_lock_irqsave(&chip->lock, flags); |
550 | snd_cs4231_busy_wait(chip); | 408 | snd_cs4231_busy_wait(chip); |
551 | #ifdef CONFIG_SND_DEBUG | 409 | #ifdef CONFIG_SND_DEBUG |
552 | if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) | 410 | if (__cs4231_readb(chip, CS4231U(chip, REGSEL)) & CS4231_INIT) |
553 | snd_printdd("mce_down [%p] - auto calibration time out (0)\n", CS4231P(chip, REGSEL)); | 411 | snd_printdd("mce_down [%p] - auto calibration time out (0)\n", |
412 | CS4231U(chip, REGSEL)); | ||
554 | #endif | 413 | #endif |
555 | chip->mce_bit &= ~CS4231_MCE; | 414 | chip->mce_bit &= ~CS4231_MCE; |
556 | timeout = __cs4231_readb(chip, CS4231P(chip, REGSEL)); | 415 | timeout = __cs4231_readb(chip, CS4231U(chip, REGSEL)); |
557 | __cs4231_writeb(chip, chip->mce_bit | (timeout & 0x1f), CS4231P(chip, REGSEL)); | 416 | __cs4231_writeb(chip, chip->mce_bit | (timeout & 0x1f), |
417 | CS4231U(chip, REGSEL)); | ||
558 | if (timeout == 0x80) | 418 | if (timeout == 0x80) |
559 | snd_printdd("mce_down [%p]: serious init problem - codec still busy\n", chip->port); | 419 | snd_printdd("mce_down [%p]: serious init problem - " |
420 | "codec still busy\n", | ||
421 | chip->port); | ||
560 | if ((timeout & CS4231_MCE) == 0) { | 422 | if ((timeout & CS4231_MCE) == 0) { |
561 | spin_unlock_irqrestore(&chip->lock, flags); | 423 | spin_unlock_irqrestore(&chip->lock, flags); |
562 | return; | 424 | return; |
563 | } | 425 | } |
564 | snd_cs4231_busy_wait(chip); | ||
565 | 426 | ||
566 | /* calibration process */ | 427 | /* |
428 | * Wait for (possible -- during init auto-calibration may not be set) | ||
429 | * calibration process to start. Needs upto 5 sample periods on AD1848 | ||
430 | * which at the slowest possible rate of 5.5125 kHz means 907 us. | ||
431 | */ | ||
432 | msleep(1); | ||
567 | 433 | ||
568 | for (timeout = 500; timeout > 0 && (snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) == 0; timeout--) | 434 | /* check condition up to 250ms */ |
569 | udelay(100); | 435 | end_time = jiffies + msecs_to_jiffies(250); |
570 | if ((snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) == 0) { | 436 | while (snd_cs4231_in(chip, CS4231_TEST_INIT) & |
571 | snd_printd("cs4231_mce_down - auto calibration time out (1)\n"); | 437 | CS4231_CALIB_IN_PROGRESS) { |
572 | spin_unlock_irqrestore(&chip->lock, flags); | ||
573 | return; | ||
574 | } | ||
575 | 438 | ||
576 | /* in 10ms increments, check condition, up to 250ms */ | ||
577 | timeout = 25; | ||
578 | while (snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) { | ||
579 | spin_unlock_irqrestore(&chip->lock, flags); | 439 | spin_unlock_irqrestore(&chip->lock, flags); |
580 | if (--timeout < 0) { | 440 | if (time_after(jiffies, end_time)) { |
581 | snd_printk("mce_down - auto calibration time out (2)\n"); | 441 | snd_printk("mce_down - " |
442 | "auto calibration time out (2)\n"); | ||
582 | return; | 443 | return; |
583 | } | 444 | } |
584 | msleep(10); | 445 | msleep(1); |
585 | spin_lock_irqsave(&chip->lock, flags); | 446 | spin_lock_irqsave(&chip->lock, flags); |
586 | } | 447 | } |
587 | 448 | ||
588 | /* in 10ms increments, check condition, up to 100ms */ | 449 | /* check condition up to 100ms */ |
589 | timeout = 10; | 450 | end_time = jiffies + msecs_to_jiffies(100); |
590 | while (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) { | 451 | while (__cs4231_readb(chip, CS4231U(chip, REGSEL)) & CS4231_INIT) { |
591 | spin_unlock_irqrestore(&chip->lock, flags); | 452 | spin_unlock_irqrestore(&chip->lock, flags); |
592 | if (--timeout < 0) { | 453 | if (time_after(jiffies, end_time)) { |
593 | snd_printk("mce_down - auto calibration time out (3)\n"); | 454 | snd_printk("mce_down - " |
455 | "auto calibration time out (3)\n"); | ||
594 | return; | 456 | return; |
595 | } | 457 | } |
596 | msleep(10); | 458 | msleep(1); |
597 | spin_lock_irqsave(&chip->lock, flags); | 459 | spin_lock_irqsave(&chip->lock, flags); |
598 | } | 460 | } |
599 | spin_unlock_irqrestore(&chip->lock, flags); | 461 | spin_unlock_irqrestore(&chip->lock, flags); |
@@ -611,7 +473,8 @@ static void snd_cs4231_advance_dma(struct cs4231_dma_control *dma_cont, | |||
611 | 473 | ||
612 | BUG_ON(period_size >= (1 << 24)); | 474 | BUG_ON(period_size >= (1 << 24)); |
613 | 475 | ||
614 | if (dma_cont->request(dma_cont, runtime->dma_addr + offset, period_size)) | 476 | if (dma_cont->request(dma_cont, |
477 | runtime->dma_addr + offset, period_size)) | ||
615 | return; | 478 | return; |
616 | (*periods_sent) = ((*periods_sent) + 1) % runtime->periods; | 479 | (*periods_sent) = ((*periods_sent) + 1) % runtime->periods; |
617 | } | 480 | } |
@@ -704,21 +567,32 @@ static unsigned char snd_cs4231_get_rate(unsigned int rate) | |||
704 | for (i = 0; i < 14; i++) | 567 | for (i = 0; i < 14; i++) |
705 | if (rate == rates[i]) | 568 | if (rate == rates[i]) |
706 | return freq_bits[i]; | 569 | return freq_bits[i]; |
707 | // snd_BUG(); | 570 | |
708 | return freq_bits[13]; | 571 | return freq_bits[13]; |
709 | } | 572 | } |
710 | 573 | ||
711 | static unsigned char snd_cs4231_get_format(struct snd_cs4231 *chip, int format, int channels) | 574 | static unsigned char snd_cs4231_get_format(struct snd_cs4231 *chip, int format, |
575 | int channels) | ||
712 | { | 576 | { |
713 | unsigned char rformat; | 577 | unsigned char rformat; |
714 | 578 | ||
715 | rformat = CS4231_LINEAR_8; | 579 | rformat = CS4231_LINEAR_8; |
716 | switch (format) { | 580 | switch (format) { |
717 | case SNDRV_PCM_FORMAT_MU_LAW: rformat = CS4231_ULAW_8; break; | 581 | case SNDRV_PCM_FORMAT_MU_LAW: |
718 | case SNDRV_PCM_FORMAT_A_LAW: rformat = CS4231_ALAW_8; break; | 582 | rformat = CS4231_ULAW_8; |
719 | case SNDRV_PCM_FORMAT_S16_LE: rformat = CS4231_LINEAR_16; break; | 583 | break; |
720 | case SNDRV_PCM_FORMAT_S16_BE: rformat = CS4231_LINEAR_16_BIG; break; | 584 | case SNDRV_PCM_FORMAT_A_LAW: |
721 | case SNDRV_PCM_FORMAT_IMA_ADPCM: rformat = CS4231_ADPCM_16; break; | 585 | rformat = CS4231_ALAW_8; |
586 | break; | ||
587 | case SNDRV_PCM_FORMAT_S16_LE: | ||
588 | rformat = CS4231_LINEAR_16; | ||
589 | break; | ||
590 | case SNDRV_PCM_FORMAT_S16_BE: | ||
591 | rformat = CS4231_LINEAR_16_BIG; | ||
592 | break; | ||
593 | case SNDRV_PCM_FORMAT_IMA_ADPCM: | ||
594 | rformat = CS4231_ADPCM_16; | ||
595 | break; | ||
722 | } | 596 | } |
723 | if (channels > 1) | 597 | if (channels > 1) |
724 | rformat |= CS4231_STEREO; | 598 | rformat |= CS4231_STEREO; |
@@ -765,7 +639,8 @@ static void snd_cs4231_calibrate_mute(struct snd_cs4231 *chip, int mute) | |||
765 | spin_unlock_irqrestore(&chip->lock, flags); | 639 | spin_unlock_irqrestore(&chip->lock, flags); |
766 | } | 640 | } |
767 | 641 | ||
768 | static void snd_cs4231_playback_format(struct snd_cs4231 *chip, struct snd_pcm_hw_params *params, | 642 | static void snd_cs4231_playback_format(struct snd_cs4231 *chip, |
643 | struct snd_pcm_hw_params *params, | ||
769 | unsigned char pdfr) | 644 | unsigned char pdfr) |
770 | { | 645 | { |
771 | unsigned long flags; | 646 | unsigned long flags; |
@@ -788,8 +663,9 @@ static void snd_cs4231_playback_format(struct snd_cs4231 *chip, struct snd_pcm_h | |||
788 | mutex_unlock(&chip->mce_mutex); | 663 | mutex_unlock(&chip->mce_mutex); |
789 | } | 664 | } |
790 | 665 | ||
791 | static void snd_cs4231_capture_format(struct snd_cs4231 *chip, struct snd_pcm_hw_params *params, | 666 | static void snd_cs4231_capture_format(struct snd_cs4231 *chip, |
792 | unsigned char cdfr) | 667 | struct snd_pcm_hw_params *params, |
668 | unsigned char cdfr) | ||
793 | { | 669 | { |
794 | unsigned long flags; | 670 | unsigned long flags; |
795 | 671 | ||
@@ -846,7 +722,8 @@ static int snd_cs4231_timer_start(struct snd_timer *timer) | |||
846 | chip->image[CS4231_TIMER_LOW] = | 722 | chip->image[CS4231_TIMER_LOW] = |
847 | (unsigned char) ticks); | 723 | (unsigned char) ticks); |
848 | snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, | 724 | snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, |
849 | chip->image[CS4231_ALT_FEATURE_1] | CS4231_TIMER_ENABLE); | 725 | chip->image[CS4231_ALT_FEATURE_1] | |
726 | CS4231_TIMER_ENABLE); | ||
850 | } | 727 | } |
851 | spin_unlock_irqrestore(&chip->lock, flags); | 728 | spin_unlock_irqrestore(&chip->lock, flags); |
852 | 729 | ||
@@ -859,8 +736,9 @@ static int snd_cs4231_timer_stop(struct snd_timer *timer) | |||
859 | struct snd_cs4231 *chip = snd_timer_chip(timer); | 736 | struct snd_cs4231 *chip = snd_timer_chip(timer); |
860 | 737 | ||
861 | spin_lock_irqsave(&chip->lock, flags); | 738 | spin_lock_irqsave(&chip->lock, flags); |
739 | chip->image[CS4231_ALT_FEATURE_1] &= ~CS4231_TIMER_ENABLE; | ||
862 | snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, | 740 | snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, |
863 | chip->image[CS4231_ALT_FEATURE_1] &= ~CS4231_TIMER_ENABLE); | 741 | chip->image[CS4231_ALT_FEATURE_1]); |
864 | spin_unlock_irqrestore(&chip->lock, flags); | 742 | spin_unlock_irqrestore(&chip->lock, flags); |
865 | 743 | ||
866 | return 0; | 744 | return 0; |
@@ -877,8 +755,10 @@ static void __init snd_cs4231_init(struct snd_cs4231 *chip) | |||
877 | #endif | 755 | #endif |
878 | snd_cs4231_mce_up(chip); | 756 | snd_cs4231_mce_up(chip); |
879 | spin_lock_irqsave(&chip->lock, flags); | 757 | spin_lock_irqsave(&chip->lock, flags); |
880 | chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO | | 758 | chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | |
881 | CS4231_RECORD_ENABLE | CS4231_RECORD_PIO | | 759 | CS4231_PLAYBACK_PIO | |
760 | CS4231_RECORD_ENABLE | | ||
761 | CS4231_RECORD_PIO | | ||
882 | CS4231_CALIB_MODE); | 762 | CS4231_CALIB_MODE); |
883 | chip->image[CS4231_IFACE_CTRL] |= CS4231_AUTOCALIB; | 763 | chip->image[CS4231_IFACE_CTRL] |= CS4231_AUTOCALIB; |
884 | snd_cs4231_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]); | 764 | snd_cs4231_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]); |
@@ -891,21 +771,25 @@ static void __init snd_cs4231_init(struct snd_cs4231 *chip) | |||
891 | 771 | ||
892 | snd_cs4231_mce_up(chip); | 772 | snd_cs4231_mce_up(chip); |
893 | spin_lock_irqsave(&chip->lock, flags); | 773 | spin_lock_irqsave(&chip->lock, flags); |
894 | snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1]); | 774 | snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, |
775 | chip->image[CS4231_ALT_FEATURE_1]); | ||
895 | spin_unlock_irqrestore(&chip->lock, flags); | 776 | spin_unlock_irqrestore(&chip->lock, flags); |
896 | snd_cs4231_mce_down(chip); | 777 | snd_cs4231_mce_down(chip); |
897 | 778 | ||
898 | #ifdef SNDRV_DEBUG_MCE | 779 | #ifdef SNDRV_DEBUG_MCE |
899 | snd_printdd("init: (3) - afei = 0x%x\n", chip->image[CS4231_ALT_FEATURE_1]); | 780 | snd_printdd("init: (3) - afei = 0x%x\n", |
781 | chip->image[CS4231_ALT_FEATURE_1]); | ||
900 | #endif | 782 | #endif |
901 | 783 | ||
902 | spin_lock_irqsave(&chip->lock, flags); | 784 | spin_lock_irqsave(&chip->lock, flags); |
903 | snd_cs4231_out(chip, CS4231_ALT_FEATURE_2, chip->image[CS4231_ALT_FEATURE_2]); | 785 | snd_cs4231_out(chip, CS4231_ALT_FEATURE_2, |
786 | chip->image[CS4231_ALT_FEATURE_2]); | ||
904 | spin_unlock_irqrestore(&chip->lock, flags); | 787 | spin_unlock_irqrestore(&chip->lock, flags); |
905 | 788 | ||
906 | snd_cs4231_mce_up(chip); | 789 | snd_cs4231_mce_up(chip); |
907 | spin_lock_irqsave(&chip->lock, flags); | 790 | spin_lock_irqsave(&chip->lock, flags); |
908 | snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, chip->image[CS4231_PLAYBK_FORMAT]); | 791 | snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, |
792 | chip->image[CS4231_PLAYBK_FORMAT]); | ||
909 | spin_unlock_irqrestore(&chip->lock, flags); | 793 | spin_unlock_irqrestore(&chip->lock, flags); |
910 | snd_cs4231_mce_down(chip); | 794 | snd_cs4231_mce_down(chip); |
911 | 795 | ||
@@ -944,8 +828,8 @@ static int snd_cs4231_open(struct snd_cs4231 *chip, unsigned int mode) | |||
944 | CS4231_RECORD_IRQ | | 828 | CS4231_RECORD_IRQ | |
945 | CS4231_TIMER_IRQ); | 829 | CS4231_TIMER_IRQ); |
946 | snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0); | 830 | snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0); |
947 | __cs4231_writeb(chip, 0, CS4231P(chip, STATUS)); /* clear IRQ */ | 831 | __cs4231_writeb(chip, 0, CS4231U(chip, STATUS)); /* clear IRQ */ |
948 | __cs4231_writeb(chip, 0, CS4231P(chip, STATUS)); /* clear IRQ */ | 832 | __cs4231_writeb(chip, 0, CS4231U(chip, STATUS)); /* clear IRQ */ |
949 | 833 | ||
950 | snd_cs4231_out(chip, CS4231_IRQ_STATUS, CS4231_PLAYBACK_IRQ | | 834 | snd_cs4231_out(chip, CS4231_IRQ_STATUS, CS4231_PLAYBACK_IRQ | |
951 | CS4231_RECORD_IRQ | | 835 | CS4231_RECORD_IRQ | |
@@ -974,8 +858,8 @@ static void snd_cs4231_close(struct snd_cs4231 *chip, unsigned int mode) | |||
974 | /* disable IRQ */ | 858 | /* disable IRQ */ |
975 | spin_lock_irqsave(&chip->lock, flags); | 859 | spin_lock_irqsave(&chip->lock, flags); |
976 | snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0); | 860 | snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0); |
977 | __cs4231_writeb(chip, 0, CS4231P(chip, STATUS)); /* clear IRQ */ | 861 | __cs4231_writeb(chip, 0, CS4231U(chip, STATUS)); /* clear IRQ */ |
978 | __cs4231_writeb(chip, 0, CS4231P(chip, STATUS)); /* clear IRQ */ | 862 | __cs4231_writeb(chip, 0, CS4231U(chip, STATUS)); /* clear IRQ */ |
979 | 863 | ||
980 | /* now disable record & playback */ | 864 | /* now disable record & playback */ |
981 | 865 | ||
@@ -988,7 +872,8 @@ static void snd_cs4231_close(struct snd_cs4231 *chip, unsigned int mode) | |||
988 | chip->image[CS4231_IFACE_CTRL] &= | 872 | chip->image[CS4231_IFACE_CTRL] &= |
989 | ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO | | 873 | ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO | |
990 | CS4231_RECORD_ENABLE | CS4231_RECORD_PIO); | 874 | CS4231_RECORD_ENABLE | CS4231_RECORD_PIO); |
991 | snd_cs4231_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]); | 875 | snd_cs4231_out(chip, CS4231_IFACE_CTRL, |
876 | chip->image[CS4231_IFACE_CTRL]); | ||
992 | spin_unlock_irqrestore(&chip->lock, flags); | 877 | spin_unlock_irqrestore(&chip->lock, flags); |
993 | snd_cs4231_mce_down(chip); | 878 | snd_cs4231_mce_down(chip); |
994 | spin_lock_irqsave(&chip->lock, flags); | 879 | spin_lock_irqsave(&chip->lock, flags); |
@@ -996,8 +881,8 @@ static void snd_cs4231_close(struct snd_cs4231 *chip, unsigned int mode) | |||
996 | 881 | ||
997 | /* clear IRQ again */ | 882 | /* clear IRQ again */ |
998 | snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0); | 883 | snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0); |
999 | __cs4231_writeb(chip, 0, CS4231P(chip, STATUS)); /* clear IRQ */ | 884 | __cs4231_writeb(chip, 0, CS4231U(chip, STATUS)); /* clear IRQ */ |
1000 | __cs4231_writeb(chip, 0, CS4231P(chip, STATUS)); /* clear IRQ */ | 885 | __cs4231_writeb(chip, 0, CS4231U(chip, STATUS)); /* clear IRQ */ |
1001 | spin_unlock_irqrestore(&chip->lock, flags); | 886 | spin_unlock_irqrestore(&chip->lock, flags); |
1002 | 887 | ||
1003 | snd_cs4231_calibrate_mute(chip, 0); | 888 | snd_cs4231_calibrate_mute(chip, 0); |
@@ -1017,15 +902,14 @@ static int snd_cs4231_timer_open(struct snd_timer *timer) | |||
1017 | return 0; | 902 | return 0; |
1018 | } | 903 | } |
1019 | 904 | ||
1020 | static int snd_cs4231_timer_close(struct snd_timer * timer) | 905 | static int snd_cs4231_timer_close(struct snd_timer *timer) |
1021 | { | 906 | { |
1022 | struct snd_cs4231 *chip = snd_timer_chip(timer); | 907 | struct snd_cs4231 *chip = snd_timer_chip(timer); |
1023 | snd_cs4231_close(chip, CS4231_MODE_TIMER); | 908 | snd_cs4231_close(chip, CS4231_MODE_TIMER); |
1024 | return 0; | 909 | return 0; |
1025 | } | 910 | } |
1026 | 911 | ||
1027 | static struct snd_timer_hardware snd_cs4231_timer_table = | 912 | static struct snd_timer_hardware snd_cs4231_timer_table = { |
1028 | { | ||
1029 | .flags = SNDRV_TIMER_HW_AUTO, | 913 | .flags = SNDRV_TIMER_HW_AUTO, |
1030 | .resolution = 9945, | 914 | .resolution = 9945, |
1031 | .ticks = 65535, | 915 | .ticks = 65535, |
@@ -1047,8 +931,9 @@ static int snd_cs4231_playback_hw_params(struct snd_pcm_substream *substream, | |||
1047 | unsigned char new_pdfr; | 931 | unsigned char new_pdfr; |
1048 | int err; | 932 | int err; |
1049 | 933 | ||
1050 | if ((err = snd_pcm_lib_malloc_pages(substream, | 934 | err = snd_pcm_lib_malloc_pages(substream, |
1051 | params_buffer_bytes(hw_params))) < 0) | 935 | params_buffer_bytes(hw_params)); |
936 | if (err < 0) | ||
1052 | return err; | 937 | return err; |
1053 | new_pdfr = snd_cs4231_get_format(chip, params_format(hw_params), | 938 | new_pdfr = snd_cs4231_get_format(chip, params_format(hw_params), |
1054 | params_channels(hw_params)) | | 939 | params_channels(hw_params)) | |
@@ -1058,11 +943,6 @@ static int snd_cs4231_playback_hw_params(struct snd_pcm_substream *substream, | |||
1058 | return 0; | 943 | return 0; |
1059 | } | 944 | } |
1060 | 945 | ||
1061 | static int snd_cs4231_playback_hw_free(struct snd_pcm_substream *substream) | ||
1062 | { | ||
1063 | return snd_pcm_lib_free_pages(substream); | ||
1064 | } | ||
1065 | |||
1066 | static int snd_cs4231_playback_prepare(struct snd_pcm_substream *substream) | 946 | static int snd_cs4231_playback_prepare(struct snd_pcm_substream *substream) |
1067 | { | 947 | { |
1068 | struct snd_cs4231 *chip = snd_pcm_substream_chip(substream); | 948 | struct snd_cs4231 *chip = snd_pcm_substream_chip(substream); |
@@ -1089,8 +969,9 @@ static int snd_cs4231_capture_hw_params(struct snd_pcm_substream *substream, | |||
1089 | unsigned char new_cdfr; | 969 | unsigned char new_cdfr; |
1090 | int err; | 970 | int err; |
1091 | 971 | ||
1092 | if ((err = snd_pcm_lib_malloc_pages(substream, | 972 | err = snd_pcm_lib_malloc_pages(substream, |
1093 | params_buffer_bytes(hw_params))) < 0) | 973 | params_buffer_bytes(hw_params)); |
974 | if (err < 0) | ||
1094 | return err; | 975 | return err; |
1095 | new_cdfr = snd_cs4231_get_format(chip, params_format(hw_params), | 976 | new_cdfr = snd_cs4231_get_format(chip, params_format(hw_params), |
1096 | params_channels(hw_params)) | | 977 | params_channels(hw_params)) | |
@@ -1100,11 +981,6 @@ static int snd_cs4231_capture_hw_params(struct snd_pcm_substream *substream, | |||
1100 | return 0; | 981 | return 0; |
1101 | } | 982 | } |
1102 | 983 | ||
1103 | static int snd_cs4231_capture_hw_free(struct snd_pcm_substream *substream) | ||
1104 | { | ||
1105 | return snd_pcm_lib_free_pages(substream); | ||
1106 | } | ||
1107 | |||
1108 | static int snd_cs4231_capture_prepare(struct snd_pcm_substream *substream) | 984 | static int snd_cs4231_capture_prepare(struct snd_pcm_substream *substream) |
1109 | { | 985 | { |
1110 | struct snd_cs4231 *chip = snd_pcm_substream_chip(substream); | 986 | struct snd_cs4231 *chip = snd_pcm_substream_chip(substream); |
@@ -1130,7 +1006,8 @@ static void snd_cs4231_overrange(struct snd_cs4231 *chip) | |||
1130 | res = snd_cs4231_in(chip, CS4231_TEST_INIT); | 1006 | res = snd_cs4231_in(chip, CS4231_TEST_INIT); |
1131 | spin_unlock_irqrestore(&chip->lock, flags); | 1007 | spin_unlock_irqrestore(&chip->lock, flags); |
1132 | 1008 | ||
1133 | if (res & (0x08 | 0x02)) /* detect overrange only above 0dB; may be user selectable? */ | 1009 | /* detect overrange only above 0dB; may be user selectable? */ |
1010 | if (res & (0x08 | 0x02)) | ||
1134 | chip->capture_substream->runtime->overrange++; | 1011 | chip->capture_substream->runtime->overrange++; |
1135 | } | 1012 | } |
1136 | 1013 | ||
@@ -1152,51 +1029,50 @@ static void snd_cs4231_capture_callback(struct snd_cs4231 *chip) | |||
1152 | } | 1029 | } |
1153 | } | 1030 | } |
1154 | 1031 | ||
1155 | static snd_pcm_uframes_t snd_cs4231_playback_pointer(struct snd_pcm_substream *substream) | 1032 | static snd_pcm_uframes_t snd_cs4231_playback_pointer( |
1033 | struct snd_pcm_substream *substream) | ||
1156 | { | 1034 | { |
1157 | struct snd_cs4231 *chip = snd_pcm_substream_chip(substream); | 1035 | struct snd_cs4231 *chip = snd_pcm_substream_chip(substream); |
1158 | struct cs4231_dma_control *dma_cont = &chip->p_dma; | 1036 | struct cs4231_dma_control *dma_cont = &chip->p_dma; |
1159 | size_t ptr; | 1037 | size_t ptr; |
1160 | 1038 | ||
1161 | if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE)) | 1039 | if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE)) |
1162 | return 0; | 1040 | return 0; |
1163 | ptr = dma_cont->address(dma_cont); | 1041 | ptr = dma_cont->address(dma_cont); |
1164 | if (ptr != 0) | 1042 | if (ptr != 0) |
1165 | ptr -= substream->runtime->dma_addr; | 1043 | ptr -= substream->runtime->dma_addr; |
1166 | 1044 | ||
1167 | return bytes_to_frames(substream->runtime, ptr); | 1045 | return bytes_to_frames(substream->runtime, ptr); |
1168 | } | 1046 | } |
1169 | 1047 | ||
1170 | static snd_pcm_uframes_t snd_cs4231_capture_pointer(struct snd_pcm_substream *substream) | 1048 | static snd_pcm_uframes_t snd_cs4231_capture_pointer( |
1049 | struct snd_pcm_substream *substream) | ||
1171 | { | 1050 | { |
1172 | struct snd_cs4231 *chip = snd_pcm_substream_chip(substream); | 1051 | struct snd_cs4231 *chip = snd_pcm_substream_chip(substream); |
1173 | struct cs4231_dma_control *dma_cont = &chip->c_dma; | 1052 | struct cs4231_dma_control *dma_cont = &chip->c_dma; |
1174 | size_t ptr; | 1053 | size_t ptr; |
1175 | 1054 | ||
1176 | if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE)) | 1055 | if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE)) |
1177 | return 0; | 1056 | return 0; |
1178 | ptr = dma_cont->address(dma_cont); | 1057 | ptr = dma_cont->address(dma_cont); |
1179 | if (ptr != 0) | 1058 | if (ptr != 0) |
1180 | ptr -= substream->runtime->dma_addr; | 1059 | ptr -= substream->runtime->dma_addr; |
1181 | 1060 | ||
1182 | return bytes_to_frames(substream->runtime, ptr); | 1061 | return bytes_to_frames(substream->runtime, ptr); |
1183 | } | 1062 | } |
1184 | 1063 | ||
1185 | /* | ||
1186 | |||
1187 | */ | ||
1188 | |||
1189 | static int __init snd_cs4231_probe(struct snd_cs4231 *chip) | 1064 | static int __init snd_cs4231_probe(struct snd_cs4231 *chip) |
1190 | { | 1065 | { |
1191 | unsigned long flags; | 1066 | unsigned long flags; |
1192 | int i, id, vers; | 1067 | int i; |
1068 | int id = 0; | ||
1069 | int vers = 0; | ||
1193 | unsigned char *ptr; | 1070 | unsigned char *ptr; |
1194 | 1071 | ||
1195 | id = vers = 0; | ||
1196 | for (i = 0; i < 50; i++) { | 1072 | for (i = 0; i < 50; i++) { |
1197 | mb(); | 1073 | mb(); |
1198 | if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) | 1074 | if (__cs4231_readb(chip, CS4231U(chip, REGSEL)) & CS4231_INIT) |
1199 | udelay(2000); | 1075 | msleep(2); |
1200 | else { | 1076 | else { |
1201 | spin_lock_irqsave(&chip->lock, flags); | 1077 | spin_lock_irqsave(&chip->lock, flags); |
1202 | snd_cs4231_out(chip, CS4231_MISC_INFO, CS4231_MODE2); | 1078 | snd_cs4231_out(chip, CS4231_MISC_INFO, CS4231_MODE2); |
@@ -1213,8 +1089,9 @@ static int __init snd_cs4231_probe(struct snd_cs4231 *chip) | |||
1213 | 1089 | ||
1214 | spin_lock_irqsave(&chip->lock, flags); | 1090 | spin_lock_irqsave(&chip->lock, flags); |
1215 | 1091 | ||
1216 | __cs4231_readb(chip, CS4231P(chip, STATUS)); /* clear any pendings IRQ */ | 1092 | /* clear any pendings IRQ */ |
1217 | __cs4231_writeb(chip, 0, CS4231P(chip, STATUS)); | 1093 | __cs4231_readb(chip, CS4231U(chip, STATUS)); |
1094 | __cs4231_writeb(chip, 0, CS4231U(chip, STATUS)); | ||
1218 | mb(); | 1095 | mb(); |
1219 | 1096 | ||
1220 | spin_unlock_irqrestore(&chip->lock, flags); | 1097 | spin_unlock_irqrestore(&chip->lock, flags); |
@@ -1247,42 +1124,50 @@ static int __init snd_cs4231_probe(struct snd_cs4231 *chip) | |||
1247 | return 0; /* all things are ok.. */ | 1124 | return 0; /* all things are ok.. */ |
1248 | } | 1125 | } |
1249 | 1126 | ||
1250 | static struct snd_pcm_hardware snd_cs4231_playback = | 1127 | static struct snd_pcm_hardware snd_cs4231_playback = { |
1251 | { | 1128 | .info = SNDRV_PCM_INFO_MMAP | |
1252 | .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | | 1129 | SNDRV_PCM_INFO_INTERLEAVED | |
1253 | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START), | 1130 | SNDRV_PCM_INFO_MMAP_VALID | |
1254 | .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | | 1131 | SNDRV_PCM_INFO_SYNC_START, |
1255 | SNDRV_PCM_FMTBIT_IMA_ADPCM | | 1132 | .formats = SNDRV_PCM_FMTBIT_MU_LAW | |
1256 | SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | | 1133 | SNDRV_PCM_FMTBIT_A_LAW | |
1257 | SNDRV_PCM_FMTBIT_S16_BE), | 1134 | SNDRV_PCM_FMTBIT_IMA_ADPCM | |
1258 | .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000, | 1135 | SNDRV_PCM_FMTBIT_U8 | |
1136 | SNDRV_PCM_FMTBIT_S16_LE | | ||
1137 | SNDRV_PCM_FMTBIT_S16_BE, | ||
1138 | .rates = SNDRV_PCM_RATE_KNOT | | ||
1139 | SNDRV_PCM_RATE_8000_48000, | ||
1259 | .rate_min = 5510, | 1140 | .rate_min = 5510, |
1260 | .rate_max = 48000, | 1141 | .rate_max = 48000, |
1261 | .channels_min = 1, | 1142 | .channels_min = 1, |
1262 | .channels_max = 2, | 1143 | .channels_max = 2, |
1263 | .buffer_bytes_max = (32*1024), | 1144 | .buffer_bytes_max = 32 * 1024, |
1264 | .period_bytes_min = 64, | 1145 | .period_bytes_min = 64, |
1265 | .period_bytes_max = (32*1024), | 1146 | .period_bytes_max = 32 * 1024, |
1266 | .periods_min = 1, | 1147 | .periods_min = 1, |
1267 | .periods_max = 1024, | 1148 | .periods_max = 1024, |
1268 | }; | 1149 | }; |
1269 | 1150 | ||
1270 | static struct snd_pcm_hardware snd_cs4231_capture = | 1151 | static struct snd_pcm_hardware snd_cs4231_capture = { |
1271 | { | 1152 | .info = SNDRV_PCM_INFO_MMAP | |
1272 | .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | | 1153 | SNDRV_PCM_INFO_INTERLEAVED | |
1273 | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START), | 1154 | SNDRV_PCM_INFO_MMAP_VALID | |
1274 | .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | | 1155 | SNDRV_PCM_INFO_SYNC_START, |
1275 | SNDRV_PCM_FMTBIT_IMA_ADPCM | | 1156 | .formats = SNDRV_PCM_FMTBIT_MU_LAW | |
1276 | SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | | 1157 | SNDRV_PCM_FMTBIT_A_LAW | |
1277 | SNDRV_PCM_FMTBIT_S16_BE), | 1158 | SNDRV_PCM_FMTBIT_IMA_ADPCM | |
1278 | .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000, | 1159 | SNDRV_PCM_FMTBIT_U8 | |
1160 | SNDRV_PCM_FMTBIT_S16_LE | | ||
1161 | SNDRV_PCM_FMTBIT_S16_BE, | ||
1162 | .rates = SNDRV_PCM_RATE_KNOT | | ||
1163 | SNDRV_PCM_RATE_8000_48000, | ||
1279 | .rate_min = 5510, | 1164 | .rate_min = 5510, |
1280 | .rate_max = 48000, | 1165 | .rate_max = 48000, |
1281 | .channels_min = 1, | 1166 | .channels_min = 1, |
1282 | .channels_max = 2, | 1167 | .channels_max = 2, |
1283 | .buffer_bytes_max = (32*1024), | 1168 | .buffer_bytes_max = 32 * 1024, |
1284 | .period_bytes_min = 64, | 1169 | .period_bytes_min = 64, |
1285 | .period_bytes_max = (32*1024), | 1170 | .period_bytes_max = 32 * 1024, |
1286 | .periods_min = 1, | 1171 | .periods_min = 1, |
1287 | .periods_max = 1024, | 1172 | .periods_max = 1024, |
1288 | }; | 1173 | }; |
@@ -1295,7 +1180,8 @@ static int snd_cs4231_playback_open(struct snd_pcm_substream *substream) | |||
1295 | 1180 | ||
1296 | runtime->hw = snd_cs4231_playback; | 1181 | runtime->hw = snd_cs4231_playback; |
1297 | 1182 | ||
1298 | if ((err = snd_cs4231_open(chip, CS4231_MODE_PLAY)) < 0) { | 1183 | err = snd_cs4231_open(chip, CS4231_MODE_PLAY); |
1184 | if (err < 0) { | ||
1299 | snd_free_pages(runtime->dma_area, runtime->dma_bytes); | 1185 | snd_free_pages(runtime->dma_area, runtime->dma_bytes); |
1300 | return err; | 1186 | return err; |
1301 | } | 1187 | } |
@@ -1315,7 +1201,8 @@ static int snd_cs4231_capture_open(struct snd_pcm_substream *substream) | |||
1315 | 1201 | ||
1316 | runtime->hw = snd_cs4231_capture; | 1202 | runtime->hw = snd_cs4231_capture; |
1317 | 1203 | ||
1318 | if ((err = snd_cs4231_open(chip, CS4231_MODE_RECORD)) < 0) { | 1204 | err = snd_cs4231_open(chip, CS4231_MODE_RECORD); |
1205 | if (err < 0) { | ||
1319 | snd_free_pages(runtime->dma_area, runtime->dma_bytes); | 1206 | snd_free_pages(runtime->dma_area, runtime->dma_bytes); |
1320 | return err; | 1207 | return err; |
1321 | } | 1208 | } |
@@ -1356,7 +1243,7 @@ static struct snd_pcm_ops snd_cs4231_playback_ops = { | |||
1356 | .close = snd_cs4231_playback_close, | 1243 | .close = snd_cs4231_playback_close, |
1357 | .ioctl = snd_pcm_lib_ioctl, | 1244 | .ioctl = snd_pcm_lib_ioctl, |
1358 | .hw_params = snd_cs4231_playback_hw_params, | 1245 | .hw_params = snd_cs4231_playback_hw_params, |
1359 | .hw_free = snd_cs4231_playback_hw_free, | 1246 | .hw_free = snd_pcm_lib_free_pages, |
1360 | .prepare = snd_cs4231_playback_prepare, | 1247 | .prepare = snd_cs4231_playback_prepare, |
1361 | .trigger = snd_cs4231_trigger, | 1248 | .trigger = snd_cs4231_trigger, |
1362 | .pointer = snd_cs4231_playback_pointer, | 1249 | .pointer = snd_cs4231_playback_pointer, |
@@ -1367,23 +1254,27 @@ static struct snd_pcm_ops snd_cs4231_capture_ops = { | |||
1367 | .close = snd_cs4231_capture_close, | 1254 | .close = snd_cs4231_capture_close, |
1368 | .ioctl = snd_pcm_lib_ioctl, | 1255 | .ioctl = snd_pcm_lib_ioctl, |
1369 | .hw_params = snd_cs4231_capture_hw_params, | 1256 | .hw_params = snd_cs4231_capture_hw_params, |
1370 | .hw_free = snd_cs4231_capture_hw_free, | 1257 | .hw_free = snd_pcm_lib_free_pages, |
1371 | .prepare = snd_cs4231_capture_prepare, | 1258 | .prepare = snd_cs4231_capture_prepare, |
1372 | .trigger = snd_cs4231_trigger, | 1259 | .trigger = snd_cs4231_trigger, |
1373 | .pointer = snd_cs4231_capture_pointer, | 1260 | .pointer = snd_cs4231_capture_pointer, |
1374 | }; | 1261 | }; |
1375 | 1262 | ||
1376 | static int __init snd_cs4231_pcm(struct snd_cs4231 *chip) | 1263 | static int __init snd_cs4231_pcm(struct snd_card *card) |
1377 | { | 1264 | { |
1265 | struct snd_cs4231 *chip = card->private_data; | ||
1378 | struct snd_pcm *pcm; | 1266 | struct snd_pcm *pcm; |
1379 | int err; | 1267 | int err; |
1380 | 1268 | ||
1381 | if ((err = snd_pcm_new(chip->card, "CS4231", 0, 1, 1, &pcm)) < 0) | 1269 | err = snd_pcm_new(card, "CS4231", 0, 1, 1, &pcm); |
1270 | if (err < 0) | ||
1382 | return err; | 1271 | return err; |
1383 | 1272 | ||
1384 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs4231_playback_ops); | 1273 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, |
1385 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cs4231_capture_ops); | 1274 | &snd_cs4231_playback_ops); |
1386 | 1275 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, | |
1276 | &snd_cs4231_capture_ops); | ||
1277 | |||
1387 | /* global setup */ | 1278 | /* global setup */ |
1388 | pcm->private_data = chip; | 1279 | pcm->private_data = chip; |
1389 | pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX; | 1280 | pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX; |
@@ -1396,8 +1287,9 @@ static int __init snd_cs4231_pcm(struct snd_cs4231 *chip) | |||
1396 | return 0; | 1287 | return 0; |
1397 | } | 1288 | } |
1398 | 1289 | ||
1399 | static int __init snd_cs4231_timer(struct snd_cs4231 *chip) | 1290 | static int __init snd_cs4231_timer(struct snd_card *card) |
1400 | { | 1291 | { |
1292 | struct snd_cs4231 *chip = card->private_data; | ||
1401 | struct snd_timer *timer; | 1293 | struct snd_timer *timer; |
1402 | struct snd_timer_id tid; | 1294 | struct snd_timer_id tid; |
1403 | int err; | 1295 | int err; |
@@ -1405,10 +1297,11 @@ static int __init snd_cs4231_timer(struct snd_cs4231 *chip) | |||
1405 | /* Timer initialization */ | 1297 | /* Timer initialization */ |
1406 | tid.dev_class = SNDRV_TIMER_CLASS_CARD; | 1298 | tid.dev_class = SNDRV_TIMER_CLASS_CARD; |
1407 | tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE; | 1299 | tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE; |
1408 | tid.card = chip->card->number; | 1300 | tid.card = card->number; |
1409 | tid.device = 0; | 1301 | tid.device = 0; |
1410 | tid.subdevice = 0; | 1302 | tid.subdevice = 0; |
1411 | if ((err = snd_timer_new(chip->card, "CS4231", &tid, &timer)) < 0) | 1303 | err = snd_timer_new(card, "CS4231", &tid, &timer); |
1304 | if (err < 0) | ||
1412 | return err; | 1305 | return err; |
1413 | strcpy(timer->name, "CS4231"); | 1306 | strcpy(timer->name, "CS4231"); |
1414 | timer->private_data = chip; | 1307 | timer->private_data = chip; |
@@ -1417,7 +1310,7 @@ static int __init snd_cs4231_timer(struct snd_cs4231 *chip) | |||
1417 | 1310 | ||
1418 | return 0; | 1311 | return 0; |
1419 | } | 1312 | } |
1420 | 1313 | ||
1421 | /* | 1314 | /* |
1422 | * MIXER part | 1315 | * MIXER part |
1423 | */ | 1316 | */ |
@@ -1428,15 +1321,14 @@ static int snd_cs4231_info_mux(struct snd_kcontrol *kcontrol, | |||
1428 | static char *texts[4] = { | 1321 | static char *texts[4] = { |
1429 | "Line", "CD", "Mic", "Mix" | 1322 | "Line", "CD", "Mic", "Mix" |
1430 | }; | 1323 | }; |
1431 | struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); | ||
1432 | 1324 | ||
1433 | snd_assert(chip->card != NULL, return -EINVAL); | ||
1434 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 1325 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
1435 | uinfo->count = 2; | 1326 | uinfo->count = 2; |
1436 | uinfo->value.enumerated.items = 4; | 1327 | uinfo->value.enumerated.items = 4; |
1437 | if (uinfo->value.enumerated.item > 3) | 1328 | if (uinfo->value.enumerated.item > 3) |
1438 | uinfo->value.enumerated.item = 3; | 1329 | uinfo->value.enumerated.item = 3; |
1439 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | 1330 | strcpy(uinfo->value.enumerated.name, |
1331 | texts[uinfo->value.enumerated.item]); | ||
1440 | 1332 | ||
1441 | return 0; | 1333 | return 0; |
1442 | } | 1334 | } |
@@ -1446,7 +1338,7 @@ static int snd_cs4231_get_mux(struct snd_kcontrol *kcontrol, | |||
1446 | { | 1338 | { |
1447 | struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); | 1339 | struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); |
1448 | unsigned long flags; | 1340 | unsigned long flags; |
1449 | 1341 | ||
1450 | spin_lock_irqsave(&chip->lock, flags); | 1342 | spin_lock_irqsave(&chip->lock, flags); |
1451 | ucontrol->value.enumerated.item[0] = | 1343 | ucontrol->value.enumerated.item[0] = |
1452 | (chip->image[CS4231_LEFT_INPUT] & CS4231_MIXS_ALL) >> 6; | 1344 | (chip->image[CS4231_LEFT_INPUT] & CS4231_MIXS_ALL) >> 6; |
@@ -1464,7 +1356,7 @@ static int snd_cs4231_put_mux(struct snd_kcontrol *kcontrol, | |||
1464 | unsigned long flags; | 1356 | unsigned long flags; |
1465 | unsigned short left, right; | 1357 | unsigned short left, right; |
1466 | int change; | 1358 | int change; |
1467 | 1359 | ||
1468 | if (ucontrol->value.enumerated.item[0] > 3 || | 1360 | if (ucontrol->value.enumerated.item[0] > 3 || |
1469 | ucontrol->value.enumerated.item[1] > 3) | 1361 | ucontrol->value.enumerated.item[1] > 3) |
1470 | return -EINVAL; | 1362 | return -EINVAL; |
@@ -1476,7 +1368,7 @@ static int snd_cs4231_put_mux(struct snd_kcontrol *kcontrol, | |||
1476 | left = (chip->image[CS4231_LEFT_INPUT] & ~CS4231_MIXS_ALL) | left; | 1368 | left = (chip->image[CS4231_LEFT_INPUT] & ~CS4231_MIXS_ALL) | left; |
1477 | right = (chip->image[CS4231_RIGHT_INPUT] & ~CS4231_MIXS_ALL) | right; | 1369 | right = (chip->image[CS4231_RIGHT_INPUT] & ~CS4231_MIXS_ALL) | right; |
1478 | change = left != chip->image[CS4231_LEFT_INPUT] || | 1370 | change = left != chip->image[CS4231_LEFT_INPUT] || |
1479 | right != chip->image[CS4231_RIGHT_INPUT]; | 1371 | right != chip->image[CS4231_RIGHT_INPUT]; |
1480 | snd_cs4231_out(chip, CS4231_LEFT_INPUT, left); | 1372 | snd_cs4231_out(chip, CS4231_LEFT_INPUT, left); |
1481 | snd_cs4231_out(chip, CS4231_RIGHT_INPUT, right); | 1373 | snd_cs4231_out(chip, CS4231_RIGHT_INPUT, right); |
1482 | 1374 | ||
@@ -1508,7 +1400,7 @@ static int snd_cs4231_get_single(struct snd_kcontrol *kcontrol, | |||
1508 | int shift = (kcontrol->private_value >> 8) & 0xff; | 1400 | int shift = (kcontrol->private_value >> 8) & 0xff; |
1509 | int mask = (kcontrol->private_value >> 16) & 0xff; | 1401 | int mask = (kcontrol->private_value >> 16) & 0xff; |
1510 | int invert = (kcontrol->private_value >> 24) & 0xff; | 1402 | int invert = (kcontrol->private_value >> 24) & 0xff; |
1511 | 1403 | ||
1512 | spin_lock_irqsave(&chip->lock, flags); | 1404 | spin_lock_irqsave(&chip->lock, flags); |
1513 | 1405 | ||
1514 | ucontrol->value.integer.value[0] = (chip->image[reg] >> shift) & mask; | 1406 | ucontrol->value.integer.value[0] = (chip->image[reg] >> shift) & mask; |
@@ -1533,7 +1425,7 @@ static int snd_cs4231_put_single(struct snd_kcontrol *kcontrol, | |||
1533 | int invert = (kcontrol->private_value >> 24) & 0xff; | 1425 | int invert = (kcontrol->private_value >> 24) & 0xff; |
1534 | int change; | 1426 | int change; |
1535 | unsigned short val; | 1427 | unsigned short val; |
1536 | 1428 | ||
1537 | val = (ucontrol->value.integer.value[0] & mask); | 1429 | val = (ucontrol->value.integer.value[0] & mask); |
1538 | if (invert) | 1430 | if (invert) |
1539 | val = mask - val; | 1431 | val = mask - val; |
@@ -1575,11 +1467,13 @@ static int snd_cs4231_get_double(struct snd_kcontrol *kcontrol, | |||
1575 | int shift_right = (kcontrol->private_value >> 19) & 0x07; | 1467 | int shift_right = (kcontrol->private_value >> 19) & 0x07; |
1576 | int mask = (kcontrol->private_value >> 24) & 0xff; | 1468 | int mask = (kcontrol->private_value >> 24) & 0xff; |
1577 | int invert = (kcontrol->private_value >> 22) & 1; | 1469 | int invert = (kcontrol->private_value >> 22) & 1; |
1578 | 1470 | ||
1579 | spin_lock_irqsave(&chip->lock, flags); | 1471 | spin_lock_irqsave(&chip->lock, flags); |
1580 | 1472 | ||
1581 | ucontrol->value.integer.value[0] = (chip->image[left_reg] >> shift_left) & mask; | 1473 | ucontrol->value.integer.value[0] = |
1582 | ucontrol->value.integer.value[1] = (chip->image[right_reg] >> shift_right) & mask; | 1474 | (chip->image[left_reg] >> shift_left) & mask; |
1475 | ucontrol->value.integer.value[1] = | ||
1476 | (chip->image[right_reg] >> shift_right) & mask; | ||
1583 | 1477 | ||
1584 | spin_unlock_irqrestore(&chip->lock, flags); | 1478 | spin_unlock_irqrestore(&chip->lock, flags); |
1585 | 1479 | ||
@@ -1606,7 +1500,7 @@ static int snd_cs4231_put_double(struct snd_kcontrol *kcontrol, | |||
1606 | int invert = (kcontrol->private_value >> 22) & 1; | 1500 | int invert = (kcontrol->private_value >> 22) & 1; |
1607 | int change; | 1501 | int change; |
1608 | unsigned short val1, val2; | 1502 | unsigned short val1, val2; |
1609 | 1503 | ||
1610 | val1 = ucontrol->value.integer.value[0] & mask; | 1504 | val1 = ucontrol->value.integer.value[0] & mask; |
1611 | val2 = ucontrol->value.integer.value[1] & mask; | 1505 | val2 = ucontrol->value.integer.value[1] & mask; |
1612 | if (invert) { | 1506 | if (invert) { |
@@ -1620,7 +1514,8 @@ static int snd_cs4231_put_double(struct snd_kcontrol *kcontrol, | |||
1620 | 1514 | ||
1621 | val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1; | 1515 | val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1; |
1622 | val2 = (chip->image[right_reg] & ~(mask << shift_right)) | val2; | 1516 | val2 = (chip->image[right_reg] & ~(mask << shift_right)) | val2; |
1623 | change = val1 != chip->image[left_reg] || val2 != chip->image[right_reg]; | 1517 | change = val1 != chip->image[left_reg]; |
1518 | change |= val2 != chip->image[right_reg]; | ||
1624 | snd_cs4231_out(chip, left_reg, val1); | 1519 | snd_cs4231_out(chip, left_reg, val1); |
1625 | snd_cs4231_out(chip, right_reg, val2); | 1520 | snd_cs4231_out(chip, right_reg, val2); |
1626 | 1521 | ||
@@ -1630,31 +1525,42 @@ static int snd_cs4231_put_double(struct snd_kcontrol *kcontrol, | |||
1630 | } | 1525 | } |
1631 | 1526 | ||
1632 | #define CS4231_SINGLE(xname, xindex, reg, shift, mask, invert) \ | 1527 | #define CS4231_SINGLE(xname, xindex, reg, shift, mask, invert) \ |
1633 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ | 1528 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), .index = (xindex), \ |
1634 | .info = snd_cs4231_info_single, \ | 1529 | .info = snd_cs4231_info_single, \ |
1635 | .get = snd_cs4231_get_single, .put = snd_cs4231_put_single, \ | 1530 | .get = snd_cs4231_get_single, .put = snd_cs4231_put_single, \ |
1636 | .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) } | 1531 | .private_value = (reg) | ((shift) << 8) | ((mask) << 16) | ((invert) << 24) } |
1637 | 1532 | ||
1638 | #define CS4231_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \ | 1533 | #define CS4231_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, \ |
1639 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ | 1534 | shift_right, mask, invert) \ |
1640 | .info = snd_cs4231_info_double, \ | 1535 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), .index = (xindex), \ |
1641 | .get = snd_cs4231_get_double, .put = snd_cs4231_put_double, \ | 1536 | .info = snd_cs4231_info_double, \ |
1642 | .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) } | 1537 | .get = snd_cs4231_get_double, .put = snd_cs4231_put_double, \ |
1538 | .private_value = (left_reg) | ((right_reg) << 8) | ((shift_left) << 16) | \ | ||
1539 | ((shift_right) << 19) | ((mask) << 24) | ((invert) << 22) } | ||
1643 | 1540 | ||
1644 | static struct snd_kcontrol_new snd_cs4231_controls[] __initdata = { | 1541 | static struct snd_kcontrol_new snd_cs4231_controls[] __initdata = { |
1645 | CS4231_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), | 1542 | CS4231_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT, |
1646 | CS4231_DOUBLE("PCM Playback Volume", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1), | 1543 | CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), |
1647 | CS4231_DOUBLE("Line Playback Switch", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1), | 1544 | CS4231_DOUBLE("PCM Playback Volume", 0, CS4231_LEFT_OUTPUT, |
1648 | CS4231_DOUBLE("Line Playback Volume", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1), | 1545 | CS4231_RIGHT_OUTPUT, 0, 0, 63, 1), |
1649 | CS4231_DOUBLE("Aux Playback Switch", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1), | 1546 | CS4231_DOUBLE("Line Playback Switch", 0, CS4231_LEFT_LINE_IN, |
1650 | CS4231_DOUBLE("Aux Playback Volume", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1), | 1547 | CS4231_RIGHT_LINE_IN, 7, 7, 1, 1), |
1651 | CS4231_DOUBLE("Aux Playback Switch", 1, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), | 1548 | CS4231_DOUBLE("Line Playback Volume", 0, CS4231_LEFT_LINE_IN, |
1652 | CS4231_DOUBLE("Aux Playback Volume", 1, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1), | 1549 | CS4231_RIGHT_LINE_IN, 0, 0, 31, 1), |
1550 | CS4231_DOUBLE("Aux Playback Switch", 0, CS4231_AUX1_LEFT_INPUT, | ||
1551 | CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1), | ||
1552 | CS4231_DOUBLE("Aux Playback Volume", 0, CS4231_AUX1_LEFT_INPUT, | ||
1553 | CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1), | ||
1554 | CS4231_DOUBLE("Aux Playback Switch", 1, CS4231_AUX2_LEFT_INPUT, | ||
1555 | CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), | ||
1556 | CS4231_DOUBLE("Aux Playback Volume", 1, CS4231_AUX2_LEFT_INPUT, | ||
1557 | CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1), | ||
1653 | CS4231_SINGLE("Mono Playback Switch", 0, CS4231_MONO_CTRL, 7, 1, 1), | 1558 | CS4231_SINGLE("Mono Playback Switch", 0, CS4231_MONO_CTRL, 7, 1, 1), |
1654 | CS4231_SINGLE("Mono Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1), | 1559 | CS4231_SINGLE("Mono Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1), |
1655 | CS4231_SINGLE("Mono Output Playback Switch", 0, CS4231_MONO_CTRL, 6, 1, 1), | 1560 | CS4231_SINGLE("Mono Output Playback Switch", 0, CS4231_MONO_CTRL, 6, 1, 1), |
1656 | CS4231_SINGLE("Mono Output Playback Bypass", 0, CS4231_MONO_CTRL, 5, 1, 0), | 1561 | CS4231_SINGLE("Mono Output Playback Bypass", 0, CS4231_MONO_CTRL, 5, 1, 0), |
1657 | CS4231_DOUBLE("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0), | 1562 | CS4231_DOUBLE("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, |
1563 | 15, 0), | ||
1658 | { | 1564 | { |
1659 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1565 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1660 | .name = "Capture Source", | 1566 | .name = "Capture Source", |
@@ -1662,29 +1568,28 @@ CS4231_DOUBLE("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, | |||
1662 | .get = snd_cs4231_get_mux, | 1568 | .get = snd_cs4231_get_mux, |
1663 | .put = snd_cs4231_put_mux, | 1569 | .put = snd_cs4231_put_mux, |
1664 | }, | 1570 | }, |
1665 | CS4231_DOUBLE("Mic Boost", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0), | 1571 | CS4231_DOUBLE("Mic Boost", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, |
1572 | 1, 0), | ||
1666 | CS4231_SINGLE("Loopback Capture Switch", 0, CS4231_LOOPBACK, 0, 1, 0), | 1573 | CS4231_SINGLE("Loopback Capture Switch", 0, CS4231_LOOPBACK, 0, 1, 0), |
1667 | CS4231_SINGLE("Loopback Capture Volume", 0, CS4231_LOOPBACK, 2, 63, 1), | 1574 | CS4231_SINGLE("Loopback Capture Volume", 0, CS4231_LOOPBACK, 2, 63, 1), |
1668 | /* SPARC specific uses of XCTL{0,1} general purpose outputs. */ | 1575 | /* SPARC specific uses of XCTL{0,1} general purpose outputs. */ |
1669 | CS4231_SINGLE("Line Out Switch", 0, CS4231_PIN_CTRL, 6, 1, 1), | 1576 | CS4231_SINGLE("Line Out Switch", 0, CS4231_PIN_CTRL, 6, 1, 1), |
1670 | CS4231_SINGLE("Headphone Out Switch", 0, CS4231_PIN_CTRL, 7, 1, 1) | 1577 | CS4231_SINGLE("Headphone Out Switch", 0, CS4231_PIN_CTRL, 7, 1, 1) |
1671 | }; | 1578 | }; |
1672 | 1579 | ||
1673 | static int __init snd_cs4231_mixer(struct snd_cs4231 *chip) | 1580 | static int __init snd_cs4231_mixer(struct snd_card *card) |
1674 | { | 1581 | { |
1675 | struct snd_card *card; | 1582 | struct snd_cs4231 *chip = card->private_data; |
1676 | int err, idx; | 1583 | int err, idx; |
1677 | 1584 | ||
1678 | snd_assert(chip != NULL && chip->pcm != NULL, return -EINVAL); | 1585 | snd_assert(chip != NULL && chip->pcm != NULL, return -EINVAL); |
1679 | 1586 | ||
1680 | card = chip->card; | ||
1681 | |||
1682 | strcpy(card->mixername, chip->pcm->name); | 1587 | strcpy(card->mixername, chip->pcm->name); |
1683 | 1588 | ||
1684 | for (idx = 0; idx < ARRAY_SIZE(snd_cs4231_controls); idx++) { | 1589 | for (idx = 0; idx < ARRAY_SIZE(snd_cs4231_controls); idx++) { |
1685 | if ((err = snd_ctl_add(card, | 1590 | err = snd_ctl_add(card, |
1686 | snd_ctl_new1(&snd_cs4231_controls[idx], | 1591 | snd_ctl_new1(&snd_cs4231_controls[idx], chip)); |
1687 | chip))) < 0) | 1592 | if (err < 0) |
1688 | return err; | 1593 | return err; |
1689 | } | 1594 | } |
1690 | return 0; | 1595 | return 0; |
@@ -1695,6 +1600,7 @@ static int dev; | |||
1695 | static int __init cs4231_attach_begin(struct snd_card **rcard) | 1600 | static int __init cs4231_attach_begin(struct snd_card **rcard) |
1696 | { | 1601 | { |
1697 | struct snd_card *card; | 1602 | struct snd_card *card; |
1603 | struct snd_cs4231 *chip; | ||
1698 | 1604 | ||
1699 | *rcard = NULL; | 1605 | *rcard = NULL; |
1700 | 1606 | ||
@@ -1706,31 +1612,40 @@ static int __init cs4231_attach_begin(struct snd_card **rcard) | |||
1706 | return -ENOENT; | 1612 | return -ENOENT; |
1707 | } | 1613 | } |
1708 | 1614 | ||
1709 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 1615 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, |
1616 | sizeof(struct snd_cs4231)); | ||
1710 | if (card == NULL) | 1617 | if (card == NULL) |
1711 | return -ENOMEM; | 1618 | return -ENOMEM; |
1712 | 1619 | ||
1713 | strcpy(card->driver, "CS4231"); | 1620 | strcpy(card->driver, "CS4231"); |
1714 | strcpy(card->shortname, "Sun CS4231"); | 1621 | strcpy(card->shortname, "Sun CS4231"); |
1715 | 1622 | ||
1623 | chip = card->private_data; | ||
1624 | chip->card = card; | ||
1625 | |||
1716 | *rcard = card; | 1626 | *rcard = card; |
1717 | return 0; | 1627 | return 0; |
1718 | } | 1628 | } |
1719 | 1629 | ||
1720 | static int __init cs4231_attach_finish(struct snd_card *card, struct snd_cs4231 *chip) | 1630 | static int __init cs4231_attach_finish(struct snd_card *card) |
1721 | { | 1631 | { |
1632 | struct snd_cs4231 *chip = card->private_data; | ||
1722 | int err; | 1633 | int err; |
1723 | 1634 | ||
1724 | if ((err = snd_cs4231_pcm(chip)) < 0) | 1635 | err = snd_cs4231_pcm(card); |
1636 | if (err < 0) | ||
1725 | goto out_err; | 1637 | goto out_err; |
1726 | 1638 | ||
1727 | if ((err = snd_cs4231_mixer(chip)) < 0) | 1639 | err = snd_cs4231_mixer(card); |
1640 | if (err < 0) | ||
1728 | goto out_err; | 1641 | goto out_err; |
1729 | 1642 | ||
1730 | if ((err = snd_cs4231_timer(chip)) < 0) | 1643 | err = snd_cs4231_timer(card); |
1644 | if (err < 0) | ||
1731 | goto out_err; | 1645 | goto out_err; |
1732 | 1646 | ||
1733 | if ((err = snd_card_register(card)) < 0) | 1647 | err = snd_card_register(card); |
1648 | if (err < 0) | ||
1734 | goto out_err; | 1649 | goto out_err; |
1735 | 1650 | ||
1736 | chip->next = cs4231_list; | 1651 | chip->next = cs4231_list; |
@@ -1754,7 +1669,7 @@ static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id) | |||
1754 | struct snd_cs4231 *chip = dev_id; | 1669 | struct snd_cs4231 *chip = dev_id; |
1755 | 1670 | ||
1756 | /*This is IRQ is not raised by the cs4231*/ | 1671 | /*This is IRQ is not raised by the cs4231*/ |
1757 | if (!(__cs4231_readb(chip, CS4231P(chip, STATUS)) & CS4231_GLOBALIRQ)) | 1672 | if (!(__cs4231_readb(chip, CS4231U(chip, STATUS)) & CS4231_GLOBALIRQ)) |
1758 | return IRQ_NONE; | 1673 | return IRQ_NONE; |
1759 | 1674 | ||
1760 | /* ACK the APC interrupt. */ | 1675 | /* ACK the APC interrupt. */ |
@@ -1762,24 +1677,24 @@ static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id) | |||
1762 | 1677 | ||
1763 | sbus_writel(csr, chip->port + APCCSR); | 1678 | sbus_writel(csr, chip->port + APCCSR); |
1764 | 1679 | ||
1765 | if ((csr & APC_PDMA_READY) && | 1680 | if ((csr & APC_PDMA_READY) && |
1766 | (csr & APC_PLAY_INT) && | 1681 | (csr & APC_PLAY_INT) && |
1767 | (csr & APC_XINT_PNVA) && | 1682 | (csr & APC_XINT_PNVA) && |
1768 | !(csr & APC_XINT_EMPT)) | 1683 | !(csr & APC_XINT_EMPT)) |
1769 | snd_cs4231_play_callback(chip); | 1684 | snd_cs4231_play_callback(chip); |
1770 | 1685 | ||
1771 | if ((csr & APC_CDMA_READY) && | 1686 | if ((csr & APC_CDMA_READY) && |
1772 | (csr & APC_CAPT_INT) && | 1687 | (csr & APC_CAPT_INT) && |
1773 | (csr & APC_XINT_CNVA) && | 1688 | (csr & APC_XINT_CNVA) && |
1774 | !(csr & APC_XINT_EMPT)) | 1689 | !(csr & APC_XINT_EMPT)) |
1775 | snd_cs4231_capture_callback(chip); | 1690 | snd_cs4231_capture_callback(chip); |
1776 | 1691 | ||
1777 | status = snd_cs4231_in(chip, CS4231_IRQ_STATUS); | 1692 | status = snd_cs4231_in(chip, CS4231_IRQ_STATUS); |
1778 | 1693 | ||
1779 | if (status & CS4231_TIMER_IRQ) { | 1694 | if (status & CS4231_TIMER_IRQ) { |
1780 | if (chip->timer) | 1695 | if (chip->timer) |
1781 | snd_timer_interrupt(chip->timer, chip->timer->sticks); | 1696 | snd_timer_interrupt(chip->timer, chip->timer->sticks); |
1782 | } | 1697 | } |
1783 | 1698 | ||
1784 | if ((status & CS4231_RECORD_IRQ) && (csr & APC_CDMA_READY)) | 1699 | if ((status & CS4231_RECORD_IRQ) && (csr & APC_CDMA_READY)) |
1785 | snd_cs4231_overrange(chip); | 1700 | snd_cs4231_overrange(chip); |
@@ -1796,26 +1711,27 @@ static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id) | |||
1796 | * SBUS DMA routines | 1711 | * SBUS DMA routines |
1797 | */ | 1712 | */ |
1798 | 1713 | ||
1799 | static int sbus_dma_request(struct cs4231_dma_control *dma_cont, dma_addr_t bus_addr, size_t len) | 1714 | static int sbus_dma_request(struct cs4231_dma_control *dma_cont, |
1715 | dma_addr_t bus_addr, size_t len) | ||
1800 | { | 1716 | { |
1801 | unsigned long flags; | 1717 | unsigned long flags; |
1802 | u32 test, csr; | 1718 | u32 test, csr; |
1803 | int err; | 1719 | int err; |
1804 | struct sbus_dma_info *base = &dma_cont->sbus_info; | 1720 | struct sbus_dma_info *base = &dma_cont->sbus_info; |
1805 | 1721 | ||
1806 | if (len >= (1 << 24)) | 1722 | if (len >= (1 << 24)) |
1807 | return -EINVAL; | 1723 | return -EINVAL; |
1808 | spin_lock_irqsave(&base->lock, flags); | 1724 | spin_lock_irqsave(&base->lock, flags); |
1809 | csr = sbus_readl(base->regs + APCCSR); | 1725 | csr = sbus_readl(base->regs + APCCSR); |
1810 | err = -EINVAL; | 1726 | err = -EINVAL; |
1811 | test = APC_CDMA_READY; | 1727 | test = APC_CDMA_READY; |
1812 | if ( base->dir == APC_PLAY ) | 1728 | if (base->dir == APC_PLAY) |
1813 | test = APC_PDMA_READY; | 1729 | test = APC_PDMA_READY; |
1814 | if (!(csr & test)) | 1730 | if (!(csr & test)) |
1815 | goto out; | 1731 | goto out; |
1816 | err = -EBUSY; | 1732 | err = -EBUSY; |
1817 | test = APC_XINT_CNVA; | 1733 | test = APC_XINT_CNVA; |
1818 | if ( base->dir == APC_PLAY ) | 1734 | if (base->dir == APC_PLAY) |
1819 | test = APC_XINT_PNVA; | 1735 | test = APC_XINT_PNVA; |
1820 | if (!(csr & test)) | 1736 | if (!(csr & test)) |
1821 | goto out; | 1737 | goto out; |
@@ -1838,7 +1754,7 @@ static void sbus_dma_prepare(struct cs4231_dma_control *dma_cont, int d) | |||
1838 | test = APC_GENL_INT | APC_PLAY_INT | APC_XINT_ENA | | 1754 | test = APC_GENL_INT | APC_PLAY_INT | APC_XINT_ENA | |
1839 | APC_XINT_PLAY | APC_XINT_PEMP | APC_XINT_GENL | | 1755 | APC_XINT_PLAY | APC_XINT_PEMP | APC_XINT_GENL | |
1840 | APC_XINT_PENA; | 1756 | APC_XINT_PENA; |
1841 | if ( base->dir == APC_RECORD ) | 1757 | if (base->dir == APC_RECORD) |
1842 | test = APC_GENL_INT | APC_CAPT_INT | APC_XINT_ENA | | 1758 | test = APC_GENL_INT | APC_CAPT_INT | APC_XINT_ENA | |
1843 | APC_XINT_CAPT | APC_XINT_CEMP | APC_XINT_GENL; | 1759 | APC_XINT_CAPT | APC_XINT_CEMP | APC_XINT_GENL; |
1844 | csr |= test; | 1760 | csr |= test; |
@@ -1856,28 +1772,28 @@ static void sbus_dma_enable(struct cs4231_dma_control *dma_cont, int on) | |||
1856 | if (!on) { | 1772 | if (!on) { |
1857 | sbus_writel(0, base->regs + base->dir + APCNC); | 1773 | sbus_writel(0, base->regs + base->dir + APCNC); |
1858 | sbus_writel(0, base->regs + base->dir + APCNVA); | 1774 | sbus_writel(0, base->regs + base->dir + APCNVA); |
1859 | if ( base->dir == APC_PLAY ) { | 1775 | if (base->dir == APC_PLAY) { |
1860 | sbus_writel(0, base->regs + base->dir + APCC); | 1776 | sbus_writel(0, base->regs + base->dir + APCC); |
1861 | sbus_writel(0, base->regs + base->dir + APCVA); | 1777 | sbus_writel(0, base->regs + base->dir + APCVA); |
1862 | } | 1778 | } |
1863 | 1779 | ||
1864 | udelay(1200); | 1780 | udelay(1200); |
1865 | } | 1781 | } |
1866 | csr = sbus_readl(base->regs + APCCSR); | 1782 | csr = sbus_readl(base->regs + APCCSR); |
1867 | shift = 0; | 1783 | shift = 0; |
1868 | if ( base->dir == APC_PLAY ) | 1784 | if (base->dir == APC_PLAY) |
1869 | shift = 1; | 1785 | shift = 1; |
1870 | if (on) | 1786 | if (on) |
1871 | csr &= ~(APC_CPAUSE << shift); | 1787 | csr &= ~(APC_CPAUSE << shift); |
1872 | else | 1788 | else |
1873 | csr |= (APC_CPAUSE << shift); | 1789 | csr |= (APC_CPAUSE << shift); |
1874 | sbus_writel(csr, base->regs + APCCSR); | 1790 | sbus_writel(csr, base->regs + APCCSR); |
1875 | if (on) | 1791 | if (on) |
1876 | csr |= (APC_CDMA_READY << shift); | 1792 | csr |= (APC_CDMA_READY << shift); |
1877 | else | 1793 | else |
1878 | csr &= ~(APC_CDMA_READY << shift); | 1794 | csr &= ~(APC_CDMA_READY << shift); |
1879 | sbus_writel(csr, base->regs + APCCSR); | 1795 | sbus_writel(csr, base->regs + APCCSR); |
1880 | 1796 | ||
1881 | spin_unlock_irqrestore(&base->lock, flags); | 1797 | spin_unlock_irqrestore(&base->lock, flags); |
1882 | } | 1798 | } |
1883 | 1799 | ||
@@ -1885,14 +1801,14 @@ static unsigned int sbus_dma_addr(struct cs4231_dma_control *dma_cont) | |||
1885 | { | 1801 | { |
1886 | struct sbus_dma_info *base = &dma_cont->sbus_info; | 1802 | struct sbus_dma_info *base = &dma_cont->sbus_info; |
1887 | 1803 | ||
1888 | return sbus_readl(base->regs + base->dir + APCVA); | 1804 | return sbus_readl(base->regs + base->dir + APCVA); |
1889 | } | 1805 | } |
1890 | 1806 | ||
1891 | static void sbus_dma_preallocate(struct snd_cs4231 *chip, struct snd_pcm *pcm) | 1807 | static void sbus_dma_preallocate(struct snd_cs4231 *chip, struct snd_pcm *pcm) |
1892 | { | 1808 | { |
1893 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_SBUS, | 1809 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_SBUS, |
1894 | snd_dma_sbus_data(chip->dev_u.sdev), | 1810 | snd_dma_sbus_data(chip->dev_u.sdev), |
1895 | 64*1024, 128*1024); | 1811 | 64 * 1024, 128 * 1024); |
1896 | } | 1812 | } |
1897 | 1813 | ||
1898 | /* | 1814 | /* |
@@ -1907,8 +1823,6 @@ static int snd_cs4231_sbus_free(struct snd_cs4231 *chip) | |||
1907 | if (chip->port) | 1823 | if (chip->port) |
1908 | sbus_iounmap(chip->port, chip->regs_size); | 1824 | sbus_iounmap(chip->port, chip->regs_size); |
1909 | 1825 | ||
1910 | kfree(chip); | ||
1911 | |||
1912 | return 0; | 1826 | return 0; |
1913 | } | 1827 | } |
1914 | 1828 | ||
@@ -1925,23 +1839,16 @@ static struct snd_device_ops snd_cs4231_sbus_dev_ops = { | |||
1925 | 1839 | ||
1926 | static int __init snd_cs4231_sbus_create(struct snd_card *card, | 1840 | static int __init snd_cs4231_sbus_create(struct snd_card *card, |
1927 | struct sbus_dev *sdev, | 1841 | struct sbus_dev *sdev, |
1928 | int dev, | 1842 | int dev) |
1929 | struct snd_cs4231 **rchip) | ||
1930 | { | 1843 | { |
1931 | struct snd_cs4231 *chip; | 1844 | struct snd_cs4231 *chip = card->private_data; |
1932 | int err; | 1845 | int err; |
1933 | 1846 | ||
1934 | *rchip = NULL; | ||
1935 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | ||
1936 | if (chip == NULL) | ||
1937 | return -ENOMEM; | ||
1938 | |||
1939 | spin_lock_init(&chip->lock); | 1847 | spin_lock_init(&chip->lock); |
1940 | spin_lock_init(&chip->c_dma.sbus_info.lock); | 1848 | spin_lock_init(&chip->c_dma.sbus_info.lock); |
1941 | spin_lock_init(&chip->p_dma.sbus_info.lock); | 1849 | spin_lock_init(&chip->p_dma.sbus_info.lock); |
1942 | mutex_init(&chip->mce_mutex); | 1850 | mutex_init(&chip->mce_mutex); |
1943 | mutex_init(&chip->open_mutex); | 1851 | mutex_init(&chip->open_mutex); |
1944 | chip->card = card; | ||
1945 | chip->dev_u.sdev = sdev; | 1852 | chip->dev_u.sdev = sdev; |
1946 | chip->regs_size = sdev->reg_addrs[0].reg_size; | 1853 | chip->regs_size = sdev->reg_addrs[0].reg_size; |
1947 | memcpy(&chip->image, &snd_cs4231_original_image, | 1854 | memcpy(&chip->image, &snd_cs4231_original_image, |
@@ -1992,14 +1899,12 @@ static int __init snd_cs4231_sbus_create(struct snd_card *card, | |||
1992 | return err; | 1899 | return err; |
1993 | } | 1900 | } |
1994 | 1901 | ||
1995 | *rchip = chip; | ||
1996 | return 0; | 1902 | return 0; |
1997 | } | 1903 | } |
1998 | 1904 | ||
1999 | static int __init cs4231_sbus_attach(struct sbus_dev *sdev) | 1905 | static int __init cs4231_sbus_attach(struct sbus_dev *sdev) |
2000 | { | 1906 | { |
2001 | struct resource *rp = &sdev->resource[0]; | 1907 | struct resource *rp = &sdev->resource[0]; |
2002 | struct snd_cs4231 *cp; | ||
2003 | struct snd_card *card; | 1908 | struct snd_card *card; |
2004 | int err; | 1909 | int err; |
2005 | 1910 | ||
@@ -2013,25 +1918,28 @@ static int __init cs4231_sbus_attach(struct sbus_dev *sdev) | |||
2013 | (unsigned long long)rp->start, | 1918 | (unsigned long long)rp->start, |
2014 | sdev->irqs[0]); | 1919 | sdev->irqs[0]); |
2015 | 1920 | ||
2016 | if ((err = snd_cs4231_sbus_create(card, sdev, dev, &cp)) < 0) { | 1921 | err = snd_cs4231_sbus_create(card, sdev, dev); |
1922 | if (err < 0) { | ||
2017 | snd_card_free(card); | 1923 | snd_card_free(card); |
2018 | return err; | 1924 | return err; |
2019 | } | 1925 | } |
2020 | 1926 | ||
2021 | return cs4231_attach_finish(card, cp); | 1927 | return cs4231_attach_finish(card); |
2022 | } | 1928 | } |
2023 | #endif | 1929 | #endif |
2024 | 1930 | ||
2025 | #ifdef EBUS_SUPPORT | 1931 | #ifdef EBUS_SUPPORT |
2026 | 1932 | ||
2027 | static void snd_cs4231_ebus_play_callback(struct ebus_dma_info *p, int event, void *cookie) | 1933 | static void snd_cs4231_ebus_play_callback(struct ebus_dma_info *p, int event, |
1934 | void *cookie) | ||
2028 | { | 1935 | { |
2029 | struct snd_cs4231 *chip = cookie; | 1936 | struct snd_cs4231 *chip = cookie; |
2030 | 1937 | ||
2031 | snd_cs4231_play_callback(chip); | 1938 | snd_cs4231_play_callback(chip); |
2032 | } | 1939 | } |
2033 | 1940 | ||
2034 | static void snd_cs4231_ebus_capture_callback(struct ebus_dma_info *p, int event, void *cookie) | 1941 | static void snd_cs4231_ebus_capture_callback(struct ebus_dma_info *p, |
1942 | int event, void *cookie) | ||
2035 | { | 1943 | { |
2036 | struct snd_cs4231 *chip = cookie; | 1944 | struct snd_cs4231 *chip = cookie; |
2037 | 1945 | ||
@@ -2042,7 +1950,8 @@ static void snd_cs4231_ebus_capture_callback(struct ebus_dma_info *p, int event, | |||
2042 | * EBUS DMA wrappers | 1950 | * EBUS DMA wrappers |
2043 | */ | 1951 | */ |
2044 | 1952 | ||
2045 | static int _ebus_dma_request(struct cs4231_dma_control *dma_cont, dma_addr_t bus_addr, size_t len) | 1953 | static int _ebus_dma_request(struct cs4231_dma_control *dma_cont, |
1954 | dma_addr_t bus_addr, size_t len) | ||
2046 | { | 1955 | { |
2047 | return ebus_dma_request(&dma_cont->ebus_info, bus_addr, len); | 1956 | return ebus_dma_request(&dma_cont->ebus_info, bus_addr, len); |
2048 | } | 1957 | } |
@@ -2087,8 +1996,6 @@ static int snd_cs4231_ebus_free(struct snd_cs4231 *chip) | |||
2087 | if (chip->port) | 1996 | if (chip->port) |
2088 | iounmap(chip->port); | 1997 | iounmap(chip->port); |
2089 | 1998 | ||
2090 | kfree(chip); | ||
2091 | |||
2092 | return 0; | 1999 | return 0; |
2093 | } | 2000 | } |
2094 | 2001 | ||
@@ -2105,24 +2012,17 @@ static struct snd_device_ops snd_cs4231_ebus_dev_ops = { | |||
2105 | 2012 | ||
2106 | static int __init snd_cs4231_ebus_create(struct snd_card *card, | 2013 | static int __init snd_cs4231_ebus_create(struct snd_card *card, |
2107 | struct linux_ebus_device *edev, | 2014 | struct linux_ebus_device *edev, |
2108 | int dev, | 2015 | int dev) |
2109 | struct snd_cs4231 **rchip) | ||
2110 | { | 2016 | { |
2111 | struct snd_cs4231 *chip; | 2017 | struct snd_cs4231 *chip = card->private_data; |
2112 | int err; | 2018 | int err; |
2113 | 2019 | ||
2114 | *rchip = NULL; | ||
2115 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | ||
2116 | if (chip == NULL) | ||
2117 | return -ENOMEM; | ||
2118 | |||
2119 | spin_lock_init(&chip->lock); | 2020 | spin_lock_init(&chip->lock); |
2120 | spin_lock_init(&chip->c_dma.ebus_info.lock); | 2021 | spin_lock_init(&chip->c_dma.ebus_info.lock); |
2121 | spin_lock_init(&chip->p_dma.ebus_info.lock); | 2022 | spin_lock_init(&chip->p_dma.ebus_info.lock); |
2122 | mutex_init(&chip->mce_mutex); | 2023 | mutex_init(&chip->mce_mutex); |
2123 | mutex_init(&chip->open_mutex); | 2024 | mutex_init(&chip->open_mutex); |
2124 | chip->flags |= CS4231_FLAG_EBUS; | 2025 | chip->flags |= CS4231_FLAG_EBUS; |
2125 | chip->card = card; | ||
2126 | chip->dev_u.pdev = edev->bus->self; | 2026 | chip->dev_u.pdev = edev->bus->self; |
2127 | memcpy(&chip->image, &snd_cs4231_original_image, | 2027 | memcpy(&chip->image, &snd_cs4231_original_image, |
2128 | sizeof(snd_cs4231_original_image)); | 2028 | sizeof(snd_cs4231_original_image)); |
@@ -2152,7 +2052,8 @@ static int __init snd_cs4231_ebus_create(struct snd_card *card, | |||
2152 | chip->port = ioremap(edev->resource[0].start, 0x10); | 2052 | chip->port = ioremap(edev->resource[0].start, 0x10); |
2153 | chip->p_dma.ebus_info.regs = ioremap(edev->resource[1].start, 0x10); | 2053 | chip->p_dma.ebus_info.regs = ioremap(edev->resource[1].start, 0x10); |
2154 | chip->c_dma.ebus_info.regs = ioremap(edev->resource[2].start, 0x10); | 2054 | chip->c_dma.ebus_info.regs = ioremap(edev->resource[2].start, 0x10); |
2155 | if (!chip->port || !chip->p_dma.ebus_info.regs || !chip->c_dma.ebus_info.regs) { | 2055 | if (!chip->port || !chip->p_dma.ebus_info.regs || |
2056 | !chip->c_dma.ebus_info.regs) { | ||
2156 | snd_cs4231_ebus_free(chip); | 2057 | snd_cs4231_ebus_free(chip); |
2157 | snd_printdd("cs4231-%d: Unable to map chip registers.\n", dev); | 2058 | snd_printdd("cs4231-%d: Unable to map chip registers.\n", dev); |
2158 | return -EIO; | 2059 | return -EIO; |
@@ -2160,18 +2061,21 @@ static int __init snd_cs4231_ebus_create(struct snd_card *card, | |||
2160 | 2061 | ||
2161 | if (ebus_dma_register(&chip->c_dma.ebus_info)) { | 2062 | if (ebus_dma_register(&chip->c_dma.ebus_info)) { |
2162 | snd_cs4231_ebus_free(chip); | 2063 | snd_cs4231_ebus_free(chip); |
2163 | snd_printdd("cs4231-%d: Unable to register EBUS capture DMA\n", dev); | 2064 | snd_printdd("cs4231-%d: Unable to register EBUS capture DMA\n", |
2065 | dev); | ||
2164 | return -EBUSY; | 2066 | return -EBUSY; |
2165 | } | 2067 | } |
2166 | if (ebus_dma_irq_enable(&chip->c_dma.ebus_info, 1)) { | 2068 | if (ebus_dma_irq_enable(&chip->c_dma.ebus_info, 1)) { |
2167 | snd_cs4231_ebus_free(chip); | 2069 | snd_cs4231_ebus_free(chip); |
2168 | snd_printdd("cs4231-%d: Unable to enable EBUS capture IRQ\n", dev); | 2070 | snd_printdd("cs4231-%d: Unable to enable EBUS capture IRQ\n", |
2071 | dev); | ||
2169 | return -EBUSY; | 2072 | return -EBUSY; |
2170 | } | 2073 | } |
2171 | 2074 | ||
2172 | if (ebus_dma_register(&chip->p_dma.ebus_info)) { | 2075 | if (ebus_dma_register(&chip->p_dma.ebus_info)) { |
2173 | snd_cs4231_ebus_free(chip); | 2076 | snd_cs4231_ebus_free(chip); |
2174 | snd_printdd("cs4231-%d: Unable to register EBUS play DMA\n", dev); | 2077 | snd_printdd("cs4231-%d: Unable to register EBUS play DMA\n", |
2078 | dev); | ||
2175 | return -EBUSY; | 2079 | return -EBUSY; |
2176 | } | 2080 | } |
2177 | if (ebus_dma_irq_enable(&chip->p_dma.ebus_info, 1)) { | 2081 | if (ebus_dma_irq_enable(&chip->p_dma.ebus_info, 1)) { |
@@ -2192,14 +2096,12 @@ static int __init snd_cs4231_ebus_create(struct snd_card *card, | |||
2192 | return err; | 2096 | return err; |
2193 | } | 2097 | } |
2194 | 2098 | ||
2195 | *rchip = chip; | ||
2196 | return 0; | 2099 | return 0; |
2197 | } | 2100 | } |
2198 | 2101 | ||
2199 | static int __init cs4231_ebus_attach(struct linux_ebus_device *edev) | 2102 | static int __init cs4231_ebus_attach(struct linux_ebus_device *edev) |
2200 | { | 2103 | { |
2201 | struct snd_card *card; | 2104 | struct snd_card *card; |
2202 | struct snd_cs4231 *chip; | ||
2203 | int err; | 2105 | int err; |
2204 | 2106 | ||
2205 | err = cs4231_attach_begin(&card); | 2107 | err = cs4231_attach_begin(&card); |
@@ -2211,12 +2113,13 @@ static int __init cs4231_ebus_attach(struct linux_ebus_device *edev) | |||
2211 | edev->resource[0].start, | 2113 | edev->resource[0].start, |
2212 | edev->irqs[0]); | 2114 | edev->irqs[0]); |
2213 | 2115 | ||
2214 | if ((err = snd_cs4231_ebus_create(card, edev, dev, &chip)) < 0) { | 2116 | err = snd_cs4231_ebus_create(card, edev, dev); |
2117 | if (err < 0) { | ||
2215 | snd_card_free(card); | 2118 | snd_card_free(card); |
2216 | return err; | 2119 | return err; |
2217 | } | 2120 | } |
2218 | 2121 | ||
2219 | return cs4231_attach_finish(card, chip); | 2122 | return cs4231_attach_finish(card); |
2220 | } | 2123 | } |
2221 | #endif | 2124 | #endif |
2222 | 2125 | ||
diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c index e07085a7cfc3..376b98691c96 100644 --- a/sound/sparc/dbri.c +++ b/sound/sparc/dbri.c | |||
@@ -8,18 +8,18 @@ | |||
8 | * Copyright (C) 1997 Rudolf Koenig (rfkoenig@immd4.informatik.uni-erlangen.de) | 8 | * Copyright (C) 1997 Rudolf Koenig (rfkoenig@immd4.informatik.uni-erlangen.de) |
9 | * Copyright (C) 1998, 1999 Brent Baccala (baccala@freesoft.org) | 9 | * Copyright (C) 1998, 1999 Brent Baccala (baccala@freesoft.org) |
10 | * | 10 | * |
11 | * This is the lowlevel driver for the DBRI & MMCODEC duo used for ISDN & AUDIO | 11 | * This is the low level driver for the DBRI & MMCODEC duo used for ISDN & AUDIO |
12 | * on Sun SPARCstation 10, 20, LX and Voyager models. | 12 | * on Sun SPARCStation 10, 20, LX and Voyager models. |
13 | * | 13 | * |
14 | * - DBRI: AT&T T5900FX Dual Basic Rates ISDN Interface. It is a 32 channel | 14 | * - DBRI: AT&T T5900FX Dual Basic Rates ISDN Interface. It is a 32 channel |
15 | * data time multiplexer with ISDN support (aka T7259) | 15 | * data time multiplexer with ISDN support (aka T7259) |
16 | * Interfaces: SBus,ISDN NT & TE, CHI, 4 bits parallel. | 16 | * Interfaces: SBus,ISDN NT & TE, CHI, 4 bits parallel. |
17 | * CHI: (spelled ki) Concentration Highway Interface (AT&T or Intel bus ?). | 17 | * CHI: (spelled ki) Concentration Highway Interface (AT&T or Intel bus ?). |
18 | * Documentation: | 18 | * Documentation: |
19 | * - "STP 4000SBus Dual Basic Rate ISDN (DBRI) Tranceiver" from | 19 | * - "STP 4000SBus Dual Basic Rate ISDN (DBRI) Transceiver" from |
20 | * Sparc Technology Business (courtesy of Sun Support) | 20 | * Sparc Technology Business (courtesy of Sun Support) |
21 | * - Data sheet of the T7903, a newer but very similar ISA bus equivalent | 21 | * - Data sheet of the T7903, a newer but very similar ISA bus equivalent |
22 | * available from the Lucent (formarly AT&T microelectronics) home | 22 | * available from the Lucent (formerly AT&T microelectronics) home |
23 | * page. | 23 | * page. |
24 | * - http://www.freesoft.org/Linux/DBRI/ | 24 | * - http://www.freesoft.org/Linux/DBRI/ |
25 | * - MMCODEC: Crystal Semiconductor CS4215 16 bit Multimedia Audio Codec | 25 | * - MMCODEC: Crystal Semiconductor CS4215 16 bit Multimedia Audio Codec |
@@ -27,21 +27,21 @@ | |||
27 | * Documentation: from the Crystal Semiconductor home page. | 27 | * Documentation: from the Crystal Semiconductor home page. |
28 | * | 28 | * |
29 | * The DBRI is a 32 pipe machine, each pipe can transfer some bits between | 29 | * The DBRI is a 32 pipe machine, each pipe can transfer some bits between |
30 | * memory and a serial device (long pipes, nr 0-15) or between two serial | 30 | * memory and a serial device (long pipes, no. 0-15) or between two serial |
31 | * devices (short pipes, nr 16-31), or simply send a fixed data to a serial | 31 | * devices (short pipes, no. 16-31), or simply send a fixed data to a serial |
32 | * device (short pipes). | 32 | * device (short pipes). |
33 | * A timeslot defines the bit-offset and nr of bits read from a serial device. | 33 | * A timeslot defines the bit-offset and no. of bits read from a serial device. |
34 | * The timeslots are linked to 6 circular lists, one for each direction for | 34 | * The timeslots are linked to 6 circular lists, one for each direction for |
35 | * each serial device (NT,TE,CHI). A timeslot is associated to 1 or 2 pipes | 35 | * each serial device (NT,TE,CHI). A timeslot is associated to 1 or 2 pipes |
36 | * (the second one is a monitor/tee pipe, valid only for serial input). | 36 | * (the second one is a monitor/tee pipe, valid only for serial input). |
37 | * | 37 | * |
38 | * The mmcodec is connected via the CHI bus and needs the data & some | 38 | * The mmcodec is connected via the CHI bus and needs the data & some |
39 | * parameters (volume, output selection) timemultiplexed in 8 byte | 39 | * parameters (volume, output selection) time multiplexed in 8 byte |
40 | * chunks. It also has a control mode, which serves for audio format setting. | 40 | * chunks. It also has a control mode, which serves for audio format setting. |
41 | * | 41 | * |
42 | * Looking at the CS4215 data sheet it is easy to set up 2 or 4 codecs on | 42 | * Looking at the CS4215 data sheet it is easy to set up 2 or 4 codecs on |
43 | * the same CHI bus, so I thought perhaps it is possible to use the onboard | 43 | * the same CHI bus, so I thought perhaps it is possible to use the on-board |
44 | * & the speakerbox codec simultanously, giving 2 (not very independent :-) | 44 | * & the speakerbox codec simultaneously, giving 2 (not very independent :-) |
45 | * audio devices. But the SUN HW group decided against it, at least on my | 45 | * audio devices. But the SUN HW group decided against it, at least on my |
46 | * LX the speakerbox connector has at least 1 pin missing and 1 wrongly | 46 | * LX the speakerbox connector has at least 1 pin missing and 1 wrongly |
47 | * connected. | 47 | * connected. |
@@ -56,6 +56,8 @@ | |||
56 | #include <sound/driver.h> | 56 | #include <sound/driver.h> |
57 | #include <linux/interrupt.h> | 57 | #include <linux/interrupt.h> |
58 | #include <linux/delay.h> | 58 | #include <linux/delay.h> |
59 | #include <linux/irq.h> | ||
60 | #include <linux/io.h> | ||
59 | 61 | ||
60 | #include <sound/core.h> | 62 | #include <sound/core.h> |
61 | #include <sound/pcm.h> | 63 | #include <sound/pcm.h> |
@@ -64,8 +66,7 @@ | |||
64 | #include <sound/control.h> | 66 | #include <sound/control.h> |
65 | #include <sound/initval.h> | 67 | #include <sound/initval.h> |
66 | 68 | ||
67 | #include <asm/irq.h> | 69 | #include <linux/of.h> |
68 | #include <asm/io.h> | ||
69 | #include <asm/sbus.h> | 70 | #include <asm/sbus.h> |
70 | #include <asm/atomic.h> | 71 | #include <asm/atomic.h> |
71 | 72 | ||
@@ -76,7 +77,8 @@ MODULE_SUPPORTED_DEVICE("{{Sun,DBRI}}"); | |||
76 | 77 | ||
77 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ | 78 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ |
78 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ | 79 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ |
79 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ | 80 | /* Enable this card */ |
81 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; | ||
80 | 82 | ||
81 | module_param_array(index, int, NULL, 0444); | 83 | module_param_array(index, int, NULL, 0444); |
82 | MODULE_PARM_DESC(index, "Index value for Sun DBRI soundcard."); | 84 | MODULE_PARM_DESC(index, "Index value for Sun DBRI soundcard."); |
@@ -104,7 +106,7 @@ static char *cmds[] = { | |||
104 | "SSP", "CHI", "NT", "TE", "CDEC", "TEST", "CDM", "RESRV" | 106 | "SSP", "CHI", "NT", "TE", "CDEC", "TEST", "CDM", "RESRV" |
105 | }; | 107 | }; |
106 | 108 | ||
107 | #define dprintk(a, x...) if(dbri_debug & a) printk(KERN_DEBUG x) | 109 | #define dprintk(a, x...) if (dbri_debug & a) printk(KERN_DEBUG x) |
108 | 110 | ||
109 | #else | 111 | #else |
110 | #define dprintk(a, x...) do { } while (0) | 112 | #define dprintk(a, x...) do { } while (0) |
@@ -131,7 +133,7 @@ struct cs4215 { | |||
131 | }; | 133 | }; |
132 | 134 | ||
133 | /* | 135 | /* |
134 | * Control mode first | 136 | * Control mode first |
135 | */ | 137 | */ |
136 | 138 | ||
137 | /* Time Slot 1, Status register */ | 139 | /* Time Slot 1, Status register */ |
@@ -219,7 +221,7 @@ static struct { | |||
219 | /* Time Slot 7, Input Setting */ | 221 | /* Time Slot 7, Input Setting */ |
220 | #define CS4215_LG(v) v /* Left Gain Setting 0xf: 22.5 dB */ | 222 | #define CS4215_LG(v) v /* Left Gain Setting 0xf: 22.5 dB */ |
221 | #define CS4215_IS (1<<4) /* Input Select: 1=Microphone, 0=Line */ | 223 | #define CS4215_IS (1<<4) /* Input Select: 1=Microphone, 0=Line */ |
222 | #define CS4215_OVR (1<<5) /* 1: Overrange condition occurred */ | 224 | #define CS4215_OVR (1<<5) /* 1: Over range condition occurred */ |
223 | #define CS4215_PIO0 (1<<6) /* Parallel I/O 0 */ | 225 | #define CS4215_PIO0 (1<<6) /* Parallel I/O 0 */ |
224 | #define CS4215_PIO1 (1<<7) | 226 | #define CS4215_PIO1 (1<<7) |
225 | 227 | ||
@@ -232,12 +234,12 @@ static struct { | |||
232 | ****************************************************************************/ | 234 | ****************************************************************************/ |
233 | 235 | ||
234 | /* DBRI main registers */ | 236 | /* DBRI main registers */ |
235 | #define REG0 0x00UL /* Status and Control */ | 237 | #define REG0 0x00 /* Status and Control */ |
236 | #define REG1 0x04UL /* Mode and Interrupt */ | 238 | #define REG1 0x04 /* Mode and Interrupt */ |
237 | #define REG2 0x08UL /* Parallel IO */ | 239 | #define REG2 0x08 /* Parallel IO */ |
238 | #define REG3 0x0cUL /* Test */ | 240 | #define REG3 0x0c /* Test */ |
239 | #define REG8 0x20UL /* Command Queue Pointer */ | 241 | #define REG8 0x20 /* Command Queue Pointer */ |
240 | #define REG9 0x24UL /* Interrupt Queue Pointer */ | 242 | #define REG9 0x24 /* Interrupt Queue Pointer */ |
241 | 243 | ||
242 | #define DBRI_NO_CMDS 64 | 244 | #define DBRI_NO_CMDS 64 |
243 | #define DBRI_INT_BLK 64 | 245 | #define DBRI_INT_BLK 64 |
@@ -285,7 +287,7 @@ struct dbri_pipe { | |||
285 | /* Per stream (playback or record) information */ | 287 | /* Per stream (playback or record) information */ |
286 | struct dbri_streaminfo { | 288 | struct dbri_streaminfo { |
287 | struct snd_pcm_substream *substream; | 289 | struct snd_pcm_substream *substream; |
288 | u32 dvma_buffer; /* Device view of Alsa DMA buffer */ | 290 | u32 dvma_buffer; /* Device view of ALSA DMA buffer */ |
289 | int size; /* Size of DMA buffer */ | 291 | int size; /* Size of DMA buffer */ |
290 | size_t offset; /* offset in user buffer */ | 292 | size_t offset; /* offset in user buffer */ |
291 | int pipe; /* Data pipe used */ | 293 | int pipe; /* Data pipe used */ |
@@ -295,8 +297,6 @@ struct dbri_streaminfo { | |||
295 | 297 | ||
296 | /* This structure holds the information for both chips (DBRI & CS4215) */ | 298 | /* This structure holds the information for both chips (DBRI & CS4215) */ |
297 | struct snd_dbri { | 299 | struct snd_dbri { |
298 | struct snd_card *card; /* ALSA card */ | ||
299 | |||
300 | int regs_size, irq; /* Needed for unload */ | 300 | int regs_size, irq; /* Needed for unload */ |
301 | struct sbus_dev *sdev; /* SBUS device info */ | 301 | struct sbus_dev *sdev; /* SBUS device info */ |
302 | spinlock_t lock; | 302 | spinlock_t lock; |
@@ -317,8 +317,6 @@ struct snd_dbri { | |||
317 | struct cs4215 mm; /* mmcodec special info */ | 317 | struct cs4215 mm; /* mmcodec special info */ |
318 | /* per stream (playback/record) info */ | 318 | /* per stream (playback/record) info */ |
319 | struct dbri_streaminfo stream_info[DBRI_NO_STREAMS]; | 319 | struct dbri_streaminfo stream_info[DBRI_NO_STREAMS]; |
320 | |||
321 | struct snd_dbri *next; | ||
322 | }; | 320 | }; |
323 | 321 | ||
324 | #define DBRI_MAX_VOLUME 63 /* Output volume */ | 322 | #define DBRI_MAX_VOLUME 63 /* Output volume */ |
@@ -341,11 +339,11 @@ struct snd_dbri { | |||
341 | /* DBRI Reg1 - Mode and Interrupt Register - defines. (Page 18) */ | 339 | /* DBRI Reg1 - Mode and Interrupt Register - defines. (Page 18) */ |
342 | #define D_LITTLE_END (1<<8) /* Byte Order */ | 340 | #define D_LITTLE_END (1<<8) /* Byte Order */ |
343 | #define D_BIG_END (0<<8) /* Byte Order */ | 341 | #define D_BIG_END (0<<8) /* Byte Order */ |
344 | #define D_MRR (1<<4) /* Multiple Error Ack on SBus (readonly) */ | 342 | #define D_MRR (1<<4) /* Multiple Error Ack on SBus (read only) */ |
345 | #define D_MLE (1<<3) /* Multiple Late Error on SBus (readonly) */ | 343 | #define D_MLE (1<<3) /* Multiple Late Error on SBus (read only) */ |
346 | #define D_LBG (1<<2) /* Lost Bus Grant on SBus (readonly) */ | 344 | #define D_LBG (1<<2) /* Lost Bus Grant on SBus (read only) */ |
347 | #define D_MBE (1<<1) /* Burst Error on SBus (readonly) */ | 345 | #define D_MBE (1<<1) /* Burst Error on SBus (read only) */ |
348 | #define D_IR (1<<0) /* Interrupt Indicator (readonly) */ | 346 | #define D_IR (1<<0) /* Interrupt Indicator (read only) */ |
349 | 347 | ||
350 | /* DBRI Reg2 - Parallel IO Register - defines. (Page 18) */ | 348 | /* DBRI Reg2 - Parallel IO Register - defines. (Page 18) */ |
351 | #define D_ENPIO3 (1<<7) /* Enable Pin 3 */ | 349 | #define D_ENPIO3 (1<<7) /* Enable Pin 3 */ |
@@ -376,11 +374,11 @@ struct snd_dbri { | |||
376 | #define D_CDM 0xe /* CHI Data mode command */ | 374 | #define D_CDM 0xe /* CHI Data mode command */ |
377 | 375 | ||
378 | /* Special bits for some commands */ | 376 | /* Special bits for some commands */ |
379 | #define D_PIPE(v) ((v)<<0) /* Pipe Nr: 0-15 long, 16-21 short */ | 377 | #define D_PIPE(v) ((v)<<0) /* Pipe No.: 0-15 long, 16-21 short */ |
380 | 378 | ||
381 | /* Setup Data Pipe */ | 379 | /* Setup Data Pipe */ |
382 | /* IRM */ | 380 | /* IRM */ |
383 | #define D_SDP_2SAME (1<<18) /* Report 2nd time in a row value rcvd */ | 381 | #define D_SDP_2SAME (1<<18) /* Report 2nd time in a row value received */ |
384 | #define D_SDP_CHANGE (2<<18) /* Report any changes */ | 382 | #define D_SDP_CHANGE (2<<18) /* Report any changes */ |
385 | #define D_SDP_EVERY (3<<18) /* Report any changes */ | 383 | #define D_SDP_EVERY (3<<18) /* Report any changes */ |
386 | #define D_SDP_EOL (1<<17) /* EOL interrupt enable */ | 384 | #define D_SDP_EOL (1<<17) /* EOL interrupt enable */ |
@@ -419,7 +417,7 @@ struct snd_dbri { | |||
419 | #define D_TS_NONCONTIG (3<<10) /* Non contiguous mode */ | 417 | #define D_TS_NONCONTIG (3<<10) /* Non contiguous mode */ |
420 | #define D_TS_ANCHOR (7<<10) /* Starting short pipes */ | 418 | #define D_TS_ANCHOR (7<<10) /* Starting short pipes */ |
421 | #define D_TS_MON(v) ((v)<<5) /* Monitor Pipe */ | 419 | #define D_TS_MON(v) ((v)<<5) /* Monitor Pipe */ |
422 | #define D_TS_NEXT(v) ((v)<<0) /* Pipe Nr: 0-15 long, 16-21 short */ | 420 | #define D_TS_NEXT(v) ((v)<<0) /* Pipe no.: 0-15 long, 16-21 short */ |
423 | 421 | ||
424 | /* Concentration Highway Interface Modes */ | 422 | /* Concentration Highway Interface Modes */ |
425 | #define D_CHI_CHICM(v) ((v)<<16) /* Clock mode */ | 423 | #define D_CHI_CHICM(v) ((v)<<16) /* Clock mode */ |
@@ -435,7 +433,7 @@ struct snd_dbri { | |||
435 | #define D_NT_NBF (1<<16) /* Number of bad frames to loose framing */ | 433 | #define D_NT_NBF (1<<16) /* Number of bad frames to loose framing */ |
436 | #define D_NT_IRM_IMM (1<<15) /* Interrupt Report & Mask: Immediate */ | 434 | #define D_NT_IRM_IMM (1<<15) /* Interrupt Report & Mask: Immediate */ |
437 | #define D_NT_IRM_EN (1<<14) /* Interrupt Report & Mask: Enable */ | 435 | #define D_NT_IRM_EN (1<<14) /* Interrupt Report & Mask: Enable */ |
438 | #define D_NT_ISNT (1<<13) /* Configfure interface as NT */ | 436 | #define D_NT_ISNT (1<<13) /* Configure interface as NT */ |
439 | #define D_NT_FT (1<<12) /* Fixed Timing */ | 437 | #define D_NT_FT (1<<12) /* Fixed Timing */ |
440 | #define D_NT_EZ (1<<11) /* Echo Channel is Zeros */ | 438 | #define D_NT_EZ (1<<11) /* Echo Channel is Zeros */ |
441 | #define D_NT_IFA (1<<10) /* Inhibit Final Activation */ | 439 | #define D_NT_IFA (1<<10) /* Inhibit Final Activation */ |
@@ -455,7 +453,7 @@ struct snd_dbri { | |||
455 | #define D_TEST_RAM(v) ((v)<<16) /* RAM Pointer */ | 453 | #define D_TEST_RAM(v) ((v)<<16) /* RAM Pointer */ |
456 | #define D_TEST_SIZE(v) ((v)<<11) /* */ | 454 | #define D_TEST_SIZE(v) ((v)<<11) /* */ |
457 | #define D_TEST_ROMONOFF 0x5 /* Toggle ROM opcode monitor on/off */ | 455 | #define D_TEST_ROMONOFF 0x5 /* Toggle ROM opcode monitor on/off */ |
458 | #define D_TEST_PROC 0x6 /* MicroProcessor test */ | 456 | #define D_TEST_PROC 0x6 /* Microprocessor test */ |
459 | #define D_TEST_SER 0x7 /* Serial-Controller test */ | 457 | #define D_TEST_SER 0x7 /* Serial-Controller test */ |
460 | #define D_TEST_RAMREAD 0x8 /* Copy from Ram to system memory */ | 458 | #define D_TEST_RAMREAD 0x8 /* Copy from Ram to system memory */ |
461 | #define D_TEST_RAMWRITE 0x9 /* Copy into Ram from system memory */ | 459 | #define D_TEST_RAMWRITE 0x9 /* Copy into Ram from system memory */ |
@@ -464,12 +462,12 @@ struct snd_dbri { | |||
464 | #define D_TEST_DUMP 0xe /* ROM Dump */ | 462 | #define D_TEST_DUMP 0xe /* ROM Dump */ |
465 | 463 | ||
466 | /* CHI Data Mode */ | 464 | /* CHI Data Mode */ |
467 | #define D_CDM_THI (1<<8) /* Transmit Data on CHIDR Pin */ | 465 | #define D_CDM_THI (1 << 8) /* Transmit Data on CHIDR Pin */ |
468 | #define D_CDM_RHI (1<<7) /* Receive Data on CHIDX Pin */ | 466 | #define D_CDM_RHI (1 << 7) /* Receive Data on CHIDX Pin */ |
469 | #define D_CDM_RCE (1<<6) /* Receive on Rising Edge of CHICK */ | 467 | #define D_CDM_RCE (1 << 6) /* Receive on Rising Edge of CHICK */ |
470 | #define D_CDM_XCE (1<<2) /* Transmit Data on Rising Edge of CHICK */ | 468 | #define D_CDM_XCE (1 << 2) /* Transmit Data on Rising Edge of CHICK */ |
471 | #define D_CDM_XEN (1<<1) /* Transmit Highway Enable */ | 469 | #define D_CDM_XEN (1 << 1) /* Transmit Highway Enable */ |
472 | #define D_CDM_REN (1<<0) /* Receive Highway Enable */ | 470 | #define D_CDM_REN (1 << 0) /* Receive Highway Enable */ |
473 | 471 | ||
474 | /* The Interrupts */ | 472 | /* The Interrupts */ |
475 | #define D_INTR_BRDY 1 /* Buffer Ready for processing */ | 473 | #define D_INTR_BRDY 1 /* Buffer Ready for processing */ |
@@ -493,9 +491,9 @@ struct snd_dbri { | |||
493 | #define D_INTR_CHI 36 | 491 | #define D_INTR_CHI 36 |
494 | #define D_INTR_CMD 38 | 492 | #define D_INTR_CMD 38 |
495 | 493 | ||
496 | #define D_INTR_GETCHAN(v) (((v)>>24) & 0x3f) | 494 | #define D_INTR_GETCHAN(v) (((v) >> 24) & 0x3f) |
497 | #define D_INTR_GETCODE(v) (((v)>>20) & 0xf) | 495 | #define D_INTR_GETCODE(v) (((v) >> 20) & 0xf) |
498 | #define D_INTR_GETCMD(v) (((v)>>16) & 0xf) | 496 | #define D_INTR_GETCMD(v) (((v) >> 16) & 0xf) |
499 | #define D_INTR_GETVAL(v) ((v) & 0xffff) | 497 | #define D_INTR_GETVAL(v) ((v) & 0xffff) |
500 | #define D_INTR_GETRVAL(v) ((v) & 0xfffff) | 498 | #define D_INTR_GETRVAL(v) ((v) & 0xfffff) |
501 | 499 | ||
@@ -533,43 +531,42 @@ struct snd_dbri { | |||
533 | #define D_P_31 31 /* */ | 531 | #define D_P_31 31 /* */ |
534 | 532 | ||
535 | /* Transmit descriptor defines */ | 533 | /* Transmit descriptor defines */ |
536 | #define DBRI_TD_F (1<<31) /* End of Frame */ | 534 | #define DBRI_TD_F (1 << 31) /* End of Frame */ |
537 | #define DBRI_TD_D (1<<30) /* Do not append CRC */ | 535 | #define DBRI_TD_D (1 << 30) /* Do not append CRC */ |
538 | #define DBRI_TD_CNT(v) ((v)<<16) /* Number of valid bytes in the buffer */ | 536 | #define DBRI_TD_CNT(v) ((v) << 16) /* Number of valid bytes in the buffer */ |
539 | #define DBRI_TD_B (1<<15) /* Final interrupt */ | 537 | #define DBRI_TD_B (1 << 15) /* Final interrupt */ |
540 | #define DBRI_TD_M (1<<14) /* Marker interrupt */ | 538 | #define DBRI_TD_M (1 << 14) /* Marker interrupt */ |
541 | #define DBRI_TD_I (1<<13) /* Transmit Idle Characters */ | 539 | #define DBRI_TD_I (1 << 13) /* Transmit Idle Characters */ |
542 | #define DBRI_TD_FCNT(v) (v) /* Flag Count */ | 540 | #define DBRI_TD_FCNT(v) (v) /* Flag Count */ |
543 | #define DBRI_TD_UNR (1<<3) /* Underrun: transmitter is out of data */ | 541 | #define DBRI_TD_UNR (1 << 3) /* Underrun: transmitter is out of data */ |
544 | #define DBRI_TD_ABT (1<<2) /* Abort: frame aborted */ | 542 | #define DBRI_TD_ABT (1 << 2) /* Abort: frame aborted */ |
545 | #define DBRI_TD_TBC (1<<0) /* Transmit buffer Complete */ | 543 | #define DBRI_TD_TBC (1 << 0) /* Transmit buffer Complete */ |
546 | #define DBRI_TD_STATUS(v) ((v)&0xff) /* Transmit status */ | 544 | #define DBRI_TD_STATUS(v) ((v) & 0xff) /* Transmit status */ |
547 | /* Maximum buffer size per TD: almost 8Kb */ | 545 | /* Maximum buffer size per TD: almost 8KB */ |
548 | #define DBRI_TD_MAXCNT ((1 << 13) - 4) | 546 | #define DBRI_TD_MAXCNT ((1 << 13) - 4) |
549 | 547 | ||
550 | /* Receive descriptor defines */ | 548 | /* Receive descriptor defines */ |
551 | #define DBRI_RD_F (1<<31) /* End of Frame */ | 549 | #define DBRI_RD_F (1 << 31) /* End of Frame */ |
552 | #define DBRI_RD_C (1<<30) /* Completed buffer */ | 550 | #define DBRI_RD_C (1 << 30) /* Completed buffer */ |
553 | #define DBRI_RD_B (1<<15) /* Final interrupt */ | 551 | #define DBRI_RD_B (1 << 15) /* Final interrupt */ |
554 | #define DBRI_RD_M (1<<14) /* Marker interrupt */ | 552 | #define DBRI_RD_M (1 << 14) /* Marker interrupt */ |
555 | #define DBRI_RD_BCNT(v) (v) /* Buffer size */ | 553 | #define DBRI_RD_BCNT(v) (v) /* Buffer size */ |
556 | #define DBRI_RD_CRC (1<<7) /* 0: CRC is correct */ | 554 | #define DBRI_RD_CRC (1 << 7) /* 0: CRC is correct */ |
557 | #define DBRI_RD_BBC (1<<6) /* 1: Bad Byte received */ | 555 | #define DBRI_RD_BBC (1 << 6) /* 1: Bad Byte received */ |
558 | #define DBRI_RD_ABT (1<<5) /* Abort: frame aborted */ | 556 | #define DBRI_RD_ABT (1 << 5) /* Abort: frame aborted */ |
559 | #define DBRI_RD_OVRN (1<<3) /* Overrun: data lost */ | 557 | #define DBRI_RD_OVRN (1 << 3) /* Overrun: data lost */ |
560 | #define DBRI_RD_STATUS(v) ((v)&0xff) /* Receive status */ | 558 | #define DBRI_RD_STATUS(v) ((v) & 0xff) /* Receive status */ |
561 | #define DBRI_RD_CNT(v) (((v)>>16)&0x1fff) /* Valid bytes in the buffer */ | 559 | #define DBRI_RD_CNT(v) (((v) >> 16) & 0x1fff) /* Valid bytes in the buffer */ |
562 | 560 | ||
563 | /* stream_info[] access */ | 561 | /* stream_info[] access */ |
564 | /* Translate the ALSA direction into the array index */ | 562 | /* Translate the ALSA direction into the array index */ |
565 | #define DBRI_STREAMNO(substream) \ | 563 | #define DBRI_STREAMNO(substream) \ |
566 | (substream->stream == \ | 564 | (substream->stream == \ |
567 | SNDRV_PCM_STREAM_PLAYBACK? DBRI_PLAY: DBRI_REC) | 565 | SNDRV_PCM_STREAM_PLAYBACK ? DBRI_PLAY: DBRI_REC) |
568 | 566 | ||
569 | /* Return a pointer to dbri_streaminfo */ | 567 | /* Return a pointer to dbri_streaminfo */ |
570 | #define DBRI_STREAM(dbri, substream) &dbri->stream_info[DBRI_STREAMNO(substream)] | 568 | #define DBRI_STREAM(dbri, substream) \ |
571 | 569 | &dbri->stream_info[DBRI_STREAMNO(substream)] | |
572 | static struct snd_dbri *dbri_list; /* All DBRI devices */ | ||
573 | 570 | ||
574 | /* | 571 | /* |
575 | * Short data pipes transmit LSB first. The CS4215 receives MSB first. Grrr. | 572 | * Short data pipes transmit LSB first. The CS4215 receives MSB first. Grrr. |
@@ -609,21 +606,21 @@ The list is terminated with a WAIT command, which generates a | |||
609 | CPU interrupt to signal completion. | 606 | CPU interrupt to signal completion. |
610 | 607 | ||
611 | Since the DBRI can run in parallel with the CPU, several means of | 608 | Since the DBRI can run in parallel with the CPU, several means of |
612 | synchronization present themselves. The method implemented here is only | 609 | synchronization present themselves. The method implemented here uses |
613 | use of the dbri_cmdwait() to wait for execution of batch of sent commands. | 610 | the dbri_cmdwait() to wait for execution of batch of sent commands. |
614 | 611 | ||
615 | A circular command buffer is used here. A new command is being added | 612 | A circular command buffer is used here. A new command is being added |
616 | while another can be executed. The scheme works by adding two WAIT commands | 613 | while another can be executed. The scheme works by adding two WAIT commands |
617 | after each sent batch of commands. When the next batch is prepared it is | 614 | after each sent batch of commands. When the next batch is prepared it is |
618 | added after the WAIT commands then the WAITs are replaced with single JUMP | 615 | added after the WAIT commands then the WAITs are replaced with single JUMP |
619 | command to the new batch. The the DBRI is forced to reread the last WAIT | 616 | command to the new batch. The the DBRI is forced to reread the last WAIT |
620 | command (replaced by the JUMP by then). If the DBRI is still executing | 617 | command (replaced by the JUMP by then). If the DBRI is still executing |
621 | previous commands the request to reread the WAIT command is ignored. | 618 | previous commands the request to reread the WAIT command is ignored. |
622 | 619 | ||
623 | Every time a routine wants to write commands to the DBRI, it must | 620 | Every time a routine wants to write commands to the DBRI, it must |
624 | first call dbri_cmdlock() and get pointer to a free space in | 621 | first call dbri_cmdlock() and get pointer to a free space in |
625 | dbri->dma->cmd buffer. After this, the commands can be written to | 622 | dbri->dma->cmd buffer. After this, the commands can be written to |
626 | the buffer, and dbri_cmdsend() is called with the final pointer value | 623 | the buffer, and dbri_cmdsend() is called with the final pointer value |
627 | to send them to the DBRI. | 624 | to send them to the DBRI. |
628 | 625 | ||
629 | */ | 626 | */ |
@@ -646,18 +643,17 @@ static void dbri_cmdwait(struct snd_dbri *dbri) | |||
646 | } | 643 | } |
647 | spin_unlock_irqrestore(&dbri->lock, flags); | 644 | spin_unlock_irqrestore(&dbri->lock, flags); |
648 | 645 | ||
649 | if (maxloops == 0) { | 646 | if (maxloops == 0) |
650 | printk(KERN_ERR "DBRI: Chip never completed command buffer\n"); | 647 | printk(KERN_ERR "DBRI: Chip never completed command buffer\n"); |
651 | } else { | 648 | else |
652 | dprintk(D_CMD, "Chip completed command buffer (%d)\n", | 649 | dprintk(D_CMD, "Chip completed command buffer (%d)\n", |
653 | MAXLOOPS - maxloops - 1); | 650 | MAXLOOPS - maxloops - 1); |
654 | } | ||
655 | } | 651 | } |
656 | /* | 652 | /* |
657 | * Lock the command queue and returns pointer to a space for len cmd words | 653 | * Lock the command queue and return pointer to space for len cmd words |
658 | * It locks the cmdlock spinlock. | 654 | * It locks the cmdlock spinlock. |
659 | */ | 655 | */ |
660 | static s32 *dbri_cmdlock(struct snd_dbri * dbri, int len) | 656 | static s32 *dbri_cmdlock(struct snd_dbri *dbri, int len) |
661 | { | 657 | { |
662 | /* Space for 2 WAIT cmds (replaced later by 1 JUMP cmd) */ | 658 | /* Space for 2 WAIT cmds (replaced later by 1 JUMP cmd) */ |
663 | len += 2; | 659 | len += 2; |
@@ -680,7 +676,7 @@ static s32 *dbri_cmdlock(struct snd_dbri * dbri, int len) | |||
680 | * | 676 | * |
681 | * Lock must be held before calling this. | 677 | * Lock must be held before calling this. |
682 | */ | 678 | */ |
683 | static void dbri_cmdsend(struct snd_dbri * dbri, s32 * cmd,int len) | 679 | static void dbri_cmdsend(struct snd_dbri *dbri, s32 *cmd, int len) |
684 | { | 680 | { |
685 | s32 tmp, addr; | 681 | s32 tmp, addr; |
686 | static int wait_id = 0; | 682 | static int wait_id = 0; |
@@ -700,16 +696,17 @@ static void dbri_cmdsend(struct snd_dbri * dbri, s32 * cmd,int len) | |||
700 | s32 *ptr; | 696 | s32 *ptr; |
701 | 697 | ||
702 | for (ptr = dbri->cmdptr; ptr < cmd+2; ptr++) | 698 | for (ptr = dbri->cmdptr; ptr < cmd+2; ptr++) |
703 | dprintk(D_CMD, "cmd: %lx:%08x\n", (unsigned long)ptr, *ptr); | 699 | dprintk(D_CMD, "cmd: %lx:%08x\n", |
700 | (unsigned long)ptr, *ptr); | ||
704 | } else { | 701 | } else { |
705 | s32 *ptr = dbri->cmdptr; | 702 | s32 *ptr = dbri->cmdptr; |
706 | 703 | ||
707 | dprintk(D_CMD, "cmd: %lx:%08x\n", (unsigned long)ptr, *ptr); | 704 | dprintk(D_CMD, "cmd: %lx:%08x\n", (unsigned long)ptr, *ptr); |
708 | ptr++; | 705 | ptr++; |
709 | dprintk(D_CMD, "cmd: %lx:%08x\n", (unsigned long)ptr, *ptr); | 706 | dprintk(D_CMD, "cmd: %lx:%08x\n", (unsigned long)ptr, *ptr); |
710 | for (ptr = dbri->dma->cmd; ptr < cmd+2; ptr++) { | 707 | for (ptr = dbri->dma->cmd; ptr < cmd+2; ptr++) |
711 | dprintk(D_CMD, "cmd: %lx:%08x\n", (unsigned long)ptr, *ptr); | 708 | dprintk(D_CMD, "cmd: %lx:%08x\n", |
712 | } | 709 | (unsigned long)ptr, *ptr); |
713 | } | 710 | } |
714 | #endif | 711 | #endif |
715 | 712 | ||
@@ -723,7 +720,7 @@ static void dbri_cmdsend(struct snd_dbri * dbri, s32 * cmd,int len) | |||
723 | } | 720 | } |
724 | 721 | ||
725 | /* Lock must be held when calling this */ | 722 | /* Lock must be held when calling this */ |
726 | static void dbri_reset(struct snd_dbri * dbri) | 723 | static void dbri_reset(struct snd_dbri *dbri) |
727 | { | 724 | { |
728 | int i; | 725 | int i; |
729 | u32 tmp; | 726 | u32 tmp; |
@@ -746,7 +743,7 @@ static void dbri_reset(struct snd_dbri * dbri) | |||
746 | } | 743 | } |
747 | 744 | ||
748 | /* Lock must not be held before calling this */ | 745 | /* Lock must not be held before calling this */ |
749 | static void dbri_initialize(struct snd_dbri * dbri) | 746 | static void __devinit dbri_initialize(struct snd_dbri *dbri) |
750 | { | 747 | { |
751 | s32 *cmd; | 748 | s32 *cmd; |
752 | u32 dma_addr; | 749 | u32 dma_addr; |
@@ -763,7 +760,7 @@ static void dbri_initialize(struct snd_dbri * dbri) | |||
763 | 760 | ||
764 | spin_lock_init(&dbri->cmdlock); | 761 | spin_lock_init(&dbri->cmdlock); |
765 | /* | 762 | /* |
766 | * Initialize the interrupt ringbuffer. | 763 | * Initialize the interrupt ring buffer. |
767 | */ | 764 | */ |
768 | dma_addr = dbri->dma_dvma + dbri_dma_off(intr, 0); | 765 | dma_addr = dbri->dma_dvma + dbri_dma_off(intr, 0); |
769 | dbri->dma->intr[0] = dma_addr; | 766 | dbri->dma->intr[0] = dma_addr; |
@@ -801,7 +798,7 @@ list ordering, among other things. The transmit and receive functions | |||
801 | here interface closely with the transmit and receive interrupt code. | 798 | here interface closely with the transmit and receive interrupt code. |
802 | 799 | ||
803 | */ | 800 | */ |
804 | static int pipe_active(struct snd_dbri * dbri, int pipe) | 801 | static inline int pipe_active(struct snd_dbri *dbri, int pipe) |
805 | { | 802 | { |
806 | return ((pipe >= 0) && (dbri->pipes[pipe].desc != -1)); | 803 | return ((pipe >= 0) && (dbri->pipes[pipe].desc != -1)); |
807 | } | 804 | } |
@@ -811,20 +808,22 @@ static int pipe_active(struct snd_dbri * dbri, int pipe) | |||
811 | * Called on an in-use pipe to clear anything being transmitted or received | 808 | * Called on an in-use pipe to clear anything being transmitted or received |
812 | * Lock must be held before calling this. | 809 | * Lock must be held before calling this. |
813 | */ | 810 | */ |
814 | static void reset_pipe(struct snd_dbri * dbri, int pipe) | 811 | static void reset_pipe(struct snd_dbri *dbri, int pipe) |
815 | { | 812 | { |
816 | int sdp; | 813 | int sdp; |
817 | int desc; | 814 | int desc; |
818 | s32 *cmd; | 815 | s32 *cmd; |
819 | 816 | ||
820 | if (pipe < 0 || pipe > DBRI_MAX_PIPE) { | 817 | if (pipe < 0 || pipe > DBRI_MAX_PIPE) { |
821 | printk(KERN_ERR "DBRI: reset_pipe called with illegal pipe number\n"); | 818 | printk(KERN_ERR "DBRI: reset_pipe called with " |
819 | "illegal pipe number\n"); | ||
822 | return; | 820 | return; |
823 | } | 821 | } |
824 | 822 | ||
825 | sdp = dbri->pipes[pipe].sdp; | 823 | sdp = dbri->pipes[pipe].sdp; |
826 | if (sdp == 0) { | 824 | if (sdp == 0) { |
827 | printk(KERN_ERR "DBRI: reset_pipe called on uninitialized pipe\n"); | 825 | printk(KERN_ERR "DBRI: reset_pipe called " |
826 | "on uninitialized pipe\n"); | ||
828 | return; | 827 | return; |
829 | } | 828 | } |
830 | 829 | ||
@@ -835,9 +834,10 @@ static void reset_pipe(struct snd_dbri * dbri, int pipe) | |||
835 | dbri_cmdsend(dbri, cmd, 3); | 834 | dbri_cmdsend(dbri, cmd, 3); |
836 | 835 | ||
837 | desc = dbri->pipes[pipe].first_desc; | 836 | desc = dbri->pipes[pipe].first_desc; |
838 | if ( desc >= 0) | 837 | if (desc >= 0) |
839 | do { | 838 | do { |
840 | dbri->dma->desc[desc].nda = dbri->dma->desc[desc].ba = 0; | 839 | dbri->dma->desc[desc].ba = 0; |
840 | dbri->dma->desc[desc].nda = 0; | ||
841 | desc = dbri->next_desc[desc]; | 841 | desc = dbri->next_desc[desc]; |
842 | } while (desc != -1 && desc != dbri->pipes[pipe].first_desc); | 842 | } while (desc != -1 && desc != dbri->pipes[pipe].first_desc); |
843 | 843 | ||
@@ -848,15 +848,17 @@ static void reset_pipe(struct snd_dbri * dbri, int pipe) | |||
848 | /* | 848 | /* |
849 | * Lock must be held before calling this. | 849 | * Lock must be held before calling this. |
850 | */ | 850 | */ |
851 | static void setup_pipe(struct snd_dbri * dbri, int pipe, int sdp) | 851 | static void setup_pipe(struct snd_dbri *dbri, int pipe, int sdp) |
852 | { | 852 | { |
853 | if (pipe < 0 || pipe > DBRI_MAX_PIPE) { | 853 | if (pipe < 0 || pipe > DBRI_MAX_PIPE) { |
854 | printk(KERN_ERR "DBRI: setup_pipe called with illegal pipe number\n"); | 854 | printk(KERN_ERR "DBRI: setup_pipe called " |
855 | "with illegal pipe number\n"); | ||
855 | return; | 856 | return; |
856 | } | 857 | } |
857 | 858 | ||
858 | if ((sdp & 0xf800) != sdp) { | 859 | if ((sdp & 0xf800) != sdp) { |
859 | printk(KERN_ERR "DBRI: setup_pipe called with strange SDP value\n"); | 860 | printk(KERN_ERR "DBRI: setup_pipe called " |
861 | "with strange SDP value\n"); | ||
860 | /* sdp &= 0xf800; */ | 862 | /* sdp &= 0xf800; */ |
861 | } | 863 | } |
862 | 864 | ||
@@ -877,25 +879,26 @@ static void setup_pipe(struct snd_dbri * dbri, int pipe, int sdp) | |||
877 | /* | 879 | /* |
878 | * Lock must be held before calling this. | 880 | * Lock must be held before calling this. |
879 | */ | 881 | */ |
880 | static void link_time_slot(struct snd_dbri * dbri, int pipe, | 882 | static void link_time_slot(struct snd_dbri *dbri, int pipe, |
881 | int prevpipe, int nextpipe, | 883 | int prevpipe, int nextpipe, |
882 | int length, int cycle) | 884 | int length, int cycle) |
883 | { | 885 | { |
884 | s32 *cmd; | 886 | s32 *cmd; |
885 | int val; | 887 | int val; |
886 | 888 | ||
887 | if (pipe < 0 || pipe > DBRI_MAX_PIPE | 889 | if (pipe < 0 || pipe > DBRI_MAX_PIPE |
888 | || prevpipe < 0 || prevpipe > DBRI_MAX_PIPE | 890 | || prevpipe < 0 || prevpipe > DBRI_MAX_PIPE |
889 | || nextpipe < 0 || nextpipe > DBRI_MAX_PIPE) { | 891 | || nextpipe < 0 || nextpipe > DBRI_MAX_PIPE) { |
890 | printk(KERN_ERR | 892 | printk(KERN_ERR |
891 | "DBRI: link_time_slot called with illegal pipe number\n"); | 893 | "DBRI: link_time_slot called with illegal pipe number\n"); |
892 | return; | 894 | return; |
893 | } | 895 | } |
894 | 896 | ||
895 | if (dbri->pipes[pipe].sdp == 0 | 897 | if (dbri->pipes[pipe].sdp == 0 |
896 | || dbri->pipes[prevpipe].sdp == 0 | 898 | || dbri->pipes[prevpipe].sdp == 0 |
897 | || dbri->pipes[nextpipe].sdp == 0) { | 899 | || dbri->pipes[nextpipe].sdp == 0) { |
898 | printk(KERN_ERR "DBRI: link_time_slot called on uninitialized pipe\n"); | 900 | printk(KERN_ERR "DBRI: link_time_slot called " |
901 | "on uninitialized pipe\n"); | ||
899 | return; | 902 | return; |
900 | } | 903 | } |
901 | 904 | ||
@@ -935,17 +938,17 @@ static void link_time_slot(struct snd_dbri * dbri, int pipe, | |||
935 | /* | 938 | /* |
936 | * Lock must be held before calling this. | 939 | * Lock must be held before calling this. |
937 | */ | 940 | */ |
938 | static void unlink_time_slot(struct snd_dbri * dbri, int pipe, | 941 | static void unlink_time_slot(struct snd_dbri *dbri, int pipe, |
939 | enum in_or_out direction, int prevpipe, | 942 | enum in_or_out direction, int prevpipe, |
940 | int nextpipe) | 943 | int nextpipe) |
941 | { | 944 | { |
942 | s32 *cmd; | 945 | s32 *cmd; |
943 | int val; | 946 | int val; |
944 | 947 | ||
945 | if (pipe < 0 || pipe > DBRI_MAX_PIPE | 948 | if (pipe < 0 || pipe > DBRI_MAX_PIPE |
946 | || prevpipe < 0 || prevpipe > DBRI_MAX_PIPE | 949 | || prevpipe < 0 || prevpipe > DBRI_MAX_PIPE |
947 | || nextpipe < 0 || nextpipe > DBRI_MAX_PIPE) { | 950 | || nextpipe < 0 || nextpipe > DBRI_MAX_PIPE) { |
948 | printk(KERN_ERR | 951 | printk(KERN_ERR |
949 | "DBRI: unlink_time_slot called with illegal pipe number\n"); | 952 | "DBRI: unlink_time_slot called with illegal pipe number\n"); |
950 | return; | 953 | return; |
951 | } | 954 | } |
@@ -985,7 +988,7 @@ static void unlink_time_slot(struct snd_dbri * dbri, int pipe, | |||
985 | * | 988 | * |
986 | * Lock must not be held before calling it. | 989 | * Lock must not be held before calling it. |
987 | */ | 990 | */ |
988 | static void xmit_fixed(struct snd_dbri * dbri, int pipe, unsigned int data) | 991 | static void xmit_fixed(struct snd_dbri *dbri, int pipe, unsigned int data) |
989 | { | 992 | { |
990 | s32 *cmd; | 993 | s32 *cmd; |
991 | unsigned long flags; | 994 | unsigned long flags; |
@@ -996,7 +999,8 @@ static void xmit_fixed(struct snd_dbri * dbri, int pipe, unsigned int data) | |||
996 | } | 999 | } |
997 | 1000 | ||
998 | if (D_SDP_MODE(dbri->pipes[pipe].sdp) == 0) { | 1001 | if (D_SDP_MODE(dbri->pipes[pipe].sdp) == 0) { |
999 | printk(KERN_ERR "DBRI: xmit_fixed: Uninitialized pipe %d\n", pipe); | 1002 | printk(KERN_ERR "DBRI: xmit_fixed: " |
1003 | "Uninitialized pipe %d\n", pipe); | ||
1000 | return; | 1004 | return; |
1001 | } | 1005 | } |
1002 | 1006 | ||
@@ -1006,7 +1010,8 @@ static void xmit_fixed(struct snd_dbri * dbri, int pipe, unsigned int data) | |||
1006 | } | 1010 | } |
1007 | 1011 | ||
1008 | if (!(dbri->pipes[pipe].sdp & D_SDP_TO_SER)) { | 1012 | if (!(dbri->pipes[pipe].sdp & D_SDP_TO_SER)) { |
1009 | printk(KERN_ERR "DBRI: xmit_fixed: Called on receive pipe %d\n", pipe); | 1013 | printk(KERN_ERR "DBRI: xmit_fixed: Called on receive pipe %d\n", |
1014 | pipe); | ||
1010 | return; | 1015 | return; |
1011 | } | 1016 | } |
1012 | 1017 | ||
@@ -1028,20 +1033,23 @@ static void xmit_fixed(struct snd_dbri * dbri, int pipe, unsigned int data) | |||
1028 | 1033 | ||
1029 | } | 1034 | } |
1030 | 1035 | ||
1031 | static void recv_fixed(struct snd_dbri * dbri, int pipe, volatile __u32 * ptr) | 1036 | static void recv_fixed(struct snd_dbri *dbri, int pipe, volatile __u32 *ptr) |
1032 | { | 1037 | { |
1033 | if (pipe < 16 || pipe > DBRI_MAX_PIPE) { | 1038 | if (pipe < 16 || pipe > DBRI_MAX_PIPE) { |
1034 | printk(KERN_ERR "DBRI: recv_fixed called with illegal pipe number\n"); | 1039 | printk(KERN_ERR "DBRI: recv_fixed called with " |
1040 | "illegal pipe number\n"); | ||
1035 | return; | 1041 | return; |
1036 | } | 1042 | } |
1037 | 1043 | ||
1038 | if (D_SDP_MODE(dbri->pipes[pipe].sdp) != D_SDP_FIXED) { | 1044 | if (D_SDP_MODE(dbri->pipes[pipe].sdp) != D_SDP_FIXED) { |
1039 | printk(KERN_ERR "DBRI: recv_fixed called on non-fixed pipe %d\n", pipe); | 1045 | printk(KERN_ERR "DBRI: recv_fixed called on " |
1046 | "non-fixed pipe %d\n", pipe); | ||
1040 | return; | 1047 | return; |
1041 | } | 1048 | } |
1042 | 1049 | ||
1043 | if (dbri->pipes[pipe].sdp & D_SDP_TO_SER) { | 1050 | if (dbri->pipes[pipe].sdp & D_SDP_TO_SER) { |
1044 | printk(KERN_ERR "DBRI: recv_fixed called on transmit pipe %d\n", pipe); | 1051 | printk(KERN_ERR "DBRI: recv_fixed called on " |
1052 | "transmit pipe %d\n", pipe); | ||
1045 | return; | 1053 | return; |
1046 | } | 1054 | } |
1047 | 1055 | ||
@@ -1064,7 +1072,7 @@ static void recv_fixed(struct snd_dbri * dbri, int pipe, volatile __u32 * ptr) | |||
1064 | * | 1072 | * |
1065 | * Lock must be held before calling this. | 1073 | * Lock must be held before calling this. |
1066 | */ | 1074 | */ |
1067 | static int setup_descs(struct snd_dbri * dbri, int streamno, unsigned int period) | 1075 | static int setup_descs(struct snd_dbri *dbri, int streamno, unsigned int period) |
1068 | { | 1076 | { |
1069 | struct dbri_streaminfo *info = &dbri->stream_info[streamno]; | 1077 | struct dbri_streaminfo *info = &dbri->stream_info[streamno]; |
1070 | __u32 dvma_buffer; | 1078 | __u32 dvma_buffer; |
@@ -1089,21 +1097,23 @@ static int setup_descs(struct snd_dbri * dbri, int streamno, unsigned int period | |||
1089 | 1097 | ||
1090 | if (streamno == DBRI_PLAY) { | 1098 | if (streamno == DBRI_PLAY) { |
1091 | if (!(dbri->pipes[info->pipe].sdp & D_SDP_TO_SER)) { | 1099 | if (!(dbri->pipes[info->pipe].sdp & D_SDP_TO_SER)) { |
1092 | printk(KERN_ERR "DBRI: setup_descs: Called on receive pipe %d\n", | 1100 | printk(KERN_ERR "DBRI: setup_descs: " |
1093 | info->pipe); | 1101 | "Called on receive pipe %d\n", info->pipe); |
1094 | return -2; | 1102 | return -2; |
1095 | } | 1103 | } |
1096 | } else { | 1104 | } else { |
1097 | if (dbri->pipes[info->pipe].sdp & D_SDP_TO_SER) { | 1105 | if (dbri->pipes[info->pipe].sdp & D_SDP_TO_SER) { |
1098 | printk(KERN_ERR | 1106 | printk(KERN_ERR |
1099 | "DBRI: setup_descs: Called on transmit pipe %d\n", | 1107 | "DBRI: setup_descs: Called on transmit pipe %d\n", |
1100 | info->pipe); | 1108 | info->pipe); |
1101 | return -2; | 1109 | return -2; |
1102 | } | 1110 | } |
1103 | /* Should be able to queue multiple buffers to receive on a pipe */ | 1111 | /* Should be able to queue multiple buffers |
1112 | * to receive on a pipe | ||
1113 | */ | ||
1104 | if (pipe_active(dbri, info->pipe)) { | 1114 | if (pipe_active(dbri, info->pipe)) { |
1105 | printk(KERN_ERR "DBRI: recv_on_pipe: Called on active pipe %d\n", | 1115 | printk(KERN_ERR "DBRI: recv_on_pipe: " |
1106 | info->pipe); | 1116 | "Called on active pipe %d\n", info->pipe); |
1107 | return -2; | 1117 | return -2; |
1108 | } | 1118 | } |
1109 | 1119 | ||
@@ -1113,11 +1123,13 @@ static int setup_descs(struct snd_dbri * dbri, int streamno, unsigned int period | |||
1113 | 1123 | ||
1114 | /* Free descriptors if pipe has any */ | 1124 | /* Free descriptors if pipe has any */ |
1115 | desc = dbri->pipes[info->pipe].first_desc; | 1125 | desc = dbri->pipes[info->pipe].first_desc; |
1116 | if ( desc >= 0) | 1126 | if (desc >= 0) |
1117 | do { | 1127 | do { |
1118 | dbri->dma->desc[desc].nda = dbri->dma->desc[desc].ba = 0; | 1128 | dbri->dma->desc[desc].ba = 0; |
1129 | dbri->dma->desc[desc].nda = 0; | ||
1119 | desc = dbri->next_desc[desc]; | 1130 | desc = dbri->next_desc[desc]; |
1120 | } while (desc != -1 && desc != dbri->pipes[info->pipe].first_desc); | 1131 | } while (desc != -1 && |
1132 | desc != dbri->pipes[info->pipe].first_desc); | ||
1121 | 1133 | ||
1122 | dbri->pipes[info->pipe].desc = -1; | 1134 | dbri->pipes[info->pipe].desc = -1; |
1123 | dbri->pipes[info->pipe].first_desc = -1; | 1135 | dbri->pipes[info->pipe].first_desc = -1; |
@@ -1130,6 +1142,7 @@ static int setup_descs(struct snd_dbri * dbri, int streamno, unsigned int period | |||
1130 | if (!dbri->dma->desc[desc].ba) | 1142 | if (!dbri->dma->desc[desc].ba) |
1131 | break; | 1143 | break; |
1132 | } | 1144 | } |
1145 | |||
1133 | if (desc == DBRI_NO_DESCS) { | 1146 | if (desc == DBRI_NO_DESCS) { |
1134 | printk(KERN_ERR "DBRI: setup_descs: No descriptors\n"); | 1147 | printk(KERN_ERR "DBRI: setup_descs: No descriptors\n"); |
1135 | return -1; | 1148 | return -1; |
@@ -1150,8 +1163,7 @@ static int setup_descs(struct snd_dbri * dbri, int streamno, unsigned int period | |||
1150 | if (streamno == DBRI_PLAY) { | 1163 | if (streamno == DBRI_PLAY) { |
1151 | dbri->dma->desc[desc].word1 = DBRI_TD_CNT(mylen); | 1164 | dbri->dma->desc[desc].word1 = DBRI_TD_CNT(mylen); |
1152 | dbri->dma->desc[desc].word4 = 0; | 1165 | dbri->dma->desc[desc].word4 = 0; |
1153 | dbri->dma->desc[desc].word1 |= | 1166 | dbri->dma->desc[desc].word1 |= DBRI_TD_F | DBRI_TD_B; |
1154 | DBRI_TD_F | DBRI_TD_B; | ||
1155 | } else { | 1167 | } else { |
1156 | dbri->dma->desc[desc].word1 = 0; | 1168 | dbri->dma->desc[desc].word1 = 0; |
1157 | dbri->dma->desc[desc].word4 = | 1169 | dbri->dma->desc[desc].word4 = |
@@ -1172,7 +1184,8 @@ static int setup_descs(struct snd_dbri * dbri, int streamno, unsigned int period | |||
1172 | } | 1184 | } |
1173 | 1185 | ||
1174 | if (first_desc == -1 || last_desc == -1) { | 1186 | if (first_desc == -1 || last_desc == -1) { |
1175 | printk(KERN_ERR "DBRI: setup_descs: Not enough descriptors available\n"); | 1187 | printk(KERN_ERR "DBRI: setup_descs: " |
1188 | " Not enough descriptors available\n"); | ||
1176 | return -1; | 1189 | return -1; |
1177 | } | 1190 | } |
1178 | 1191 | ||
@@ -1183,14 +1196,14 @@ static int setup_descs(struct snd_dbri * dbri, int streamno, unsigned int period | |||
1183 | dbri->pipes[info->pipe].desc = first_desc; | 1196 | dbri->pipes[info->pipe].desc = first_desc; |
1184 | 1197 | ||
1185 | #ifdef DBRI_DEBUG | 1198 | #ifdef DBRI_DEBUG |
1186 | for (desc = first_desc; desc != -1; ) { | 1199 | for (desc = first_desc; desc != -1;) { |
1187 | dprintk(D_DESC, "DESC %d: %08x %08x %08x %08x\n", | 1200 | dprintk(D_DESC, "DESC %d: %08x %08x %08x %08x\n", |
1188 | desc, | 1201 | desc, |
1189 | dbri->dma->desc[desc].word1, | 1202 | dbri->dma->desc[desc].word1, |
1190 | dbri->dma->desc[desc].ba, | 1203 | dbri->dma->desc[desc].ba, |
1191 | dbri->dma->desc[desc].nda, dbri->dma->desc[desc].word4); | 1204 | dbri->dma->desc[desc].nda, dbri->dma->desc[desc].word4); |
1192 | desc = dbri->next_desc[desc]; | 1205 | desc = dbri->next_desc[desc]; |
1193 | if ( desc == first_desc ) | 1206 | if (desc == first_desc) |
1194 | break; | 1207 | break; |
1195 | } | 1208 | } |
1196 | #endif | 1209 | #endif |
@@ -1213,7 +1226,8 @@ enum master_or_slave { CHImaster, CHIslave }; | |||
1213 | /* | 1226 | /* |
1214 | * Lock must not be held before calling it. | 1227 | * Lock must not be held before calling it. |
1215 | */ | 1228 | */ |
1216 | static void reset_chi(struct snd_dbri * dbri, enum master_or_slave master_or_slave, | 1229 | static void reset_chi(struct snd_dbri *dbri, |
1230 | enum master_or_slave master_or_slave, | ||
1217 | int bits_per_frame) | 1231 | int bits_per_frame) |
1218 | { | 1232 | { |
1219 | s32 *cmd; | 1233 | s32 *cmd; |
@@ -1222,7 +1236,7 @@ static void reset_chi(struct snd_dbri * dbri, enum master_or_slave master_or_sla | |||
1222 | /* Set CHI Anchor: Pipe 16 */ | 1236 | /* Set CHI Anchor: Pipe 16 */ |
1223 | 1237 | ||
1224 | cmd = dbri_cmdlock(dbri, 4); | 1238 | cmd = dbri_cmdlock(dbri, 4); |
1225 | val = D_DTS_VO | D_DTS_VI | D_DTS_INS | 1239 | val = D_DTS_VO | D_DTS_VI | D_DTS_INS |
1226 | | D_DTS_PRVIN(16) | D_PIPE(16) | D_DTS_PRVOUT(16); | 1240 | | D_DTS_PRVIN(16) | D_PIPE(16) | D_DTS_PRVOUT(16); |
1227 | *(cmd++) = DBRI_CMD(D_DTS, 0, val); | 1241 | *(cmd++) = DBRI_CMD(D_DTS, 0, val); |
1228 | *(cmd++) = D_TS_ANCHOR | D_TS_NEXT(16); | 1242 | *(cmd++) = D_TS_ANCHOR | D_TS_NEXT(16); |
@@ -1246,15 +1260,16 @@ static void reset_chi(struct snd_dbri * dbri, enum master_or_slave master_or_sla | |||
1246 | } else { | 1260 | } else { |
1247 | /* Setup DBRI for CHI Master - generate clock, FS | 1261 | /* Setup DBRI for CHI Master - generate clock, FS |
1248 | * | 1262 | * |
1249 | * BPF = bits per 8 kHz frame | 1263 | * BPF = bits per 8 kHz frame |
1250 | * 12.288 MHz / CHICM_divisor = clock rate | 1264 | * 12.288 MHz / CHICM_divisor = clock rate |
1251 | * FD = 1 - drive CHIFS on rising edge of CHICK | 1265 | * FD = 1 - drive CHIFS on rising edge of CHICK |
1252 | */ | 1266 | */ |
1253 | int clockrate = bits_per_frame * 8; | 1267 | int clockrate = bits_per_frame * 8; |
1254 | int divisor = 12288 / clockrate; | 1268 | int divisor = 12288 / clockrate; |
1255 | 1269 | ||
1256 | if (divisor > 255 || divisor * clockrate != 12288) | 1270 | if (divisor > 255 || divisor * clockrate != 12288) |
1257 | printk(KERN_ERR "DBRI: illegal bits_per_frame in setup_chi\n"); | 1271 | printk(KERN_ERR "DBRI: illegal bits_per_frame " |
1272 | "in setup_chi\n"); | ||
1258 | 1273 | ||
1259 | *(cmd++) = DBRI_CMD(D_CHI, 0, D_CHI_CHICM(divisor) | D_CHI_FD | 1274 | *(cmd++) = DBRI_CMD(D_CHI, 0, D_CHI_CHICM(divisor) | D_CHI_FD |
1260 | | D_CHI_BPF(bits_per_frame)); | 1275 | | D_CHI_BPF(bits_per_frame)); |
@@ -1288,7 +1303,7 @@ to the DBRI via the CHI interface and few of the DBRI's PIO pins. | |||
1288 | * Lock must not be held before calling it. | 1303 | * Lock must not be held before calling it. |
1289 | 1304 | ||
1290 | */ | 1305 | */ |
1291 | static void cs4215_setup_pipes(struct snd_dbri * dbri) | 1306 | static __devinit void cs4215_setup_pipes(struct snd_dbri *dbri) |
1292 | { | 1307 | { |
1293 | unsigned long flags; | 1308 | unsigned long flags; |
1294 | 1309 | ||
@@ -1303,9 +1318,9 @@ static void cs4215_setup_pipes(struct snd_dbri * dbri) | |||
1303 | * not relevant for us (only for doublechecking). | 1318 | * not relevant for us (only for doublechecking). |
1304 | * | 1319 | * |
1305 | * Control mode: | 1320 | * Control mode: |
1306 | * Pipe 17: Send timeslots 1-4 (slots 5-8 are readonly) | 1321 | * Pipe 17: Send timeslots 1-4 (slots 5-8 are read only) |
1307 | * Pipe 18: Receive timeslot 1 (clb). | 1322 | * Pipe 18: Receive timeslot 1 (clb). |
1308 | * Pipe 19: Receive timeslot 7 (version). | 1323 | * Pipe 19: Receive timeslot 7 (version). |
1309 | */ | 1324 | */ |
1310 | 1325 | ||
1311 | setup_pipe(dbri, 4, D_SDP_MEM | D_SDP_TO_SER | D_SDP_MSB); | 1326 | setup_pipe(dbri, 4, D_SDP_MEM | D_SDP_TO_SER | D_SDP_MSB); |
@@ -1321,7 +1336,7 @@ static void cs4215_setup_pipes(struct snd_dbri * dbri) | |||
1321 | dbri_cmdwait(dbri); | 1336 | dbri_cmdwait(dbri); |
1322 | } | 1337 | } |
1323 | 1338 | ||
1324 | static int cs4215_init_data(struct cs4215 *mm) | 1339 | static __devinit int cs4215_init_data(struct cs4215 *mm) |
1325 | { | 1340 | { |
1326 | /* | 1341 | /* |
1327 | * No action, memory resetting only. | 1342 | * No action, memory resetting only. |
@@ -1355,7 +1370,7 @@ static int cs4215_init_data(struct cs4215 *mm) | |||
1355 | return 0; | 1370 | return 0; |
1356 | } | 1371 | } |
1357 | 1372 | ||
1358 | static void cs4215_setdata(struct snd_dbri * dbri, int muted) | 1373 | static void cs4215_setdata(struct snd_dbri *dbri, int muted) |
1359 | { | 1374 | { |
1360 | if (muted) { | 1375 | if (muted) { |
1361 | dbri->mm.data[0] |= 63; | 1376 | dbri->mm.data[0] |= 63; |
@@ -1387,7 +1402,7 @@ static void cs4215_setdata(struct snd_dbri * dbri, int muted) | |||
1387 | /* | 1402 | /* |
1388 | * Set the CS4215 to data mode. | 1403 | * Set the CS4215 to data mode. |
1389 | */ | 1404 | */ |
1390 | static void cs4215_open(struct snd_dbri * dbri) | 1405 | static void cs4215_open(struct snd_dbri *dbri) |
1391 | { | 1406 | { |
1392 | int data_width; | 1407 | int data_width; |
1393 | u32 tmp; | 1408 | u32 tmp; |
@@ -1452,7 +1467,7 @@ static void cs4215_open(struct snd_dbri * dbri) | |||
1452 | /* | 1467 | /* |
1453 | * Send the control information (i.e. audio format) | 1468 | * Send the control information (i.e. audio format) |
1454 | */ | 1469 | */ |
1455 | static int cs4215_setctrl(struct snd_dbri * dbri) | 1470 | static int cs4215_setctrl(struct snd_dbri *dbri) |
1456 | { | 1471 | { |
1457 | int i, val; | 1472 | int i, val; |
1458 | u32 tmp; | 1473 | u32 tmp; |
@@ -1502,9 +1517,9 @@ static int cs4215_setctrl(struct snd_dbri * dbri) | |||
1502 | 1517 | ||
1503 | /* | 1518 | /* |
1504 | * Control mode: | 1519 | * Control mode: |
1505 | * Pipe 17: Send timeslots 1-4 (slots 5-8 are readonly) | 1520 | * Pipe 17: Send timeslots 1-4 (slots 5-8 are read only) |
1506 | * Pipe 18: Receive timeslot 1 (clb). | 1521 | * Pipe 18: Receive timeslot 1 (clb). |
1507 | * Pipe 19: Receive timeslot 7 (version). | 1522 | * Pipe 19: Receive timeslot 7 (version). |
1508 | */ | 1523 | */ |
1509 | 1524 | ||
1510 | link_time_slot(dbri, 17, 16, 16, 32, dbri->mm.offset); | 1525 | link_time_slot(dbri, 17, 16, 16, 32, dbri->mm.offset); |
@@ -1522,9 +1537,9 @@ static int cs4215_setctrl(struct snd_dbri * dbri) | |||
1522 | sbus_writel(tmp, dbri->regs + REG0); | 1537 | sbus_writel(tmp, dbri->regs + REG0); |
1523 | spin_unlock_irqrestore(&dbri->lock, flags); | 1538 | spin_unlock_irqrestore(&dbri->lock, flags); |
1524 | 1539 | ||
1525 | for (i = 10; ((dbri->mm.status & 0xe4) != 0x20); --i) { | 1540 | for (i = 10; ((dbri->mm.status & 0xe4) != 0x20); --i) |
1526 | msleep_interruptible(1); | 1541 | msleep_interruptible(1); |
1527 | } | 1542 | |
1528 | if (i == 0) { | 1543 | if (i == 0) { |
1529 | dprintk(D_MM, "CS4215 didn't respond to CLB (0x%02x)\n", | 1544 | dprintk(D_MM, "CS4215 didn't respond to CLB (0x%02x)\n", |
1530 | dbri->mm.status); | 1545 | dbri->mm.status); |
@@ -1556,7 +1571,7 @@ static int cs4215_setctrl(struct snd_dbri * dbri) | |||
1556 | * As part of the process we resend the settings for the data | 1571 | * As part of the process we resend the settings for the data |
1557 | * timeslots as well. | 1572 | * timeslots as well. |
1558 | */ | 1573 | */ |
1559 | static int cs4215_prepare(struct snd_dbri * dbri, unsigned int rate, | 1574 | static int cs4215_prepare(struct snd_dbri *dbri, unsigned int rate, |
1560 | snd_pcm_format_t format, unsigned int channels) | 1575 | snd_pcm_format_t format, unsigned int channels) |
1561 | { | 1576 | { |
1562 | int freq_idx; | 1577 | int freq_idx; |
@@ -1613,7 +1628,7 @@ static int cs4215_prepare(struct snd_dbri * dbri, unsigned int rate, | |||
1613 | /* | 1628 | /* |
1614 | * | 1629 | * |
1615 | */ | 1630 | */ |
1616 | static int cs4215_init(struct snd_dbri * dbri) | 1631 | static __devinit int cs4215_init(struct snd_dbri *dbri) |
1617 | { | 1632 | { |
1618 | u32 reg2 = sbus_readl(dbri->regs + REG2); | 1633 | u32 reg2 = sbus_readl(dbri->regs + REG2); |
1619 | dprintk(D_MM, "cs4215_init: reg2=0x%x\n", reg2); | 1634 | dprintk(D_MM, "cs4215_init: reg2=0x%x\n", reg2); |
@@ -1674,7 +1689,7 @@ interrupts are disabled. | |||
1674 | 1689 | ||
1675 | /* xmit_descs() | 1690 | /* xmit_descs() |
1676 | * | 1691 | * |
1677 | * Starts transmiting the current TD's for recording/playing. | 1692 | * Starts transmitting the current TD's for recording/playing. |
1678 | * For playback, ALSA has filled the DMA memory with new data (we hope). | 1693 | * For playback, ALSA has filled the DMA memory with new data (we hope). |
1679 | */ | 1694 | */ |
1680 | static void xmit_descs(struct snd_dbri *dbri) | 1695 | static void xmit_descs(struct snd_dbri *dbri) |
@@ -1701,7 +1716,8 @@ static void xmit_descs(struct snd_dbri *dbri) | |||
1701 | *(cmd++) = DBRI_CMD(D_SDP, 0, | 1716 | *(cmd++) = DBRI_CMD(D_SDP, 0, |
1702 | dbri->pipes[info->pipe].sdp | 1717 | dbri->pipes[info->pipe].sdp |
1703 | | D_SDP_P | D_SDP_EVERY | D_SDP_C); | 1718 | | D_SDP_P | D_SDP_EVERY | D_SDP_C); |
1704 | *(cmd++) = dbri->dma_dvma + dbri_dma_off(desc, first_td); | 1719 | *(cmd++) = dbri->dma_dvma + |
1720 | dbri_dma_off(desc, first_td); | ||
1705 | dbri_cmdsend(dbri, cmd, 2); | 1721 | dbri_cmdsend(dbri, cmd, 2); |
1706 | 1722 | ||
1707 | /* Reset our admin of the pipe. */ | 1723 | /* Reset our admin of the pipe. */ |
@@ -1722,7 +1738,8 @@ static void xmit_descs(struct snd_dbri *dbri) | |||
1722 | *(cmd++) = DBRI_CMD(D_SDP, 0, | 1738 | *(cmd++) = DBRI_CMD(D_SDP, 0, |
1723 | dbri->pipes[info->pipe].sdp | 1739 | dbri->pipes[info->pipe].sdp |
1724 | | D_SDP_P | D_SDP_EVERY | D_SDP_C); | 1740 | | D_SDP_P | D_SDP_EVERY | D_SDP_C); |
1725 | *(cmd++) = dbri->dma_dvma + dbri_dma_off(desc, first_td); | 1741 | *(cmd++) = dbri->dma_dvma + |
1742 | dbri_dma_off(desc, first_td); | ||
1726 | dbri_cmdsend(dbri, cmd, 2); | 1743 | dbri_cmdsend(dbri, cmd, 2); |
1727 | 1744 | ||
1728 | /* Reset our admin of the pipe. */ | 1745 | /* Reset our admin of the pipe. */ |
@@ -1747,15 +1764,12 @@ static void xmit_descs(struct snd_dbri *dbri) | |||
1747 | * | 1764 | * |
1748 | */ | 1765 | */ |
1749 | 1766 | ||
1750 | static void transmission_complete_intr(struct snd_dbri * dbri, int pipe) | 1767 | static void transmission_complete_intr(struct snd_dbri *dbri, int pipe) |
1751 | { | 1768 | { |
1752 | struct dbri_streaminfo *info; | 1769 | struct dbri_streaminfo *info = &dbri->stream_info[DBRI_PLAY]; |
1753 | int td; | 1770 | int td = dbri->pipes[pipe].desc; |
1754 | int status; | 1771 | int status; |
1755 | 1772 | ||
1756 | info = &dbri->stream_info[DBRI_PLAY]; | ||
1757 | |||
1758 | td = dbri->pipes[pipe].desc; | ||
1759 | while (td >= 0) { | 1773 | while (td >= 0) { |
1760 | if (td >= DBRI_NO_DESCS) { | 1774 | if (td >= DBRI_NO_DESCS) { |
1761 | printk(KERN_ERR "DBRI: invalid td on pipe %d\n", pipe); | 1775 | printk(KERN_ERR "DBRI: invalid td on pipe %d\n", pipe); |
@@ -1763,9 +1777,8 @@ static void transmission_complete_intr(struct snd_dbri * dbri, int pipe) | |||
1763 | } | 1777 | } |
1764 | 1778 | ||
1765 | status = DBRI_TD_STATUS(dbri->dma->desc[td].word4); | 1779 | status = DBRI_TD_STATUS(dbri->dma->desc[td].word4); |
1766 | if (!(status & DBRI_TD_TBC)) { | 1780 | if (!(status & DBRI_TD_TBC)) |
1767 | break; | 1781 | break; |
1768 | } | ||
1769 | 1782 | ||
1770 | dprintk(D_INT, "TD %d, status 0x%02x\n", td, status); | 1783 | dprintk(D_INT, "TD %d, status 0x%02x\n", td, status); |
1771 | 1784 | ||
@@ -1777,15 +1790,12 @@ static void transmission_complete_intr(struct snd_dbri * dbri, int pipe) | |||
1777 | } | 1790 | } |
1778 | 1791 | ||
1779 | /* Notify ALSA */ | 1792 | /* Notify ALSA */ |
1780 | if (spin_is_locked(&dbri->lock)) { | 1793 | spin_unlock(&dbri->lock); |
1781 | spin_unlock(&dbri->lock); | 1794 | snd_pcm_period_elapsed(info->substream); |
1782 | snd_pcm_period_elapsed(info->substream); | 1795 | spin_lock(&dbri->lock); |
1783 | spin_lock(&dbri->lock); | ||
1784 | } else | ||
1785 | snd_pcm_period_elapsed(info->substream); | ||
1786 | } | 1796 | } |
1787 | 1797 | ||
1788 | static void reception_complete_intr(struct snd_dbri * dbri, int pipe) | 1798 | static void reception_complete_intr(struct snd_dbri *dbri, int pipe) |
1789 | { | 1799 | { |
1790 | struct dbri_streaminfo *info; | 1800 | struct dbri_streaminfo *info; |
1791 | int rd = dbri->pipes[pipe].desc; | 1801 | int rd = dbri->pipes[pipe].desc; |
@@ -1809,15 +1819,12 @@ static void reception_complete_intr(struct snd_dbri * dbri, int pipe) | |||
1809 | rd, DBRI_RD_STATUS(status), DBRI_RD_CNT(status)); | 1819 | rd, DBRI_RD_STATUS(status), DBRI_RD_CNT(status)); |
1810 | 1820 | ||
1811 | /* Notify ALSA */ | 1821 | /* Notify ALSA */ |
1812 | if (spin_is_locked(&dbri->lock)) { | 1822 | spin_unlock(&dbri->lock); |
1813 | spin_unlock(&dbri->lock); | 1823 | snd_pcm_period_elapsed(info->substream); |
1814 | snd_pcm_period_elapsed(info->substream); | 1824 | spin_lock(&dbri->lock); |
1815 | spin_lock(&dbri->lock); | ||
1816 | } else | ||
1817 | snd_pcm_period_elapsed(info->substream); | ||
1818 | } | 1825 | } |
1819 | 1826 | ||
1820 | static void dbri_process_one_interrupt(struct snd_dbri * dbri, int x) | 1827 | static void dbri_process_one_interrupt(struct snd_dbri *dbri, int x) |
1821 | { | 1828 | { |
1822 | int val = D_INTR_GETVAL(x); | 1829 | int val = D_INTR_GETVAL(x); |
1823 | int channel = D_INTR_GETCHAN(x); | 1830 | int channel = D_INTR_GETCHAN(x); |
@@ -1889,7 +1896,7 @@ static void dbri_process_one_interrupt(struct snd_dbri * dbri, int x) | |||
1889 | * right now). Non-zero words require processing and are handed off | 1896 | * right now). Non-zero words require processing and are handed off |
1890 | * to dbri_process_one_interrupt AFTER advancing the pointer. | 1897 | * to dbri_process_one_interrupt AFTER advancing the pointer. |
1891 | */ | 1898 | */ |
1892 | static void dbri_process_interrupt_buffer(struct snd_dbri * dbri) | 1899 | static void dbri_process_interrupt_buffer(struct snd_dbri *dbri) |
1893 | { | 1900 | { |
1894 | s32 x; | 1901 | s32 x; |
1895 | 1902 | ||
@@ -1965,20 +1972,20 @@ static irqreturn_t snd_dbri_interrupt(int irq, void *dev_id) | |||
1965 | PCM Interface | 1972 | PCM Interface |
1966 | ****************************************************************************/ | 1973 | ****************************************************************************/ |
1967 | static struct snd_pcm_hardware snd_dbri_pcm_hw = { | 1974 | static struct snd_pcm_hardware snd_dbri_pcm_hw = { |
1968 | .info = (SNDRV_PCM_INFO_MMAP | | 1975 | .info = SNDRV_PCM_INFO_MMAP | |
1969 | SNDRV_PCM_INFO_INTERLEAVED | | 1976 | SNDRV_PCM_INFO_INTERLEAVED | |
1970 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 1977 | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
1971 | SNDRV_PCM_INFO_MMAP_VALID), | 1978 | SNDRV_PCM_INFO_MMAP_VALID, |
1972 | .formats = SNDRV_PCM_FMTBIT_MU_LAW | | 1979 | .formats = SNDRV_PCM_FMTBIT_MU_LAW | |
1973 | SNDRV_PCM_FMTBIT_A_LAW | | 1980 | SNDRV_PCM_FMTBIT_A_LAW | |
1974 | SNDRV_PCM_FMTBIT_U8 | | 1981 | SNDRV_PCM_FMTBIT_U8 | |
1975 | SNDRV_PCM_FMTBIT_S16_BE, | 1982 | SNDRV_PCM_FMTBIT_S16_BE, |
1976 | .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_5512, | 1983 | .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_5512, |
1977 | .rate_min = 5512, | 1984 | .rate_min = 5512, |
1978 | .rate_max = 48000, | 1985 | .rate_max = 48000, |
1979 | .channels_min = 1, | 1986 | .channels_min = 1, |
1980 | .channels_max = 2, | 1987 | .channels_max = 2, |
1981 | .buffer_bytes_max = (64 * 1024), | 1988 | .buffer_bytes_max = 64 * 1024, |
1982 | .period_bytes_min = 1, | 1989 | .period_bytes_min = 1, |
1983 | .period_bytes_max = DBRI_TD_MAXCNT, | 1990 | .period_bytes_max = DBRI_TD_MAXCNT, |
1984 | .periods_min = 1, | 1991 | .periods_min = 1, |
@@ -2011,7 +2018,8 @@ static int snd_hw_rule_channels(struct snd_pcm_hw_params *params, | |||
2011 | 2018 | ||
2012 | snd_interval_any(&ch); | 2019 | snd_interval_any(&ch); |
2013 | if (!(f->bits[0] & SNDRV_PCM_FMTBIT_S16_BE)) { | 2020 | if (!(f->bits[0] & SNDRV_PCM_FMTBIT_S16_BE)) { |
2014 | ch.min = ch.max = 1; | 2021 | ch.min = 1; |
2022 | ch.max = 1; | ||
2015 | ch.integer = 1; | 2023 | ch.integer = 1; |
2016 | return snd_interval_refine(c, &ch); | 2024 | return snd_interval_refine(c, &ch); |
2017 | } | 2025 | } |
@@ -2035,14 +2043,14 @@ static int snd_dbri_open(struct snd_pcm_substream *substream) | |||
2035 | info->pipe = -1; | 2043 | info->pipe = -1; |
2036 | spin_unlock_irqrestore(&dbri->lock, flags); | 2044 | spin_unlock_irqrestore(&dbri->lock, flags); |
2037 | 2045 | ||
2038 | snd_pcm_hw_rule_add(runtime,0,SNDRV_PCM_HW_PARAM_CHANNELS, | 2046 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, |
2039 | snd_hw_rule_format, NULL, SNDRV_PCM_HW_PARAM_FORMAT, | 2047 | snd_hw_rule_format, NULL, SNDRV_PCM_HW_PARAM_FORMAT, |
2040 | -1); | 2048 | -1); |
2041 | snd_pcm_hw_rule_add(runtime,0,SNDRV_PCM_HW_PARAM_FORMAT, | 2049 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT, |
2042 | snd_hw_rule_channels, NULL, | 2050 | snd_hw_rule_channels, NULL, |
2043 | SNDRV_PCM_HW_PARAM_CHANNELS, | 2051 | SNDRV_PCM_HW_PARAM_CHANNELS, |
2044 | -1); | 2052 | -1); |
2045 | 2053 | ||
2046 | cs4215_open(dbri); | 2054 | cs4215_open(dbri); |
2047 | 2055 | ||
2048 | return 0; | 2056 | return 0; |
@@ -2145,7 +2153,7 @@ static int snd_dbri_prepare(struct snd_pcm_substream *substream) | |||
2145 | spin_lock_irq(&dbri->lock); | 2153 | spin_lock_irq(&dbri->lock); |
2146 | info->offset = 0; | 2154 | info->offset = 0; |
2147 | 2155 | ||
2148 | /* Setup the all the transmit/receive desciptors to cover the | 2156 | /* Setup the all the transmit/receive descriptors to cover the |
2149 | * whole DMA buffer. | 2157 | * whole DMA buffer. |
2150 | */ | 2158 | */ |
2151 | ret = setup_descs(dbri, DBRI_STREAMNO(substream), | 2159 | ret = setup_descs(dbri, DBRI_STREAMNO(substream), |
@@ -2205,12 +2213,12 @@ static struct snd_pcm_ops snd_dbri_ops = { | |||
2205 | .pointer = snd_dbri_pointer, | 2213 | .pointer = snd_dbri_pointer, |
2206 | }; | 2214 | }; |
2207 | 2215 | ||
2208 | static int __devinit snd_dbri_pcm(struct snd_dbri * dbri) | 2216 | static int __devinit snd_dbri_pcm(struct snd_card *card) |
2209 | { | 2217 | { |
2210 | struct snd_pcm *pcm; | 2218 | struct snd_pcm *pcm; |
2211 | int err; | 2219 | int err; |
2212 | 2220 | ||
2213 | if ((err = snd_pcm_new(dbri->card, | 2221 | if ((err = snd_pcm_new(card, |
2214 | /* ID */ "sun_dbri", | 2222 | /* ID */ "sun_dbri", |
2215 | /* device */ 0, | 2223 | /* device */ 0, |
2216 | /* playback count */ 1, | 2224 | /* playback count */ 1, |
@@ -2221,16 +2229,15 @@ static int __devinit snd_dbri_pcm(struct snd_dbri * dbri) | |||
2221 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_dbri_ops); | 2229 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_dbri_ops); |
2222 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_dbri_ops); | 2230 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_dbri_ops); |
2223 | 2231 | ||
2224 | pcm->private_data = dbri; | 2232 | pcm->private_data = card->private_data; |
2225 | pcm->info_flags = 0; | 2233 | pcm->info_flags = 0; |
2226 | strcpy(pcm->name, dbri->card->shortname); | 2234 | strcpy(pcm->name, card->shortname); |
2227 | 2235 | ||
2228 | if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm, | 2236 | if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm, |
2229 | SNDRV_DMA_TYPE_CONTINUOUS, | 2237 | SNDRV_DMA_TYPE_CONTINUOUS, |
2230 | snd_dma_continuous_data(GFP_KERNEL), | 2238 | snd_dma_continuous_data(GFP_KERNEL), |
2231 | 64 * 1024, 64 * 1024)) < 0) { | 2239 | 64 * 1024, 64 * 1024)) < 0) |
2232 | return err; | 2240 | return err; |
2233 | } | ||
2234 | 2241 | ||
2235 | return 0; | 2242 | return 0; |
2236 | } | 2243 | } |
@@ -2245,11 +2252,10 @@ static int snd_cs4215_info_volume(struct snd_kcontrol *kcontrol, | |||
2245 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | 2252 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
2246 | uinfo->count = 2; | 2253 | uinfo->count = 2; |
2247 | uinfo->value.integer.min = 0; | 2254 | uinfo->value.integer.min = 0; |
2248 | if (kcontrol->private_value == DBRI_PLAY) { | 2255 | if (kcontrol->private_value == DBRI_PLAY) |
2249 | uinfo->value.integer.max = DBRI_MAX_VOLUME; | 2256 | uinfo->value.integer.max = DBRI_MAX_VOLUME; |
2250 | } else { | 2257 | else |
2251 | uinfo->value.integer.max = DBRI_MAX_GAIN; | 2258 | uinfo->value.integer.max = DBRI_MAX_GAIN; |
2252 | } | ||
2253 | return 0; | 2259 | return 0; |
2254 | } | 2260 | } |
2255 | 2261 | ||
@@ -2271,7 +2277,8 @@ static int snd_cs4215_put_volume(struct snd_kcontrol *kcontrol, | |||
2271 | struct snd_ctl_elem_value *ucontrol) | 2277 | struct snd_ctl_elem_value *ucontrol) |
2272 | { | 2278 | { |
2273 | struct snd_dbri *dbri = snd_kcontrol_chip(kcontrol); | 2279 | struct snd_dbri *dbri = snd_kcontrol_chip(kcontrol); |
2274 | struct dbri_streaminfo *info = &dbri->stream_info[kcontrol->private_value]; | 2280 | struct dbri_streaminfo *info = |
2281 | &dbri->stream_info[kcontrol->private_value]; | ||
2275 | int changed = 0; | 2282 | int changed = 0; |
2276 | 2283 | ||
2277 | if (info->left_gain != ucontrol->value.integer.value[0]) { | 2284 | if (info->left_gain != ucontrol->value.integer.value[0]) { |
@@ -2282,7 +2289,7 @@ static int snd_cs4215_put_volume(struct snd_kcontrol *kcontrol, | |||
2282 | info->right_gain = ucontrol->value.integer.value[1]; | 2289 | info->right_gain = ucontrol->value.integer.value[1]; |
2283 | changed = 1; | 2290 | changed = 1; |
2284 | } | 2291 | } |
2285 | if (changed == 1) { | 2292 | if (changed) { |
2286 | /* First mute outputs, and wait 1/8000 sec (125 us) | 2293 | /* First mute outputs, and wait 1/8000 sec (125 us) |
2287 | * to make sure this takes. This avoids clicking noises. | 2294 | * to make sure this takes. This avoids clicking noises. |
2288 | */ | 2295 | */ |
@@ -2316,18 +2323,16 @@ static int snd_cs4215_get_single(struct snd_kcontrol *kcontrol, | |||
2316 | int invert = (kcontrol->private_value >> 24) & 1; | 2323 | int invert = (kcontrol->private_value >> 24) & 1; |
2317 | snd_assert(dbri != NULL, return -EINVAL); | 2324 | snd_assert(dbri != NULL, return -EINVAL); |
2318 | 2325 | ||
2319 | if (elem < 4) { | 2326 | if (elem < 4) |
2320 | ucontrol->value.integer.value[0] = | 2327 | ucontrol->value.integer.value[0] = |
2321 | (dbri->mm.data[elem] >> shift) & mask; | 2328 | (dbri->mm.data[elem] >> shift) & mask; |
2322 | } else { | 2329 | else |
2323 | ucontrol->value.integer.value[0] = | 2330 | ucontrol->value.integer.value[0] = |
2324 | (dbri->mm.ctrl[elem - 4] >> shift) & mask; | 2331 | (dbri->mm.ctrl[elem - 4] >> shift) & mask; |
2325 | } | ||
2326 | 2332 | ||
2327 | if (invert == 1) { | 2333 | if (invert == 1) |
2328 | ucontrol->value.integer.value[0] = | 2334 | ucontrol->value.integer.value[0] = |
2329 | mask - ucontrol->value.integer.value[0]; | 2335 | mask - ucontrol->value.integer.value[0]; |
2330 | } | ||
2331 | return 0; | 2336 | return 0; |
2332 | } | 2337 | } |
2333 | 2338 | ||
@@ -2378,11 +2383,12 @@ static int snd_cs4215_put_single(struct snd_kcontrol *kcontrol, | |||
2378 | timeslots. Shift is the bit offset in the timeslot, mask defines the | 2383 | timeslots. Shift is the bit offset in the timeslot, mask defines the |
2379 | number of bits. invert is a boolean for use with attenuation. | 2384 | number of bits. invert is a boolean for use with attenuation. |
2380 | */ | 2385 | */ |
2381 | #define CS4215_SINGLE(xname, entry, shift, mask, invert) \ | 2386 | #define CS4215_SINGLE(xname, entry, shift, mask, invert) \ |
2382 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | 2387 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ |
2383 | .info = snd_cs4215_info_single, \ | 2388 | .info = snd_cs4215_info_single, \ |
2384 | .get = snd_cs4215_get_single, .put = snd_cs4215_put_single, \ | 2389 | .get = snd_cs4215_get_single, .put = snd_cs4215_put_single, \ |
2385 | .private_value = entry | (shift << 8) | (mask << 16) | (invert << 24) }, | 2390 | .private_value = (entry) | ((shift) << 8) | ((mask) << 16) | \ |
2391 | ((invert) << 24) }, | ||
2386 | 2392 | ||
2387 | static struct snd_kcontrol_new dbri_controls[] __devinitdata = { | 2393 | static struct snd_kcontrol_new dbri_controls[] __devinitdata = { |
2388 | { | 2394 | { |
@@ -2411,19 +2417,20 @@ static struct snd_kcontrol_new dbri_controls[] __devinitdata = { | |||
2411 | CS4215_SINGLE("Mic boost", 4, 4, 1, 1) | 2417 | CS4215_SINGLE("Mic boost", 4, 4, 1, 1) |
2412 | }; | 2418 | }; |
2413 | 2419 | ||
2414 | static int __init snd_dbri_mixer(struct snd_dbri * dbri) | 2420 | static int __devinit snd_dbri_mixer(struct snd_card *card) |
2415 | { | 2421 | { |
2416 | struct snd_card *card; | ||
2417 | int idx, err; | 2422 | int idx, err; |
2423 | struct snd_dbri *dbri; | ||
2418 | 2424 | ||
2419 | snd_assert(dbri != NULL && dbri->card != NULL, return -EINVAL); | 2425 | snd_assert(card != NULL && card->private_data != NULL, return -EINVAL); |
2426 | dbri = card->private_data; | ||
2420 | 2427 | ||
2421 | card = dbri->card; | ||
2422 | strcpy(card->mixername, card->shortname); | 2428 | strcpy(card->mixername, card->shortname); |
2423 | 2429 | ||
2424 | for (idx = 0; idx < ARRAY_SIZE(dbri_controls); idx++) { | 2430 | for (idx = 0; idx < ARRAY_SIZE(dbri_controls); idx++) { |
2425 | if ((err = snd_ctl_add(card, | 2431 | err = snd_ctl_add(card, |
2426 | snd_ctl_new1(&dbri_controls[idx], dbri))) < 0) | 2432 | snd_ctl_new1(&dbri_controls[idx], dbri)); |
2433 | if (err < 0) | ||
2427 | return err; | 2434 | return err; |
2428 | } | 2435 | } |
2429 | 2436 | ||
@@ -2438,7 +2445,8 @@ static int __init snd_dbri_mixer(struct snd_dbri * dbri) | |||
2438 | /**************************************************************************** | 2445 | /**************************************************************************** |
2439 | /proc interface | 2446 | /proc interface |
2440 | ****************************************************************************/ | 2447 | ****************************************************************************/ |
2441 | static void dbri_regs_read(struct snd_info_entry * entry, struct snd_info_buffer *buffer) | 2448 | static void dbri_regs_read(struct snd_info_entry *entry, |
2449 | struct snd_info_buffer *buffer) | ||
2442 | { | 2450 | { |
2443 | struct snd_dbri *dbri = entry->private_data; | 2451 | struct snd_dbri *dbri = entry->private_data; |
2444 | 2452 | ||
@@ -2449,7 +2457,7 @@ static void dbri_regs_read(struct snd_info_entry * entry, struct snd_info_buffer | |||
2449 | } | 2457 | } |
2450 | 2458 | ||
2451 | #ifdef DBRI_DEBUG | 2459 | #ifdef DBRI_DEBUG |
2452 | static void dbri_debug_read(struct snd_info_entry * entry, | 2460 | static void dbri_debug_read(struct snd_info_entry *entry, |
2453 | struct snd_info_buffer *buffer) | 2461 | struct snd_info_buffer *buffer) |
2454 | { | 2462 | { |
2455 | struct snd_dbri *dbri = entry->private_data; | 2463 | struct snd_dbri *dbri = entry->private_data; |
@@ -2463,7 +2471,8 @@ static void dbri_debug_read(struct snd_info_entry * entry, | |||
2463 | "Pipe %d: %s SDP=0x%x desc=%d, " | 2471 | "Pipe %d: %s SDP=0x%x desc=%d, " |
2464 | "len=%d next %d\n", | 2472 | "len=%d next %d\n", |
2465 | pipe, | 2473 | pipe, |
2466 | ((pptr->sdp & D_SDP_TO_SER) ? "output" : "input"), | 2474 | (pptr->sdp & D_SDP_TO_SER) ? "output" : |
2475 | "input", | ||
2467 | pptr->sdp, pptr->desc, | 2476 | pptr->sdp, pptr->desc, |
2468 | pptr->length, pptr->nextpipe); | 2477 | pptr->length, pptr->nextpipe); |
2469 | } | 2478 | } |
@@ -2471,15 +2480,16 @@ static void dbri_debug_read(struct snd_info_entry * entry, | |||
2471 | } | 2480 | } |
2472 | #endif | 2481 | #endif |
2473 | 2482 | ||
2474 | void snd_dbri_proc(struct snd_dbri * dbri) | 2483 | void __devinit snd_dbri_proc(struct snd_card *card) |
2475 | { | 2484 | { |
2485 | struct snd_dbri *dbri = card->private_data; | ||
2476 | struct snd_info_entry *entry; | 2486 | struct snd_info_entry *entry; |
2477 | 2487 | ||
2478 | if (! snd_card_proc_new(dbri->card, "regs", &entry)) | 2488 | if (!snd_card_proc_new(card, "regs", &entry)) |
2479 | snd_info_set_text_ops(entry, dbri, dbri_regs_read); | 2489 | snd_info_set_text_ops(entry, dbri, dbri_regs_read); |
2480 | 2490 | ||
2481 | #ifdef DBRI_DEBUG | 2491 | #ifdef DBRI_DEBUG |
2482 | if (! snd_card_proc_new(dbri->card, "debug", &entry)) { | 2492 | if (!snd_card_proc_new(card, "debug", &entry)) { |
2483 | snd_info_set_text_ops(entry, dbri, dbri_debug_read); | 2493 | snd_info_set_text_ops(entry, dbri, dbri_debug_read); |
2484 | entry->mode = S_IFREG | S_IRUGO; /* Readable only. */ | 2494 | entry->mode = S_IFREG | S_IRUGO; /* Readable only. */ |
2485 | } | 2495 | } |
@@ -2491,19 +2501,18 @@ void snd_dbri_proc(struct snd_dbri * dbri) | |||
2491 | **************************** Initialization ******************************** | 2501 | **************************** Initialization ******************************** |
2492 | **************************************************************************** | 2502 | **************************************************************************** |
2493 | */ | 2503 | */ |
2494 | static void snd_dbri_free(struct snd_dbri * dbri); | 2504 | static void snd_dbri_free(struct snd_dbri *dbri); |
2495 | 2505 | ||
2496 | static int __init snd_dbri_create(struct snd_card *card, | 2506 | static int __devinit snd_dbri_create(struct snd_card *card, |
2497 | struct sbus_dev *sdev, | 2507 | struct sbus_dev *sdev, |
2498 | struct linux_prom_irqs *irq, int dev) | 2508 | int irq, int dev) |
2499 | { | 2509 | { |
2500 | struct snd_dbri *dbri = card->private_data; | 2510 | struct snd_dbri *dbri = card->private_data; |
2501 | int err; | 2511 | int err; |
2502 | 2512 | ||
2503 | spin_lock_init(&dbri->lock); | 2513 | spin_lock_init(&dbri->lock); |
2504 | dbri->card = card; | ||
2505 | dbri->sdev = sdev; | 2514 | dbri->sdev = sdev; |
2506 | dbri->irq = irq->pri; | 2515 | dbri->irq = irq; |
2507 | 2516 | ||
2508 | dbri->dma = sbus_alloc_consistent(sdev, sizeof(struct dbri_dma), | 2517 | dbri->dma = sbus_alloc_consistent(sdev, sizeof(struct dbri_dma), |
2509 | &dbri->dma_dvma); | 2518 | &dbri->dma_dvma); |
@@ -2541,13 +2550,10 @@ static int __init snd_dbri_create(struct snd_card *card, | |||
2541 | return err; | 2550 | return err; |
2542 | } | 2551 | } |
2543 | 2552 | ||
2544 | dbri->next = dbri_list; | ||
2545 | dbri_list = dbri; | ||
2546 | |||
2547 | return 0; | 2553 | return 0; |
2548 | } | 2554 | } |
2549 | 2555 | ||
2550 | static void snd_dbri_free(struct snd_dbri * dbri) | 2556 | static void snd_dbri_free(struct snd_dbri *dbri) |
2551 | { | 2557 | { |
2552 | dprintk(D_GEN, "snd_dbri_free\n"); | 2558 | dprintk(D_GEN, "snd_dbri_free\n"); |
2553 | dbri_reset(dbri); | 2559 | dbri_reset(dbri); |
@@ -2563,20 +2569,19 @@ static void snd_dbri_free(struct snd_dbri * dbri) | |||
2563 | (void *)dbri->dma, dbri->dma_dvma); | 2569 | (void *)dbri->dma, dbri->dma_dvma); |
2564 | } | 2570 | } |
2565 | 2571 | ||
2566 | static int __init dbri_attach(int prom_node, struct sbus_dev *sdev) | 2572 | static int __devinit dbri_probe(struct of_device *of_dev, |
2573 | const struct of_device_id *match) | ||
2567 | { | 2574 | { |
2575 | struct sbus_dev *sdev = to_sbus_device(&of_dev->dev); | ||
2568 | struct snd_dbri *dbri; | 2576 | struct snd_dbri *dbri; |
2569 | struct linux_prom_irqs irq; | 2577 | int irq; |
2570 | struct resource *rp; | 2578 | struct resource *rp; |
2571 | struct snd_card *card; | 2579 | struct snd_card *card; |
2572 | static int dev = 0; | 2580 | static int dev = 0; |
2573 | int err; | 2581 | int err; |
2574 | 2582 | ||
2575 | if (sdev->prom_name[9] < 'e') { | 2583 | dprintk(D_GEN, "DBRI: Found %s in SBUS slot %d\n", |
2576 | printk(KERN_ERR "DBRI: unsupported chip version %c found.\n", | 2584 | sdev->prom_name, sdev->slot); |
2577 | sdev->prom_name[9]); | ||
2578 | return -EIO; | ||
2579 | } | ||
2580 | 2585 | ||
2581 | if (dev >= SNDRV_CARDS) | 2586 | if (dev >= SNDRV_CARDS) |
2582 | return -ENODEV; | 2587 | return -ENODEV; |
@@ -2585,9 +2590,9 @@ static int __init dbri_attach(int prom_node, struct sbus_dev *sdev) | |||
2585 | return -ENOENT; | 2590 | return -ENOENT; |
2586 | } | 2591 | } |
2587 | 2592 | ||
2588 | err = prom_getproperty(prom_node, "intr", (char *)&irq, sizeof(irq)); | 2593 | irq = sdev->irqs[0]; |
2589 | if (err < 0) { | 2594 | if (irq <= 0) { |
2590 | printk(KERN_ERR "DBRI-%d: Firmware node lacks IRQ property.\n", dev); | 2595 | printk(KERN_ERR "DBRI-%d: No IRQ.\n", dev); |
2591 | return -ENODEV; | 2596 | return -ENODEV; |
2592 | } | 2597 | } |
2593 | 2598 | ||
@@ -2601,24 +2606,29 @@ static int __init dbri_attach(int prom_node, struct sbus_dev *sdev) | |||
2601 | rp = &sdev->resource[0]; | 2606 | rp = &sdev->resource[0]; |
2602 | sprintf(card->longname, "%s at 0x%02lx:0x%016Lx, irq %d", | 2607 | sprintf(card->longname, "%s at 0x%02lx:0x%016Lx, irq %d", |
2603 | card->shortname, | 2608 | card->shortname, |
2604 | rp->flags & 0xffL, (unsigned long long)rp->start, irq.pri); | 2609 | rp->flags & 0xffL, (unsigned long long)rp->start, irq); |
2605 | 2610 | ||
2606 | if ((err = snd_dbri_create(card, sdev, &irq, dev)) < 0) { | 2611 | err = snd_dbri_create(card, sdev, irq, dev); |
2612 | if (err < 0) { | ||
2607 | snd_card_free(card); | 2613 | snd_card_free(card); |
2608 | return err; | 2614 | return err; |
2609 | } | 2615 | } |
2610 | 2616 | ||
2611 | dbri = card->private_data; | 2617 | dbri = card->private_data; |
2612 | if ((err = snd_dbri_pcm(dbri)) < 0) | 2618 | err = snd_dbri_pcm(card); |
2619 | if (err < 0) | ||
2613 | goto _err; | 2620 | goto _err; |
2614 | 2621 | ||
2615 | if ((err = snd_dbri_mixer(dbri)) < 0) | 2622 | err = snd_dbri_mixer(card); |
2623 | if (err < 0) | ||
2616 | goto _err; | 2624 | goto _err; |
2617 | 2625 | ||
2618 | /* /proc file handling */ | 2626 | /* /proc file handling */ |
2619 | snd_dbri_proc(dbri); | 2627 | snd_dbri_proc(card); |
2628 | dev_set_drvdata(&of_dev->dev, card); | ||
2620 | 2629 | ||
2621 | if ((err = snd_card_register(card)) < 0) | 2630 | err = snd_card_register(card); |
2631 | if (err < 0) | ||
2622 | goto _err; | 2632 | goto _err; |
2623 | 2633 | ||
2624 | printk(KERN_INFO "audio%d at %p (irq %d) is DBRI(%c)+CS4215(%d)\n", | 2634 | printk(KERN_INFO "audio%d at %p (irq %d) is DBRI(%c)+CS4215(%d)\n", |
@@ -2628,49 +2638,52 @@ static int __init dbri_attach(int prom_node, struct sbus_dev *sdev) | |||
2628 | 2638 | ||
2629 | return 0; | 2639 | return 0; |
2630 | 2640 | ||
2631 | _err: | 2641 | _err: |
2632 | snd_dbri_free(dbri); | 2642 | snd_dbri_free(dbri); |
2633 | snd_card_free(card); | 2643 | snd_card_free(card); |
2634 | return err; | 2644 | return err; |
2635 | } | 2645 | } |
2636 | 2646 | ||
2637 | /* Probe for the dbri chip and then attach the driver. */ | 2647 | static int __devexit dbri_remove(struct of_device *dev) |
2638 | static int __init dbri_init(void) | ||
2639 | { | 2648 | { |
2640 | struct sbus_bus *sbus; | 2649 | struct snd_card *card = dev_get_drvdata(&dev->dev); |
2641 | struct sbus_dev *sdev; | ||
2642 | int found = 0; | ||
2643 | |||
2644 | /* Probe each SBUS for the DBRI chip(s). */ | ||
2645 | for_all_sbusdev(sdev, sbus) { | ||
2646 | /* | ||
2647 | * The version is coded in the last character | ||
2648 | */ | ||
2649 | if (!strncmp(sdev->prom_name, "SUNW,DBRI", 9)) { | ||
2650 | dprintk(D_GEN, "DBRI: Found %s in SBUS slot %d\n", | ||
2651 | sdev->prom_name, sdev->slot); | ||
2652 | 2650 | ||
2653 | if (dbri_attach(sdev->prom_node, sdev) == 0) | 2651 | snd_dbri_free(card->private_data); |
2654 | found++; | 2652 | snd_card_free(card); |
2655 | } | 2653 | |
2656 | } | 2654 | dev_set_drvdata(&dev->dev, NULL); |
2655 | |||
2656 | return 0; | ||
2657 | } | ||
2658 | |||
2659 | static struct of_device_id dbri_match[] = { | ||
2660 | { | ||
2661 | .name = "SUNW,DBRIe", | ||
2662 | }, | ||
2663 | { | ||
2664 | .name = "SUNW,DBRIf", | ||
2665 | }, | ||
2666 | {}, | ||
2667 | }; | ||
2668 | |||
2669 | MODULE_DEVICE_TABLE(of, dbri_match); | ||
2670 | |||
2671 | static struct of_platform_driver dbri_sbus_driver = { | ||
2672 | .name = "dbri", | ||
2673 | .match_table = dbri_match, | ||
2674 | .probe = dbri_probe, | ||
2675 | .remove = __devexit_p(dbri_remove), | ||
2676 | }; | ||
2657 | 2677 | ||
2658 | return (found > 0) ? 0 : -EIO; | 2678 | /* Probe for the dbri chip and then attach the driver. */ |
2679 | static int __init dbri_init(void) | ||
2680 | { | ||
2681 | return of_register_driver(&dbri_sbus_driver, &sbus_bus_type); | ||
2659 | } | 2682 | } |
2660 | 2683 | ||
2661 | static void __exit dbri_exit(void) | 2684 | static void __exit dbri_exit(void) |
2662 | { | 2685 | { |
2663 | struct snd_dbri *this = dbri_list; | 2686 | of_unregister_driver(&dbri_sbus_driver); |
2664 | |||
2665 | while (this != NULL) { | ||
2666 | struct snd_dbri *next = this->next; | ||
2667 | struct snd_card *card = this->card; | ||
2668 | |||
2669 | snd_dbri_free(this); | ||
2670 | snd_card_free(card); | ||
2671 | this = next; | ||
2672 | } | ||
2673 | dbri_list = NULL; | ||
2674 | } | 2687 | } |
2675 | 2688 | ||
2676 | module_init(dbri_init); | 2689 | module_init(dbri_init); |
diff --git a/sound/spi/Kconfig b/sound/spi/Kconfig new file mode 100644 index 000000000000..0d08c29213c8 --- /dev/null +++ b/sound/spi/Kconfig | |||
@@ -0,0 +1,31 @@ | |||
1 | #SPI drivers | ||
2 | |||
3 | menu "SPI devices" | ||
4 | depends on SND != n | ||
5 | |||
6 | config SND_AT73C213 | ||
7 | tristate "Atmel AT73C213 DAC driver" | ||
8 | depends on ATMEL_SSC | ||
9 | select SND_PCM | ||
10 | help | ||
11 | Say Y here if you want to use the Atmel AT73C213 external DAC. This | ||
12 | DAC can be found on Atmel development boards. | ||
13 | |||
14 | This driver requires the Atmel SSC driver for sound sink, a | ||
15 | peripheral found on most AT91 and AVR32 microprocessors. | ||
16 | |||
17 | To compile this driver as a module, choose M here: the module will be | ||
18 | called snd-at73c213. | ||
19 | |||
20 | config SND_AT73C213_TARGET_BITRATE | ||
21 | int "Target bitrate for AT73C213" | ||
22 | depends on SND_AT73C213 | ||
23 | default "48000" | ||
24 | range 8000 50000 | ||
25 | help | ||
26 | Sets the target bitrate for the bitrate calculator in the driver. | ||
27 | Limited by hardware to be between 8000 Hz and 50000 Hz. | ||
28 | |||
29 | Set to 48000 Hz by default. | ||
30 | |||
31 | endmenu | ||
diff --git a/sound/spi/Makefile b/sound/spi/Makefile new file mode 100644 index 000000000000..026fb73f887f --- /dev/null +++ b/sound/spi/Makefile | |||
@@ -0,0 +1,5 @@ | |||
1 | # Makefile for SPI drivers | ||
2 | |||
3 | snd-at73c213-objs := at73c213.o | ||
4 | |||
5 | obj-$(CONFIG_SND_AT73C213) += snd-at73c213.o | ||
diff --git a/sound/spi/at73c213.c b/sound/spi/at73c213.c new file mode 100644 index 000000000000..fee869bcc959 --- /dev/null +++ b/sound/spi/at73c213.c | |||
@@ -0,0 +1,1129 @@ | |||
1 | /* | ||
2 | * Driver for AT73C213 16-bit stereo DAC connected to Atmel SSC | ||
3 | * | ||
4 | * Copyright (C) 2006-2007 Atmel Norway | ||
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 | |||
11 | /*#define DEBUG*/ | ||
12 | |||
13 | #include <linux/clk.h> | ||
14 | #include <linux/err.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/device.h> | ||
17 | #include <linux/dma-mapping.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/io.h> | ||
23 | |||
24 | #include <sound/driver.h> | ||
25 | #include <sound/initval.h> | ||
26 | #include <sound/control.h> | ||
27 | #include <sound/core.h> | ||
28 | #include <sound/pcm.h> | ||
29 | |||
30 | #include <linux/atmel-ssc.h> | ||
31 | |||
32 | #include <linux/spi/spi.h> | ||
33 | #include <linux/spi/at73c213.h> | ||
34 | |||
35 | #include "at73c213.h" | ||
36 | |||
37 | #define BITRATE_MIN 8000 /* Hardware limit? */ | ||
38 | #define BITRATE_TARGET CONFIG_SND_AT73C213_TARGET_BITRATE | ||
39 | #define BITRATE_MAX 50000 /* Hardware limit. */ | ||
40 | |||
41 | /* Initial (hardware reset) AT73C213 register values. */ | ||
42 | static u8 snd_at73c213_original_image[18] = | ||
43 | { | ||
44 | 0x00, /* 00 - CTRL */ | ||
45 | 0x05, /* 01 - LLIG */ | ||
46 | 0x05, /* 02 - RLIG */ | ||
47 | 0x08, /* 03 - LPMG */ | ||
48 | 0x08, /* 04 - RPMG */ | ||
49 | 0x00, /* 05 - LLOG */ | ||
50 | 0x00, /* 06 - RLOG */ | ||
51 | 0x22, /* 07 - OLC */ | ||
52 | 0x09, /* 08 - MC */ | ||
53 | 0x00, /* 09 - CSFC */ | ||
54 | 0x00, /* 0A - MISC */ | ||
55 | 0x00, /* 0B - */ | ||
56 | 0x00, /* 0C - PRECH */ | ||
57 | 0x05, /* 0D - AUXG */ | ||
58 | 0x00, /* 0E - */ | ||
59 | 0x00, /* 0F - */ | ||
60 | 0x00, /* 10 - RST */ | ||
61 | 0x00, /* 11 - PA_CTRL */ | ||
62 | }; | ||
63 | |||
64 | struct snd_at73c213 { | ||
65 | struct snd_card *card; | ||
66 | struct snd_pcm *pcm; | ||
67 | struct snd_pcm_substream *substream; | ||
68 | struct at73c213_board_info *board; | ||
69 | int irq; | ||
70 | int period; | ||
71 | unsigned long bitrate; | ||
72 | struct clk *bitclk; | ||
73 | struct ssc_device *ssc; | ||
74 | struct spi_device *spi; | ||
75 | u8 spi_wbuffer[2]; | ||
76 | u8 spi_rbuffer[2]; | ||
77 | /* Image of the SPI registers in AT73C213. */ | ||
78 | u8 reg_image[18]; | ||
79 | /* Protect registers against concurrent access. */ | ||
80 | spinlock_t lock; | ||
81 | }; | ||
82 | |||
83 | #define get_chip(card) ((struct snd_at73c213 *)card->private_data) | ||
84 | |||
85 | static int | ||
86 | snd_at73c213_write_reg(struct snd_at73c213 *chip, u8 reg, u8 val) | ||
87 | { | ||
88 | struct spi_message msg; | ||
89 | struct spi_transfer msg_xfer = { | ||
90 | .len = 2, | ||
91 | .cs_change = 0, | ||
92 | }; | ||
93 | int retval; | ||
94 | |||
95 | spi_message_init(&msg); | ||
96 | |||
97 | chip->spi_wbuffer[0] = reg; | ||
98 | chip->spi_wbuffer[1] = val; | ||
99 | |||
100 | msg_xfer.tx_buf = chip->spi_wbuffer; | ||
101 | msg_xfer.rx_buf = chip->spi_rbuffer; | ||
102 | spi_message_add_tail(&msg_xfer, &msg); | ||
103 | |||
104 | retval = spi_sync(chip->spi, &msg); | ||
105 | |||
106 | if (!retval) | ||
107 | chip->reg_image[reg] = val; | ||
108 | |||
109 | return retval; | ||
110 | } | ||
111 | |||
112 | static struct snd_pcm_hardware snd_at73c213_playback_hw = { | ||
113 | .info = SNDRV_PCM_INFO_INTERLEAVED | | ||
114 | SNDRV_PCM_INFO_BLOCK_TRANSFER, | ||
115 | .formats = SNDRV_PCM_FMTBIT_S16_BE, | ||
116 | .rates = SNDRV_PCM_RATE_CONTINUOUS, | ||
117 | .rate_min = 8000, /* Replaced by chip->bitrate later. */ | ||
118 | .rate_max = 50000, /* Replaced by chip->bitrate later. */ | ||
119 | .channels_min = 2, | ||
120 | .channels_max = 2, | ||
121 | .buffer_bytes_max = 64 * 1024 - 1, | ||
122 | .period_bytes_min = 512, | ||
123 | .period_bytes_max = 64 * 1024 - 1, | ||
124 | .periods_min = 4, | ||
125 | .periods_max = 1024, | ||
126 | }; | ||
127 | |||
128 | /* | ||
129 | * Calculate and set bitrate and divisions. | ||
130 | */ | ||
131 | static int snd_at73c213_set_bitrate(struct snd_at73c213 *chip) | ||
132 | { | ||
133 | unsigned long ssc_rate = clk_get_rate(chip->ssc->clk); | ||
134 | unsigned long dac_rate_new, ssc_div, status; | ||
135 | unsigned long ssc_div_max, ssc_div_min; | ||
136 | int max_tries; | ||
137 | |||
138 | /* | ||
139 | * We connect two clocks here, picking divisors so the I2S clocks | ||
140 | * out data at the same rate the DAC clocks it in ... and as close | ||
141 | * as practical to the desired target rate. | ||
142 | * | ||
143 | * The DAC master clock (MCLK) is programmable, and is either 256 | ||
144 | * or (not here) 384 times the I2S output clock (BCLK). | ||
145 | */ | ||
146 | |||
147 | /* SSC clock / (bitrate * stereo * 16-bit). */ | ||
148 | ssc_div = ssc_rate / (BITRATE_TARGET * 2 * 16); | ||
149 | ssc_div_min = ssc_rate / (BITRATE_MAX * 2 * 16); | ||
150 | ssc_div_max = ssc_rate / (BITRATE_MIN * 2 * 16); | ||
151 | max_tries = (ssc_div_max - ssc_div_min) / 2; | ||
152 | |||
153 | if (max_tries < 1) | ||
154 | max_tries = 1; | ||
155 | |||
156 | /* ssc_div must be a power of 2. */ | ||
157 | ssc_div = (ssc_div + 1) & ~1UL; | ||
158 | |||
159 | if ((ssc_rate / (ssc_div * 2 * 16)) < BITRATE_MIN) { | ||
160 | ssc_div -= 2; | ||
161 | if ((ssc_rate / (ssc_div * 2 * 16)) > BITRATE_MAX) | ||
162 | return -ENXIO; | ||
163 | } | ||
164 | |||
165 | /* Search for a possible bitrate. */ | ||
166 | do { | ||
167 | /* SSC clock / (ssc divider * 16-bit * stereo). */ | ||
168 | if ((ssc_rate / (ssc_div * 2 * 16)) < BITRATE_MIN) | ||
169 | return -ENXIO; | ||
170 | |||
171 | /* 256 / (2 * 16) = 8 */ | ||
172 | dac_rate_new = 8 * (ssc_rate / ssc_div); | ||
173 | |||
174 | status = clk_round_rate(chip->board->dac_clk, dac_rate_new); | ||
175 | if (status < 0) | ||
176 | return status; | ||
177 | |||
178 | /* Ignore difference smaller than 256 Hz. */ | ||
179 | if ((status/256) == (dac_rate_new/256)) | ||
180 | goto set_rate; | ||
181 | |||
182 | ssc_div += 2; | ||
183 | } while (--max_tries); | ||
184 | |||
185 | /* Not able to find a valid bitrate. */ | ||
186 | return -ENXIO; | ||
187 | |||
188 | set_rate: | ||
189 | status = clk_set_rate(chip->board->dac_clk, status); | ||
190 | if (status < 0) | ||
191 | return status; | ||
192 | |||
193 | /* Set divider in SSC device. */ | ||
194 | ssc_writel(chip->ssc->regs, CMR, ssc_div/2); | ||
195 | |||
196 | /* SSC clock / (ssc divider * 16-bit * stereo). */ | ||
197 | chip->bitrate = ssc_rate / (ssc_div * 16 * 2); | ||
198 | |||
199 | dev_info(&chip->spi->dev, | ||
200 | "at73c213: supported bitrate is %lu (%lu divider)\n", | ||
201 | chip->bitrate, ssc_div); | ||
202 | |||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | static int snd_at73c213_pcm_open(struct snd_pcm_substream *substream) | ||
207 | { | ||
208 | struct snd_at73c213 *chip = snd_pcm_substream_chip(substream); | ||
209 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
210 | |||
211 | snd_at73c213_playback_hw.rate_min = chip->bitrate; | ||
212 | snd_at73c213_playback_hw.rate_max = chip->bitrate; | ||
213 | runtime->hw = snd_at73c213_playback_hw; | ||
214 | chip->substream = substream; | ||
215 | |||
216 | return 0; | ||
217 | } | ||
218 | |||
219 | static int snd_at73c213_pcm_close(struct snd_pcm_substream *substream) | ||
220 | { | ||
221 | struct snd_at73c213 *chip = snd_pcm_substream_chip(substream); | ||
222 | chip->substream = NULL; | ||
223 | return 0; | ||
224 | } | ||
225 | |||
226 | static int snd_at73c213_pcm_hw_params(struct snd_pcm_substream *substream, | ||
227 | struct snd_pcm_hw_params *hw_params) | ||
228 | { | ||
229 | return snd_pcm_lib_malloc_pages(substream, | ||
230 | params_buffer_bytes(hw_params)); | ||
231 | } | ||
232 | |||
233 | static int snd_at73c213_pcm_hw_free(struct snd_pcm_substream *substream) | ||
234 | { | ||
235 | return snd_pcm_lib_free_pages(substream); | ||
236 | } | ||
237 | |||
238 | static int snd_at73c213_pcm_prepare(struct snd_pcm_substream *substream) | ||
239 | { | ||
240 | struct snd_at73c213 *chip = snd_pcm_substream_chip(substream); | ||
241 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
242 | int block_size; | ||
243 | |||
244 | block_size = frames_to_bytes(runtime, runtime->period_size); | ||
245 | |||
246 | chip->period = 0; | ||
247 | |||
248 | ssc_writel(chip->ssc->regs, PDC_TPR, | ||
249 | (long)runtime->dma_addr); | ||
250 | ssc_writel(chip->ssc->regs, PDC_TCR, runtime->period_size * 2); | ||
251 | ssc_writel(chip->ssc->regs, PDC_TNPR, | ||
252 | (long)runtime->dma_addr + block_size); | ||
253 | ssc_writel(chip->ssc->regs, PDC_TNCR, runtime->period_size * 2); | ||
254 | |||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | static int snd_at73c213_pcm_trigger(struct snd_pcm_substream *substream, | ||
259 | int cmd) | ||
260 | { | ||
261 | struct snd_at73c213 *chip = snd_pcm_substream_chip(substream); | ||
262 | int retval = 0; | ||
263 | |||
264 | spin_lock(&chip->lock); | ||
265 | |||
266 | switch (cmd) { | ||
267 | case SNDRV_PCM_TRIGGER_START: | ||
268 | ssc_writel(chip->ssc->regs, IER, SSC_BIT(IER_ENDTX)); | ||
269 | ssc_writel(chip->ssc->regs, PDC_PTCR, SSC_BIT(PDC_PTCR_TXTEN)); | ||
270 | break; | ||
271 | case SNDRV_PCM_TRIGGER_STOP: | ||
272 | ssc_writel(chip->ssc->regs, PDC_PTCR, SSC_BIT(PDC_PTCR_TXTDIS)); | ||
273 | ssc_writel(chip->ssc->regs, IDR, SSC_BIT(IDR_ENDTX)); | ||
274 | break; | ||
275 | default: | ||
276 | dev_dbg(&chip->spi->dev, "spurious command %x\n", cmd); | ||
277 | retval = -EINVAL; | ||
278 | break; | ||
279 | } | ||
280 | |||
281 | spin_unlock(&chip->lock); | ||
282 | |||
283 | return retval; | ||
284 | } | ||
285 | |||
286 | static snd_pcm_uframes_t | ||
287 | snd_at73c213_pcm_pointer(struct snd_pcm_substream *substream) | ||
288 | { | ||
289 | struct snd_at73c213 *chip = snd_pcm_substream_chip(substream); | ||
290 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
291 | snd_pcm_uframes_t pos; | ||
292 | unsigned long bytes; | ||
293 | |||
294 | bytes = ssc_readl(chip->ssc->regs, PDC_TPR) | ||
295 | - (unsigned long)runtime->dma_addr; | ||
296 | |||
297 | pos = bytes_to_frames(runtime, bytes); | ||
298 | if (pos >= runtime->buffer_size) | ||
299 | pos -= runtime->buffer_size; | ||
300 | |||
301 | return pos; | ||
302 | } | ||
303 | |||
304 | static struct snd_pcm_ops at73c213_playback_ops = { | ||
305 | .open = snd_at73c213_pcm_open, | ||
306 | .close = snd_at73c213_pcm_close, | ||
307 | .ioctl = snd_pcm_lib_ioctl, | ||
308 | .hw_params = snd_at73c213_pcm_hw_params, | ||
309 | .hw_free = snd_at73c213_pcm_hw_free, | ||
310 | .prepare = snd_at73c213_pcm_prepare, | ||
311 | .trigger = snd_at73c213_pcm_trigger, | ||
312 | .pointer = snd_at73c213_pcm_pointer, | ||
313 | }; | ||
314 | |||
315 | static void snd_at73c213_pcm_free(struct snd_pcm *pcm) | ||
316 | { | ||
317 | struct snd_at73c213 *chip = snd_pcm_chip(pcm); | ||
318 | if (chip->pcm) { | ||
319 | snd_pcm_lib_preallocate_free_for_all(chip->pcm); | ||
320 | chip->pcm = NULL; | ||
321 | } | ||
322 | } | ||
323 | |||
324 | static int __devinit snd_at73c213_pcm_new(struct snd_at73c213 *chip, int device) | ||
325 | { | ||
326 | struct snd_pcm *pcm; | ||
327 | int retval; | ||
328 | |||
329 | retval = snd_pcm_new(chip->card, chip->card->shortname, | ||
330 | device, 1, 0, &pcm); | ||
331 | if (retval < 0) | ||
332 | goto out; | ||
333 | |||
334 | pcm->private_data = chip; | ||
335 | pcm->private_free = snd_at73c213_pcm_free; | ||
336 | pcm->info_flags = SNDRV_PCM_INFO_BLOCK_TRANSFER; | ||
337 | strcpy(pcm->name, "at73c213"); | ||
338 | chip->pcm = pcm; | ||
339 | |||
340 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &at73c213_playback_ops); | ||
341 | |||
342 | retval = snd_pcm_lib_preallocate_pages_for_all(chip->pcm, | ||
343 | SNDRV_DMA_TYPE_DEV, &chip->ssc->pdev->dev, | ||
344 | 64 * 1024, 64 * 1024); | ||
345 | out: | ||
346 | return retval; | ||
347 | } | ||
348 | |||
349 | static irqreturn_t snd_at73c213_interrupt(int irq, void *dev_id) | ||
350 | { | ||
351 | struct snd_at73c213 *chip = dev_id; | ||
352 | struct snd_pcm_runtime *runtime = chip->substream->runtime; | ||
353 | u32 status; | ||
354 | int offset; | ||
355 | int block_size; | ||
356 | int next_period; | ||
357 | int retval = IRQ_NONE; | ||
358 | |||
359 | spin_lock(&chip->lock); | ||
360 | |||
361 | block_size = frames_to_bytes(runtime, runtime->period_size); | ||
362 | status = ssc_readl(chip->ssc->regs, IMR); | ||
363 | |||
364 | if (status & SSC_BIT(IMR_ENDTX)) { | ||
365 | chip->period++; | ||
366 | if (chip->period == runtime->periods) | ||
367 | chip->period = 0; | ||
368 | next_period = chip->period + 1; | ||
369 | if (next_period == runtime->periods) | ||
370 | next_period = 0; | ||
371 | |||
372 | offset = block_size * next_period; | ||
373 | |||
374 | ssc_writel(chip->ssc->regs, PDC_TNPR, | ||
375 | (long)runtime->dma_addr + offset); | ||
376 | ssc_writel(chip->ssc->regs, PDC_TNCR, runtime->period_size * 2); | ||
377 | retval = IRQ_HANDLED; | ||
378 | } | ||
379 | |||
380 | ssc_readl(chip->ssc->regs, IMR); | ||
381 | spin_unlock(&chip->lock); | ||
382 | |||
383 | if (status & SSC_BIT(IMR_ENDTX)) | ||
384 | snd_pcm_period_elapsed(chip->substream); | ||
385 | |||
386 | return retval; | ||
387 | } | ||
388 | |||
389 | /* | ||
390 | * Mixer functions. | ||
391 | */ | ||
392 | static int snd_at73c213_mono_get(struct snd_kcontrol *kcontrol, | ||
393 | struct snd_ctl_elem_value *ucontrol) | ||
394 | { | ||
395 | struct snd_at73c213 *chip = snd_kcontrol_chip(kcontrol); | ||
396 | int reg = kcontrol->private_value & 0xff; | ||
397 | int shift = (kcontrol->private_value >> 8) & 0xff; | ||
398 | int mask = (kcontrol->private_value >> 16) & 0xff; | ||
399 | int invert = (kcontrol->private_value >> 24) & 0xff; | ||
400 | |||
401 | spin_lock_irq(&chip->lock); | ||
402 | |||
403 | ucontrol->value.integer.value[0] = | ||
404 | (chip->reg_image[reg] >> shift) & mask; | ||
405 | |||
406 | if (invert) | ||
407 | ucontrol->value.integer.value[0] = | ||
408 | mask - ucontrol->value.integer.value[0]; | ||
409 | |||
410 | spin_unlock_irq(&chip->lock); | ||
411 | |||
412 | return 0; | ||
413 | } | ||
414 | |||
415 | static int snd_at73c213_mono_put(struct snd_kcontrol *kcontrol, | ||
416 | struct snd_ctl_elem_value *ucontrol) | ||
417 | { | ||
418 | struct snd_at73c213 *chip = snd_kcontrol_chip(kcontrol); | ||
419 | int reg = kcontrol->private_value & 0xff; | ||
420 | int shift = (kcontrol->private_value >> 8) & 0xff; | ||
421 | int mask = (kcontrol->private_value >> 16) & 0xff; | ||
422 | int invert = (kcontrol->private_value >> 24) & 0xff; | ||
423 | int change, retval; | ||
424 | unsigned short val; | ||
425 | |||
426 | val = (ucontrol->value.integer.value[0] & mask); | ||
427 | if (invert) | ||
428 | val = mask - val; | ||
429 | val <<= shift; | ||
430 | |||
431 | spin_lock_irq(&chip->lock); | ||
432 | |||
433 | val = (chip->reg_image[reg] & ~(mask << shift)) | val; | ||
434 | change = val != chip->reg_image[reg]; | ||
435 | retval = snd_at73c213_write_reg(chip, reg, val); | ||
436 | |||
437 | spin_unlock_irq(&chip->lock); | ||
438 | |||
439 | if (retval) | ||
440 | return retval; | ||
441 | |||
442 | return change; | ||
443 | } | ||
444 | |||
445 | static int snd_at73c213_stereo_info(struct snd_kcontrol *kcontrol, | ||
446 | struct snd_ctl_elem_info *uinfo) | ||
447 | { | ||
448 | int mask = (kcontrol->private_value >> 24) & 0xff; | ||
449 | |||
450 | if (mask == 1) | ||
451 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
452 | else | ||
453 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
454 | |||
455 | uinfo->count = 2; | ||
456 | uinfo->value.integer.min = 0; | ||
457 | uinfo->value.integer.max = mask; | ||
458 | |||
459 | return 0; | ||
460 | } | ||
461 | |||
462 | static int snd_at73c213_stereo_get(struct snd_kcontrol *kcontrol, | ||
463 | struct snd_ctl_elem_value *ucontrol) | ||
464 | { | ||
465 | struct snd_at73c213 *chip = snd_kcontrol_chip(kcontrol); | ||
466 | int left_reg = kcontrol->private_value & 0xff; | ||
467 | int right_reg = (kcontrol->private_value >> 8) & 0xff; | ||
468 | int shift_left = (kcontrol->private_value >> 16) & 0x07; | ||
469 | int shift_right = (kcontrol->private_value >> 19) & 0x07; | ||
470 | int mask = (kcontrol->private_value >> 24) & 0xff; | ||
471 | int invert = (kcontrol->private_value >> 22) & 1; | ||
472 | |||
473 | spin_lock_irq(&chip->lock); | ||
474 | |||
475 | ucontrol->value.integer.value[0] = | ||
476 | (chip->reg_image[left_reg] >> shift_left) & mask; | ||
477 | ucontrol->value.integer.value[1] = | ||
478 | (chip->reg_image[right_reg] >> shift_right) & mask; | ||
479 | |||
480 | if (invert) { | ||
481 | ucontrol->value.integer.value[0] = | ||
482 | mask - ucontrol->value.integer.value[0]; | ||
483 | ucontrol->value.integer.value[1] = | ||
484 | mask - ucontrol->value.integer.value[1]; | ||
485 | } | ||
486 | |||
487 | spin_unlock_irq(&chip->lock); | ||
488 | |||
489 | return 0; | ||
490 | } | ||
491 | |||
492 | static int snd_at73c213_stereo_put(struct snd_kcontrol *kcontrol, | ||
493 | struct snd_ctl_elem_value *ucontrol) | ||
494 | { | ||
495 | struct snd_at73c213 *chip = snd_kcontrol_chip(kcontrol); | ||
496 | int left_reg = kcontrol->private_value & 0xff; | ||
497 | int right_reg = (kcontrol->private_value >> 8) & 0xff; | ||
498 | int shift_left = (kcontrol->private_value >> 16) & 0x07; | ||
499 | int shift_right = (kcontrol->private_value >> 19) & 0x07; | ||
500 | int mask = (kcontrol->private_value >> 24) & 0xff; | ||
501 | int invert = (kcontrol->private_value >> 22) & 1; | ||
502 | int change, retval; | ||
503 | unsigned short val1, val2; | ||
504 | |||
505 | val1 = ucontrol->value.integer.value[0] & mask; | ||
506 | val2 = ucontrol->value.integer.value[1] & mask; | ||
507 | if (invert) { | ||
508 | val1 = mask - val1; | ||
509 | val2 = mask - val2; | ||
510 | } | ||
511 | val1 <<= shift_left; | ||
512 | val2 <<= shift_right; | ||
513 | |||
514 | spin_lock_irq(&chip->lock); | ||
515 | |||
516 | val1 = (chip->reg_image[left_reg] & ~(mask << shift_left)) | val1; | ||
517 | val2 = (chip->reg_image[right_reg] & ~(mask << shift_right)) | val2; | ||
518 | change = val1 != chip->reg_image[left_reg] | ||
519 | || val2 != chip->reg_image[right_reg]; | ||
520 | retval = snd_at73c213_write_reg(chip, left_reg, val1); | ||
521 | if (retval) { | ||
522 | spin_unlock_irq(&chip->lock); | ||
523 | goto out; | ||
524 | } | ||
525 | retval = snd_at73c213_write_reg(chip, right_reg, val2); | ||
526 | if (retval) { | ||
527 | spin_unlock_irq(&chip->lock); | ||
528 | goto out; | ||
529 | } | ||
530 | |||
531 | spin_unlock_irq(&chip->lock); | ||
532 | |||
533 | return change; | ||
534 | |||
535 | out: | ||
536 | return retval; | ||
537 | } | ||
538 | |||
539 | static int snd_at73c213_mono_switch_info(struct snd_kcontrol *kcontrol, | ||
540 | struct snd_ctl_elem_info *uinfo) | ||
541 | { | ||
542 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
543 | uinfo->count = 1; | ||
544 | uinfo->value.integer.min = 0; | ||
545 | uinfo->value.integer.max = 1; | ||
546 | |||
547 | return 0; | ||
548 | } | ||
549 | |||
550 | static int snd_at73c213_mono_switch_get(struct snd_kcontrol *kcontrol, | ||
551 | struct snd_ctl_elem_value *ucontrol) | ||
552 | { | ||
553 | struct snd_at73c213 *chip = snd_kcontrol_chip(kcontrol); | ||
554 | int reg = kcontrol->private_value & 0xff; | ||
555 | int shift = (kcontrol->private_value >> 8) & 0xff; | ||
556 | int invert = (kcontrol->private_value >> 24) & 0xff; | ||
557 | |||
558 | spin_lock_irq(&chip->lock); | ||
559 | |||
560 | ucontrol->value.integer.value[0] = | ||
561 | (chip->reg_image[reg] >> shift) & 0x01; | ||
562 | |||
563 | if (invert) | ||
564 | ucontrol->value.integer.value[0] = | ||
565 | 0x01 - ucontrol->value.integer.value[0]; | ||
566 | |||
567 | spin_unlock_irq(&chip->lock); | ||
568 | |||
569 | return 0; | ||
570 | } | ||
571 | |||
572 | static int snd_at73c213_mono_switch_put(struct snd_kcontrol *kcontrol, | ||
573 | struct snd_ctl_elem_value *ucontrol) | ||
574 | { | ||
575 | struct snd_at73c213 *chip = snd_kcontrol_chip(kcontrol); | ||
576 | int reg = kcontrol->private_value & 0xff; | ||
577 | int shift = (kcontrol->private_value >> 8) & 0xff; | ||
578 | int mask = (kcontrol->private_value >> 16) & 0xff; | ||
579 | int invert = (kcontrol->private_value >> 24) & 0xff; | ||
580 | int change, retval; | ||
581 | unsigned short val; | ||
582 | |||
583 | if (ucontrol->value.integer.value[0]) | ||
584 | val = mask; | ||
585 | else | ||
586 | val = 0; | ||
587 | |||
588 | if (invert) | ||
589 | val = mask - val; | ||
590 | val <<= shift; | ||
591 | |||
592 | spin_lock_irq(&chip->lock); | ||
593 | |||
594 | val |= (chip->reg_image[reg] & ~(mask << shift)); | ||
595 | change = val != chip->reg_image[reg]; | ||
596 | |||
597 | retval = snd_at73c213_write_reg(chip, reg, val); | ||
598 | |||
599 | spin_unlock_irq(&chip->lock); | ||
600 | |||
601 | if (retval) | ||
602 | return retval; | ||
603 | |||
604 | return change; | ||
605 | } | ||
606 | |||
607 | static int snd_at73c213_pa_volume_info(struct snd_kcontrol *kcontrol, | ||
608 | struct snd_ctl_elem_info *uinfo) | ||
609 | { | ||
610 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
611 | uinfo->count = 1; | ||
612 | uinfo->value.integer.min = 0; | ||
613 | uinfo->value.integer.max = ((kcontrol->private_value >> 16) & 0xff) - 1; | ||
614 | |||
615 | return 0; | ||
616 | } | ||
617 | |||
618 | static int snd_at73c213_line_capture_volume_info( | ||
619 | struct snd_kcontrol *kcontrol, | ||
620 | struct snd_ctl_elem_info *uinfo) | ||
621 | { | ||
622 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
623 | uinfo->count = 2; | ||
624 | /* When inverted will give values 0x10001 => 0. */ | ||
625 | uinfo->value.integer.min = 14; | ||
626 | uinfo->value.integer.max = 31; | ||
627 | |||
628 | return 0; | ||
629 | } | ||
630 | |||
631 | static int snd_at73c213_aux_capture_volume_info( | ||
632 | struct snd_kcontrol *kcontrol, | ||
633 | struct snd_ctl_elem_info *uinfo) | ||
634 | { | ||
635 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
636 | uinfo->count = 1; | ||
637 | /* When inverted will give values 0x10001 => 0. */ | ||
638 | uinfo->value.integer.min = 14; | ||
639 | uinfo->value.integer.max = 31; | ||
640 | |||
641 | return 0; | ||
642 | } | ||
643 | |||
644 | #define AT73C213_MONO_SWITCH(xname, xindex, reg, shift, mask, invert) \ | ||
645 | { \ | ||
646 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
647 | .name = xname, \ | ||
648 | .index = xindex, \ | ||
649 | .info = snd_at73c213_mono_switch_info, \ | ||
650 | .get = snd_at73c213_mono_switch_get, \ | ||
651 | .put = snd_at73c213_mono_switch_put, \ | ||
652 | .private_value = (reg | (shift << 8) | (mask << 16) | (invert << 24)) \ | ||
653 | } | ||
654 | |||
655 | #define AT73C213_STEREO(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \ | ||
656 | { \ | ||
657 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
658 | .name = xname, \ | ||
659 | .index = xindex, \ | ||
660 | .info = snd_at73c213_stereo_info, \ | ||
661 | .get = snd_at73c213_stereo_get, \ | ||
662 | .put = snd_at73c213_stereo_put, \ | ||
663 | .private_value = (left_reg | (right_reg << 8) \ | ||
664 | | (shift_left << 16) | (shift_right << 19) \ | ||
665 | | (mask << 24) | (invert << 22)) \ | ||
666 | } | ||
667 | |||
668 | static struct snd_kcontrol_new snd_at73c213_controls[] __devinitdata = { | ||
669 | AT73C213_STEREO("Master Playback Volume", 0, DAC_LMPG, DAC_RMPG, 0, 0, 0x1f, 1), | ||
670 | AT73C213_STEREO("Master Playback Switch", 0, DAC_LMPG, DAC_RMPG, 5, 5, 1, 1), | ||
671 | AT73C213_STEREO("PCM Playback Volume", 0, DAC_LLOG, DAC_RLOG, 0, 0, 0x1f, 1), | ||
672 | AT73C213_STEREO("PCM Playback Switch", 0, DAC_LLOG, DAC_RLOG, 5, 5, 1, 1), | ||
673 | AT73C213_MONO_SWITCH("Mono PA Playback Switch", 0, DAC_CTRL, DAC_CTRL_ONPADRV, | ||
674 | 0x01, 0), | ||
675 | { | ||
676 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
677 | .name = "PA Playback Volume", | ||
678 | .index = 0, | ||
679 | .info = snd_at73c213_pa_volume_info, | ||
680 | .get = snd_at73c213_mono_get, | ||
681 | .put = snd_at73c213_mono_put, | ||
682 | .private_value = PA_CTRL | (PA_CTRL_APAGAIN << 8) | \ | ||
683 | (0x0f << 16) | (1 << 24), | ||
684 | }, | ||
685 | AT73C213_MONO_SWITCH("PA High Gain Playback Switch", 0, PA_CTRL, PA_CTRL_APALP, | ||
686 | 0x01, 1), | ||
687 | AT73C213_MONO_SWITCH("PA Playback Switch", 0, PA_CTRL, PA_CTRL_APAON, 0x01, 0), | ||
688 | { | ||
689 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
690 | .name = "Aux Capture Volume", | ||
691 | .index = 0, | ||
692 | .info = snd_at73c213_aux_capture_volume_info, | ||
693 | .get = snd_at73c213_mono_get, | ||
694 | .put = snd_at73c213_mono_put, | ||
695 | .private_value = DAC_AUXG | (0 << 8) | (0x1f << 16) | (1 << 24), | ||
696 | }, | ||
697 | AT73C213_MONO_SWITCH("Aux Capture Switch", 0, DAC_CTRL, DAC_CTRL_ONAUXIN, | ||
698 | 0x01, 0), | ||
699 | { | ||
700 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
701 | .name = "Line Capture Volume", | ||
702 | .index = 0, | ||
703 | .info = snd_at73c213_line_capture_volume_info, | ||
704 | .get = snd_at73c213_stereo_get, | ||
705 | .put = snd_at73c213_stereo_put, | ||
706 | .private_value = DAC_LLIG | (DAC_RLIG << 8) | (0 << 16) | (0 << 19) | ||
707 | | (0x1f << 24) | (1 << 22), | ||
708 | }, | ||
709 | AT73C213_MONO_SWITCH("Line Capture Switch", 0, DAC_CTRL, 0, 0x03, 0), | ||
710 | }; | ||
711 | |||
712 | static int __devinit snd_at73c213_mixer(struct snd_at73c213 *chip) | ||
713 | { | ||
714 | struct snd_card *card; | ||
715 | int errval, idx; | ||
716 | |||
717 | if (chip == NULL || chip->pcm == NULL) | ||
718 | return -EINVAL; | ||
719 | |||
720 | card = chip->card; | ||
721 | |||
722 | strcpy(card->mixername, chip->pcm->name); | ||
723 | |||
724 | for (idx = 0; idx < ARRAY_SIZE(snd_at73c213_controls); idx++) { | ||
725 | errval = snd_ctl_add(card, | ||
726 | snd_ctl_new1(&snd_at73c213_controls[idx], | ||
727 | chip)); | ||
728 | if (errval < 0) | ||
729 | goto cleanup; | ||
730 | } | ||
731 | |||
732 | return 0; | ||
733 | |||
734 | cleanup: | ||
735 | for (idx = 1; idx < ARRAY_SIZE(snd_at73c213_controls) + 1; idx++) { | ||
736 | struct snd_kcontrol *kctl; | ||
737 | kctl = snd_ctl_find_numid(card, idx); | ||
738 | if (kctl) | ||
739 | snd_ctl_remove(card, kctl); | ||
740 | } | ||
741 | return errval; | ||
742 | } | ||
743 | |||
744 | /* | ||
745 | * Device functions | ||
746 | */ | ||
747 | static int snd_at73c213_ssc_init(struct snd_at73c213 *chip) | ||
748 | { | ||
749 | /* | ||
750 | * Continuous clock output. | ||
751 | * Starts on falling TF. | ||
752 | * Delay 1 cycle (1 bit). | ||
753 | * Periode is 16 bit (16 - 1). | ||
754 | */ | ||
755 | ssc_writel(chip->ssc->regs, TCMR, | ||
756 | SSC_BF(TCMR_CKO, 1) | ||
757 | | SSC_BF(TCMR_START, 4) | ||
758 | | SSC_BF(TCMR_STTDLY, 1) | ||
759 | | SSC_BF(TCMR_PERIOD, 16 - 1)); | ||
760 | /* | ||
761 | * Data length is 16 bit (16 - 1). | ||
762 | * Transmit MSB first. | ||
763 | * Transmit 2 words each transfer. | ||
764 | * Frame sync length is 16 bit (16 - 1). | ||
765 | * Frame starts on negative pulse. | ||
766 | */ | ||
767 | ssc_writel(chip->ssc->regs, TFMR, | ||
768 | SSC_BF(TFMR_DATLEN, 16 - 1) | ||
769 | | SSC_BIT(TFMR_MSBF) | ||
770 | | SSC_BF(TFMR_DATNB, 1) | ||
771 | | SSC_BF(TFMR_FSLEN, 16 - 1) | ||
772 | | SSC_BF(TFMR_FSOS, 1)); | ||
773 | |||
774 | return 0; | ||
775 | } | ||
776 | |||
777 | static int snd_at73c213_chip_init(struct snd_at73c213 *chip) | ||
778 | { | ||
779 | int retval; | ||
780 | unsigned char dac_ctrl = 0; | ||
781 | |||
782 | retval = snd_at73c213_set_bitrate(chip); | ||
783 | if (retval) | ||
784 | goto out; | ||
785 | |||
786 | /* Enable DAC master clock. */ | ||
787 | clk_enable(chip->board->dac_clk); | ||
788 | |||
789 | /* Initialize at73c213 on SPI bus. */ | ||
790 | retval = snd_at73c213_write_reg(chip, DAC_RST, 0x04); | ||
791 | if (retval) | ||
792 | goto out_clk; | ||
793 | msleep(1); | ||
794 | retval = snd_at73c213_write_reg(chip, DAC_RST, 0x03); | ||
795 | if (retval) | ||
796 | goto out_clk; | ||
797 | |||
798 | /* Precharge everything. */ | ||
799 | retval = snd_at73c213_write_reg(chip, DAC_PRECH, 0xff); | ||
800 | if (retval) | ||
801 | goto out_clk; | ||
802 | retval = snd_at73c213_write_reg(chip, PA_CTRL, (1<<PA_CTRL_APAPRECH)); | ||
803 | if (retval) | ||
804 | goto out_clk; | ||
805 | retval = snd_at73c213_write_reg(chip, DAC_CTRL, | ||
806 | (1<<DAC_CTRL_ONLNOL) | (1<<DAC_CTRL_ONLNOR)); | ||
807 | if (retval) | ||
808 | goto out_clk; | ||
809 | |||
810 | msleep(50); | ||
811 | |||
812 | /* Stop precharging PA. */ | ||
813 | retval = snd_at73c213_write_reg(chip, PA_CTRL, | ||
814 | (1<<PA_CTRL_APALP) | 0x0f); | ||
815 | if (retval) | ||
816 | goto out_clk; | ||
817 | |||
818 | msleep(450); | ||
819 | |||
820 | /* Stop precharging DAC, turn on master power. */ | ||
821 | retval = snd_at73c213_write_reg(chip, DAC_PRECH, (1<<DAC_PRECH_ONMSTR)); | ||
822 | if (retval) | ||
823 | goto out_clk; | ||
824 | |||
825 | msleep(1); | ||
826 | |||
827 | /* Turn on DAC. */ | ||
828 | dac_ctrl = (1<<DAC_CTRL_ONDACL) | (1<<DAC_CTRL_ONDACR) | ||
829 | | (1<<DAC_CTRL_ONLNOL) | (1<<DAC_CTRL_ONLNOR); | ||
830 | |||
831 | retval = snd_at73c213_write_reg(chip, DAC_CTRL, dac_ctrl); | ||
832 | if (retval) | ||
833 | goto out_clk; | ||
834 | |||
835 | /* Mute sound. */ | ||
836 | retval = snd_at73c213_write_reg(chip, DAC_LMPG, 0x3f); | ||
837 | if (retval) | ||
838 | goto out_clk; | ||
839 | retval = snd_at73c213_write_reg(chip, DAC_RMPG, 0x3f); | ||
840 | if (retval) | ||
841 | goto out_clk; | ||
842 | retval = snd_at73c213_write_reg(chip, DAC_LLOG, 0x3f); | ||
843 | if (retval) | ||
844 | goto out_clk; | ||
845 | retval = snd_at73c213_write_reg(chip, DAC_RLOG, 0x3f); | ||
846 | if (retval) | ||
847 | goto out_clk; | ||
848 | retval = snd_at73c213_write_reg(chip, DAC_LLIG, 0x11); | ||
849 | if (retval) | ||
850 | goto out_clk; | ||
851 | retval = snd_at73c213_write_reg(chip, DAC_RLIG, 0x11); | ||
852 | if (retval) | ||
853 | goto out_clk; | ||
854 | retval = snd_at73c213_write_reg(chip, DAC_AUXG, 0x11); | ||
855 | if (retval) | ||
856 | goto out_clk; | ||
857 | |||
858 | /* Enable I2S device, i.e. clock output. */ | ||
859 | ssc_writel(chip->ssc->regs, CR, SSC_BIT(CR_TXEN)); | ||
860 | |||
861 | goto out; | ||
862 | |||
863 | out_clk: | ||
864 | clk_disable(chip->board->dac_clk); | ||
865 | out: | ||
866 | return retval; | ||
867 | } | ||
868 | |||
869 | static int snd_at73c213_dev_free(struct snd_device *device) | ||
870 | { | ||
871 | struct snd_at73c213 *chip = device->device_data; | ||
872 | |||
873 | ssc_writel(chip->ssc->regs, CR, SSC_BIT(CR_TXDIS)); | ||
874 | if (chip->irq >= 0) { | ||
875 | free_irq(chip->irq, chip); | ||
876 | chip->irq = -1; | ||
877 | } | ||
878 | |||
879 | return 0; | ||
880 | } | ||
881 | |||
882 | static int __devinit snd_at73c213_dev_init(struct snd_card *card, | ||
883 | struct spi_device *spi) | ||
884 | { | ||
885 | static struct snd_device_ops ops = { | ||
886 | .dev_free = snd_at73c213_dev_free, | ||
887 | }; | ||
888 | struct snd_at73c213 *chip = get_chip(card); | ||
889 | int irq, retval; | ||
890 | |||
891 | irq = chip->ssc->irq; | ||
892 | if (irq < 0) | ||
893 | return irq; | ||
894 | |||
895 | spin_lock_init(&chip->lock); | ||
896 | chip->card = card; | ||
897 | chip->irq = -1; | ||
898 | |||
899 | retval = request_irq(irq, snd_at73c213_interrupt, 0, "at73c213", chip); | ||
900 | if (retval) { | ||
901 | dev_dbg(&chip->spi->dev, "unable to request irq %d\n", irq); | ||
902 | goto out; | ||
903 | } | ||
904 | chip->irq = irq; | ||
905 | |||
906 | memcpy(&chip->reg_image, &snd_at73c213_original_image, | ||
907 | sizeof(snd_at73c213_original_image)); | ||
908 | |||
909 | retval = snd_at73c213_ssc_init(chip); | ||
910 | if (retval) | ||
911 | goto out_irq; | ||
912 | |||
913 | retval = snd_at73c213_chip_init(chip); | ||
914 | if (retval) | ||
915 | goto out_irq; | ||
916 | |||
917 | retval = snd_at73c213_pcm_new(chip, 0); | ||
918 | if (retval) | ||
919 | goto out_irq; | ||
920 | |||
921 | retval = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); | ||
922 | if (retval) | ||
923 | goto out_irq; | ||
924 | |||
925 | retval = snd_at73c213_mixer(chip); | ||
926 | if (retval) | ||
927 | goto out_snd_dev; | ||
928 | |||
929 | snd_card_set_dev(card, &spi->dev); | ||
930 | |||
931 | goto out; | ||
932 | |||
933 | out_snd_dev: | ||
934 | snd_device_free(card, chip); | ||
935 | out_irq: | ||
936 | free_irq(chip->irq, chip); | ||
937 | chip->irq = -1; | ||
938 | out: | ||
939 | return retval; | ||
940 | } | ||
941 | |||
942 | static int snd_at73c213_probe(struct spi_device *spi) | ||
943 | { | ||
944 | struct snd_card *card; | ||
945 | struct snd_at73c213 *chip; | ||
946 | struct at73c213_board_info *board; | ||
947 | int retval; | ||
948 | char id[16]; | ||
949 | |||
950 | board = spi->dev.platform_data; | ||
951 | if (!board) { | ||
952 | dev_dbg(&spi->dev, "no platform_data\n"); | ||
953 | return -ENXIO; | ||
954 | } | ||
955 | |||
956 | if (!board->dac_clk) { | ||
957 | dev_dbg(&spi->dev, "no DAC clk\n"); | ||
958 | return -ENXIO; | ||
959 | } | ||
960 | |||
961 | if (IS_ERR(board->dac_clk)) { | ||
962 | dev_dbg(&spi->dev, "no DAC clk\n"); | ||
963 | return PTR_ERR(board->dac_clk); | ||
964 | } | ||
965 | |||
966 | retval = -ENOMEM; | ||
967 | |||
968 | /* Allocate "card" using some unused identifiers. */ | ||
969 | snprintf(id, sizeof id, "at73c213_%d", board->ssc_id); | ||
970 | card = snd_card_new(-1, id, THIS_MODULE, sizeof(struct snd_at73c213)); | ||
971 | if (!card) | ||
972 | goto out; | ||
973 | |||
974 | chip = card->private_data; | ||
975 | chip->spi = spi; | ||
976 | chip->board = board; | ||
977 | |||
978 | chip->ssc = ssc_request(board->ssc_id); | ||
979 | if (IS_ERR(chip->ssc)) { | ||
980 | dev_dbg(&spi->dev, "could not get ssc%d device\n", | ||
981 | board->ssc_id); | ||
982 | retval = PTR_ERR(chip->ssc); | ||
983 | goto out_card; | ||
984 | } | ||
985 | |||
986 | retval = snd_at73c213_dev_init(card, spi); | ||
987 | if (retval) | ||
988 | goto out_ssc; | ||
989 | |||
990 | strcpy(card->driver, "at73c213"); | ||
991 | strcpy(card->shortname, board->shortname); | ||
992 | sprintf(card->longname, "%s on irq %d", card->shortname, chip->irq); | ||
993 | |||
994 | retval = snd_card_register(card); | ||
995 | if (retval) | ||
996 | goto out_ssc; | ||
997 | |||
998 | dev_set_drvdata(&spi->dev, card); | ||
999 | |||
1000 | goto out; | ||
1001 | |||
1002 | out_ssc: | ||
1003 | ssc_free(chip->ssc); | ||
1004 | out_card: | ||
1005 | snd_card_free(card); | ||
1006 | out: | ||
1007 | return retval; | ||
1008 | } | ||
1009 | |||
1010 | static int __devexit snd_at73c213_remove(struct spi_device *spi) | ||
1011 | { | ||
1012 | struct snd_card *card = dev_get_drvdata(&spi->dev); | ||
1013 | struct snd_at73c213 *chip = card->private_data; | ||
1014 | int retval; | ||
1015 | |||
1016 | /* Stop playback. */ | ||
1017 | ssc_writel(chip->ssc->regs, CR, SSC_BIT(CR_TXDIS)); | ||
1018 | |||
1019 | /* Mute sound. */ | ||
1020 | retval = snd_at73c213_write_reg(chip, DAC_LMPG, 0x3f); | ||
1021 | if (retval) | ||
1022 | goto out; | ||
1023 | retval = snd_at73c213_write_reg(chip, DAC_RMPG, 0x3f); | ||
1024 | if (retval) | ||
1025 | goto out; | ||
1026 | retval = snd_at73c213_write_reg(chip, DAC_LLOG, 0x3f); | ||
1027 | if (retval) | ||
1028 | goto out; | ||
1029 | retval = snd_at73c213_write_reg(chip, DAC_RLOG, 0x3f); | ||
1030 | if (retval) | ||
1031 | goto out; | ||
1032 | retval = snd_at73c213_write_reg(chip, DAC_LLIG, 0x11); | ||
1033 | if (retval) | ||
1034 | goto out; | ||
1035 | retval = snd_at73c213_write_reg(chip, DAC_RLIG, 0x11); | ||
1036 | if (retval) | ||
1037 | goto out; | ||
1038 | retval = snd_at73c213_write_reg(chip, DAC_AUXG, 0x11); | ||
1039 | if (retval) | ||
1040 | goto out; | ||
1041 | |||
1042 | /* Turn off PA. */ | ||
1043 | retval = snd_at73c213_write_reg(chip, PA_CTRL, | ||
1044 | chip->reg_image[PA_CTRL] | 0x0f); | ||
1045 | if (retval) | ||
1046 | goto out; | ||
1047 | msleep(10); | ||
1048 | retval = snd_at73c213_write_reg(chip, PA_CTRL, | ||
1049 | (1 << PA_CTRL_APALP) | 0x0f); | ||
1050 | if (retval) | ||
1051 | goto out; | ||
1052 | |||
1053 | /* Turn off external DAC. */ | ||
1054 | retval = snd_at73c213_write_reg(chip, DAC_CTRL, 0x0c); | ||
1055 | if (retval) | ||
1056 | goto out; | ||
1057 | msleep(2); | ||
1058 | retval = snd_at73c213_write_reg(chip, DAC_CTRL, 0x00); | ||
1059 | if (retval) | ||
1060 | goto out; | ||
1061 | |||
1062 | /* Turn off master power. */ | ||
1063 | retval = snd_at73c213_write_reg(chip, DAC_PRECH, 0x00); | ||
1064 | if (retval) | ||
1065 | goto out; | ||
1066 | |||
1067 | out: | ||
1068 | /* Stop DAC master clock. */ | ||
1069 | clk_disable(chip->board->dac_clk); | ||
1070 | |||
1071 | ssc_free(chip->ssc); | ||
1072 | snd_card_free(card); | ||
1073 | dev_set_drvdata(&spi->dev, NULL); | ||
1074 | |||
1075 | return 0; | ||
1076 | } | ||
1077 | |||
1078 | #ifdef CONFIG_PM | ||
1079 | static int snd_at73c213_suspend(struct spi_device *spi, pm_message_t msg) | ||
1080 | { | ||
1081 | struct snd_card *card = dev_get_drvdata(&spi->dev); | ||
1082 | struct snd_at73c213 *chip = card->private_data; | ||
1083 | |||
1084 | ssc_writel(chip->ssc->regs, CR, SSC_BIT(CR_TXDIS)); | ||
1085 | clk_disable(chip->board->dac_clk); | ||
1086 | |||
1087 | return 0; | ||
1088 | } | ||
1089 | |||
1090 | static int snd_at73c213_resume(struct spi_device *spi) | ||
1091 | { | ||
1092 | struct snd_card *card = dev_get_drvdata(&spi->dev); | ||
1093 | struct snd_at73c213 *chip = card->private_data; | ||
1094 | |||
1095 | clk_enable(chip->board->dac_clk); | ||
1096 | ssc_writel(chip->ssc->regs, CR, SSC_BIT(CR_TXEN)); | ||
1097 | |||
1098 | return 0; | ||
1099 | } | ||
1100 | #else | ||
1101 | #define snd_at73c213_suspend NULL | ||
1102 | #define snd_at73c213_resume NULL | ||
1103 | #endif | ||
1104 | |||
1105 | static struct spi_driver at73c213_driver = { | ||
1106 | .driver = { | ||
1107 | .name = "at73c213", | ||
1108 | }, | ||
1109 | .probe = snd_at73c213_probe, | ||
1110 | .suspend = snd_at73c213_suspend, | ||
1111 | .resume = snd_at73c213_resume, | ||
1112 | .remove = __devexit_p(snd_at73c213_remove), | ||
1113 | }; | ||
1114 | |||
1115 | static int __init at73c213_init(void) | ||
1116 | { | ||
1117 | return spi_register_driver(&at73c213_driver); | ||
1118 | } | ||
1119 | module_init(at73c213_init); | ||
1120 | |||
1121 | static void __exit at73c213_exit(void) | ||
1122 | { | ||
1123 | spi_unregister_driver(&at73c213_driver); | ||
1124 | } | ||
1125 | module_exit(at73c213_exit); | ||
1126 | |||
1127 | MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>"); | ||
1128 | MODULE_DESCRIPTION("Sound driver for AT73C213 with Atmel SSC"); | ||
1129 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/spi/at73c213.h b/sound/spi/at73c213.h new file mode 100644 index 000000000000..fd8b372df5d1 --- /dev/null +++ b/sound/spi/at73c213.h | |||
@@ -0,0 +1,119 @@ | |||
1 | /* | ||
2 | * Driver for the AT73C213 16-bit stereo DAC on Atmel ATSTK1000 | ||
3 | * | ||
4 | * Copyright (C) 2006 - 2007 Atmel Corporation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation; either version 2 of the | ||
9 | * License, or (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||
19 | * 02111-1307, USA. | ||
20 | * | ||
21 | * The full GNU General Public License is included in this | ||
22 | * distribution in the file called COPYING. | ||
23 | */ | ||
24 | |||
25 | #ifndef _SND_AT73C213_H | ||
26 | #define _SND_AT73C213_H | ||
27 | |||
28 | /* DAC control register */ | ||
29 | #define DAC_CTRL 0x00 | ||
30 | #define DAC_CTRL_ONPADRV 7 | ||
31 | #define DAC_CTRL_ONAUXIN 6 | ||
32 | #define DAC_CTRL_ONDACR 5 | ||
33 | #define DAC_CTRL_ONDACL 4 | ||
34 | #define DAC_CTRL_ONLNOR 3 | ||
35 | #define DAC_CTRL_ONLNOL 2 | ||
36 | #define DAC_CTRL_ONLNIR 1 | ||
37 | #define DAC_CTRL_ONLNIL 0 | ||
38 | |||
39 | /* DAC left line in gain register */ | ||
40 | #define DAC_LLIG 0x01 | ||
41 | #define DAC_LLIG_LLIG 0 | ||
42 | |||
43 | /* DAC right line in gain register */ | ||
44 | #define DAC_RLIG 0x02 | ||
45 | #define DAC_RLIG_RLIG 0 | ||
46 | |||
47 | /* DAC Left Master Playback Gain Register */ | ||
48 | #define DAC_LMPG 0x03 | ||
49 | #define DAC_LMPG_LMPG 0 | ||
50 | |||
51 | /* DAC Right Master Playback Gain Register */ | ||
52 | #define DAC_RMPG 0x04 | ||
53 | #define DAC_RMPG_RMPG 0 | ||
54 | |||
55 | /* DAC Left Line Out Gain Register */ | ||
56 | #define DAC_LLOG 0x05 | ||
57 | #define DAC_LLOG_LLOG 0 | ||
58 | |||
59 | /* DAC Right Line Out Gain Register */ | ||
60 | #define DAC_RLOG 0x06 | ||
61 | #define DAC_RLOG_RLOG 0 | ||
62 | |||
63 | /* DAC Output Level Control Register */ | ||
64 | #define DAC_OLC 0x07 | ||
65 | #define DAC_OLC_RSHORT 7 | ||
66 | #define DAC_OLC_ROLC 4 | ||
67 | #define DAC_OLC_LSHORT 3 | ||
68 | #define DAC_OLC_LOLC 0 | ||
69 | |||
70 | /* DAC Mixer Control Register */ | ||
71 | #define DAC_MC 0x08 | ||
72 | #define DAC_MC_INVR 5 | ||
73 | #define DAC_MC_INVL 4 | ||
74 | #define DAC_MC_RMSMIN2 3 | ||
75 | #define DAC_MC_RMSMIN1 2 | ||
76 | #define DAC_MC_LMSMIN2 1 | ||
77 | #define DAC_MC_LMSMIN1 0 | ||
78 | |||
79 | /* DAC Clock and Sampling Frequency Control Register */ | ||
80 | #define DAC_CSFC 0x09 | ||
81 | #define DAC_CSFC_OVRSEL 4 | ||
82 | |||
83 | /* DAC Miscellaneous Register */ | ||
84 | #define DAC_MISC 0x0A | ||
85 | #define DAC_MISC_VCMCAPSEL 7 | ||
86 | #define DAC_MISC_DINTSEL 4 | ||
87 | #define DAC_MISC_DITHEN 3 | ||
88 | #define DAC_MISC_DEEMPEN 2 | ||
89 | #define DAC_MISC_NBITS 0 | ||
90 | |||
91 | /* DAC Precharge Control Register */ | ||
92 | #define DAC_PRECH 0x0C | ||
93 | #define DAC_PRECH_PRCHGPDRV 7 | ||
94 | #define DAC_PRECH_PRCHGAUX1 6 | ||
95 | #define DAC_PRECH_PRCHGLNOR 5 | ||
96 | #define DAC_PRECH_PRCHGLNOL 4 | ||
97 | #define DAC_PRECH_PRCHGLNIR 3 | ||
98 | #define DAC_PRECH_PRCHGLNIL 2 | ||
99 | #define DAC_PRECH_PRCHG 1 | ||
100 | #define DAC_PRECH_ONMSTR 0 | ||
101 | |||
102 | /* DAC Auxiliary Input Gain Control Register */ | ||
103 | #define DAC_AUXG 0x0D | ||
104 | #define DAC_AUXG_AUXG 0 | ||
105 | |||
106 | /* DAC Reset Register */ | ||
107 | #define DAC_RST 0x10 | ||
108 | #define DAC_RST_RESMASK 2 | ||
109 | #define DAC_RST_RESFILZ 1 | ||
110 | #define DAC_RST_RSTZ 0 | ||
111 | |||
112 | /* Power Amplifier Control Register */ | ||
113 | #define PA_CTRL 0x11 | ||
114 | #define PA_CTRL_APAON 6 | ||
115 | #define PA_CTRL_APAPRECH 5 | ||
116 | #define PA_CTRL_APALP 4 | ||
117 | #define PA_CTRL_APAGAIN 0 | ||
118 | |||
119 | #endif /* _SND_AT73C213_H */ | ||
diff --git a/sound/synth/Makefile b/sound/synth/Makefile index 986291dcb914..e99fd76caa17 100644 --- a/sound/synth/Makefile +++ b/sound/synth/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-util-mem-objs := util_mem.o | 6 | snd-util-mem-objs := util_mem.o |
diff --git a/sound/synth/emux/Makefile b/sound/synth/emux/Makefile index 32a102d26709..b69035240cf6 100644 --- a/sound/synth/emux/Makefile +++ b/sound/synth/emux/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-emux-synth-objs := emux.o emux_synth.o emux_seq.o emux_nrpn.o \ | 6 | snd-emux-synth-objs := emux.o emux_synth.o emux_seq.o emux_nrpn.o \ |
diff --git a/sound/synth/util_mem.c b/sound/synth/util_mem.c index 1d9b11f345f8..6fc3d2b2519f 100644 --- a/sound/synth/util_mem.c +++ b/sound/synth/util_mem.c | |||
@@ -116,7 +116,7 @@ __snd_util_memblk_new(struct snd_util_memhdr *hdr, unsigned int units, | |||
116 | if (blk == NULL) | 116 | if (blk == NULL) |
117 | return NULL; | 117 | return NULL; |
118 | 118 | ||
119 | if (! prev || prev == &hdr->block) | 119 | if (prev == &hdr->block) |
120 | blk->offset = 0; | 120 | blk->offset = 0; |
121 | else { | 121 | else { |
122 | struct snd_util_memblk *p = get_memblk(prev); | 122 | struct snd_util_memblk *p = get_memblk(prev); |
diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig index 315360f31278..706143826aff 100644 --- a/sound/usb/Kconfig +++ b/sound/usb/Kconfig | |||
@@ -40,6 +40,7 @@ config SND_USB_CAIAQ | |||
40 | namely: | 40 | namely: |
41 | 41 | ||
42 | * Native Instruments RigKontrol2 | 42 | * Native Instruments RigKontrol2 |
43 | * Native Instruments RigKontrol3 | ||
43 | * Native Instruments Kore Controller | 44 | * Native Instruments Kore Controller |
44 | * Native Instruments Audio Kontrol 1 | 45 | * Native Instruments Audio Kontrol 1 |
45 | * Native Instruments Audio 8 DJ | 46 | * Native Instruments Audio 8 DJ |
@@ -55,6 +56,7 @@ config SND_USB_CAIAQ_INPUT | |||
55 | alpha dials and analog pedals on the following products: | 56 | alpha dials and analog pedals on the following products: |
56 | 57 | ||
57 | * Native Instruments RigKontrol2 | 58 | * Native Instruments RigKontrol2 |
59 | * Native Instruments RigKontrol3 | ||
58 | * Native Instruments Audio Kontrol 1 | 60 | * Native Instruments Audio Kontrol 1 |
59 | 61 | ||
60 | endmenu | 62 | endmenu |
diff --git a/sound/usb/caiaq/caiaq-audio.c b/sound/usb/caiaq/caiaq-audio.c index 0414d766ba07..0666908a2361 100644 --- a/sound/usb/caiaq/caiaq-audio.c +++ b/sound/usb/caiaq/caiaq-audio.c | |||
@@ -648,6 +648,7 @@ int __devinit snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev) | |||
648 | dev->samplerates = dev->pcm_info.rates; | 648 | dev->samplerates = dev->pcm_info.rates; |
649 | switch (dev->chip.usb_id) { | 649 | switch (dev->chip.usb_id) { |
650 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1): | 650 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1): |
651 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3): | ||
651 | dev->samplerates |= SNDRV_PCM_RATE_88200; | 652 | dev->samplerates |= SNDRV_PCM_RATE_88200; |
652 | dev->samplerates |= SNDRV_PCM_RATE_192000; | 653 | dev->samplerates |= SNDRV_PCM_RATE_192000; |
653 | break; | 654 | break; |
diff --git a/sound/usb/caiaq/caiaq-device.c b/sound/usb/caiaq/caiaq-device.c index 4709347326f9..58af8142c571 100644 --- a/sound/usb/caiaq/caiaq-device.c +++ b/sound/usb/caiaq/caiaq-device.c | |||
@@ -41,9 +41,10 @@ | |||
41 | #endif | 41 | #endif |
42 | 42 | ||
43 | MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); | 43 | MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); |
44 | MODULE_DESCRIPTION("caiaq USB audio, version 1.1.0"); | 44 | MODULE_DESCRIPTION("caiaq USB audio, version 1.2.0"); |
45 | MODULE_LICENSE("GPL"); | 45 | MODULE_LICENSE("GPL"); |
46 | MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2}," | 46 | MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2}," |
47 | "{Native Instruments, RigKontrol3}," | ||
47 | "{Native Instruments, Kore Controller}," | 48 | "{Native Instruments, Kore Controller}," |
48 | "{Native Instruments, Audio Kontrol 1}" | 49 | "{Native Instruments, Audio Kontrol 1}" |
49 | "{Native Instruments, Audio 8 DJ}}"); | 50 | "{Native Instruments, Audio 8 DJ}}"); |
@@ -85,6 +86,11 @@ static struct usb_device_id snd_usb_id_table[] = { | |||
85 | { | 86 | { |
86 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE, | 87 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE, |
87 | .idVendor = USB_VID_NATIVEINSTRUMENTS, | 88 | .idVendor = USB_VID_NATIVEINSTRUMENTS, |
89 | .idProduct = USB_PID_RIGKONTROL3 | ||
90 | }, | ||
91 | { | ||
92 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE, | ||
93 | .idVendor = USB_VID_NATIVEINSTRUMENTS, | ||
88 | .idProduct = USB_PID_KORECONTROLLER | 94 | .idProduct = USB_PID_KORECONTROLLER |
89 | }, | 95 | }, |
90 | { | 96 | { |
@@ -226,7 +232,7 @@ int snd_usb_caiaq_set_auto_msg (struct snd_usb_caiaqdev *dev, | |||
226 | static void setup_card(struct snd_usb_caiaqdev *dev) | 232 | static void setup_card(struct snd_usb_caiaqdev *dev) |
227 | { | 233 | { |
228 | int ret; | 234 | int ret; |
229 | char val[3]; | 235 | char val[4]; |
230 | 236 | ||
231 | /* device-specific startup specials */ | 237 | /* device-specific startup specials */ |
232 | switch (dev->chip.usb_id) { | 238 | switch (dev->chip.usb_id) { |
@@ -237,6 +243,14 @@ static void setup_card(struct snd_usb_caiaqdev *dev) | |||
237 | val[2] = 0x01; | 243 | val[2] = 0x01; |
238 | send_command(dev, EP1_CMD_WRITE_IO, val, 3); | 244 | send_command(dev, EP1_CMD_WRITE_IO, val, 3); |
239 | break; | 245 | break; |
246 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3): | ||
247 | /* RigKontrol2 - display two centered dashes ('--') */ | ||
248 | val[0] = 0x00; | ||
249 | val[1] = 0x40; | ||
250 | val[2] = 0x40; | ||
251 | val[3] = 0x00; | ||
252 | send_command(dev, EP1_CMD_WRITE_IO, val, 4); | ||
253 | break; | ||
240 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1): | 254 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1): |
241 | /* Audio Kontrol 1 - make USB-LED stop blinking */ | 255 | /* Audio Kontrol 1 - make USB-LED stop blinking */ |
242 | val[0] = 0x00; | 256 | val[0] = 0x00; |
diff --git a/sound/usb/caiaq/caiaq-device.h b/sound/usb/caiaq/caiaq-device.h index 088d5ec241f3..79bc5be2df7a 100644 --- a/sound/usb/caiaq/caiaq-device.h +++ b/sound/usb/caiaq/caiaq-device.h | |||
@@ -6,6 +6,7 @@ | |||
6 | #define USB_VID_NATIVEINSTRUMENTS 0x17cc | 6 | #define USB_VID_NATIVEINSTRUMENTS 0x17cc |
7 | 7 | ||
8 | #define USB_PID_RIGKONTROL2 0x1969 | 8 | #define USB_PID_RIGKONTROL2 0x1969 |
9 | #define USB_PID_RIGKONTROL3 0x1940 | ||
9 | #define USB_PID_KORECONTROLLER 0x4711 | 10 | #define USB_PID_KORECONTROLLER 0x4711 |
10 | #define USB_PID_AK1 0x0815 | 11 | #define USB_PID_AK1 0x0815 |
11 | #define USB_PID_AUDIO8DJ 0x1978 | 12 | #define USB_PID_AUDIO8DJ 0x1978 |
diff --git a/sound/usb/caiaq/caiaq-input.c b/sound/usb/caiaq/caiaq-input.c index 3acd12db6952..a1de0c608957 100644 --- a/sound/usb/caiaq/caiaq-input.c +++ b/sound/usb/caiaq/caiaq-input.c | |||
@@ -34,6 +34,8 @@ | |||
34 | static unsigned char keycode_ak1[] = { KEY_C, KEY_B, KEY_A }; | 34 | static unsigned char keycode_ak1[] = { KEY_C, KEY_B, KEY_A }; |
35 | static unsigned char keycode_rk2[] = { KEY_1, KEY_2, KEY_3, KEY_4, | 35 | static unsigned char keycode_rk2[] = { KEY_1, KEY_2, KEY_3, KEY_4, |
36 | KEY_5, KEY_6, KEY_7 }; | 36 | KEY_5, KEY_6, KEY_7 }; |
37 | static unsigned char keycode_rk3[] = { KEY_1, KEY_2, KEY_3, KEY_4, | ||
38 | KEY_5, KEY_6, KEY_7, KEY_5, KEY_6 }; | ||
37 | 39 | ||
38 | #define DEG90 (range/2) | 40 | #define DEG90 (range/2) |
39 | #define DEG180 (range) | 41 | #define DEG180 (range) |
@@ -107,7 +109,8 @@ static unsigned int decode_erp(unsigned char a, unsigned char b) | |||
107 | 109 | ||
108 | 110 | ||
109 | static void snd_caiaq_input_read_analog(struct snd_usb_caiaqdev *dev, | 111 | static void snd_caiaq_input_read_analog(struct snd_usb_caiaqdev *dev, |
110 | const char *buf, unsigned int len) | 112 | const unsigned char *buf, |
113 | unsigned int len) | ||
111 | { | 114 | { |
112 | switch(dev->input_dev->id.product) { | 115 | switch(dev->input_dev->id.product) { |
113 | case USB_PID_RIGKONTROL2: | 116 | case USB_PID_RIGKONTROL2: |
@@ -116,6 +119,12 @@ static void snd_caiaq_input_read_analog(struct snd_usb_caiaqdev *dev, | |||
116 | input_report_abs(dev->input_dev, ABS_Z, (buf[2] << 8) |buf[3]); | 119 | input_report_abs(dev->input_dev, ABS_Z, (buf[2] << 8) |buf[3]); |
117 | input_sync(dev->input_dev); | 120 | input_sync(dev->input_dev); |
118 | break; | 121 | break; |
122 | case USB_PID_RIGKONTROL3: | ||
123 | input_report_abs(dev->input_dev, ABS_X, (buf[0] << 8) |buf[1]); | ||
124 | input_report_abs(dev->input_dev, ABS_Y, (buf[2] << 8) |buf[3]); | ||
125 | input_report_abs(dev->input_dev, ABS_Z, (buf[4] << 8) |buf[5]); | ||
126 | input_sync(dev->input_dev); | ||
127 | break; | ||
119 | } | 128 | } |
120 | } | 129 | } |
121 | 130 | ||
@@ -128,7 +137,7 @@ static void snd_caiaq_input_read_erp(struct snd_usb_caiaqdev *dev, | |||
128 | case USB_PID_AK1: | 137 | case USB_PID_AK1: |
129 | i = decode_erp(buf[0], buf[1]); | 138 | i = decode_erp(buf[0], buf[1]); |
130 | input_report_abs(dev->input_dev, ABS_X, i); | 139 | input_report_abs(dev->input_dev, ABS_X, i); |
131 | input_sync(dev->input_dev); | 140 | input_sync(dev->input_dev); |
132 | break; | 141 | break; |
133 | } | 142 | } |
134 | } | 143 | } |
@@ -204,6 +213,20 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev) | |||
204 | input_set_abs_params(input, ABS_Z, 0, 4096, 0, 10); | 213 | input_set_abs_params(input, ABS_Z, 0, 4096, 0, 10); |
205 | snd_usb_caiaq_set_auto_msg(dev, 1, 10, 0); | 214 | snd_usb_caiaq_set_auto_msg(dev, 1, 10, 0); |
206 | break; | 215 | break; |
216 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3): | ||
217 | input->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); | ||
218 | input->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_Z); | ||
219 | input->keycode = keycode_rk3; | ||
220 | input->keycodesize = sizeof(char); | ||
221 | input->keycodemax = ARRAY_SIZE(keycode_rk3); | ||
222 | for (i=0; i<ARRAY_SIZE(keycode_rk3); i++) | ||
223 | set_bit(keycode_rk3[i], input->keybit); | ||
224 | |||
225 | input_set_abs_params(input, ABS_X, 0, 1024, 0, 10); | ||
226 | input_set_abs_params(input, ABS_Y, 0, 1024, 0, 10); | ||
227 | input_set_abs_params(input, ABS_Z, 0, 1024, 0, 10); | ||
228 | snd_usb_caiaq_set_auto_msg(dev, 1, 10, 0); | ||
229 | break; | ||
207 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1): | 230 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1): |
208 | input->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); | 231 | input->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); |
209 | input->absbit[0] = BIT(ABS_X); | 232 | input->absbit[0] = BIT(ABS_X); |
@@ -238,7 +261,6 @@ void snd_usb_caiaq_input_free(struct snd_usb_caiaqdev *dev) | |||
238 | return; | 261 | return; |
239 | 262 | ||
240 | input_unregister_device(dev->input_dev); | 263 | input_unregister_device(dev->input_dev); |
241 | input_free_device(dev->input_dev); | ||
242 | dev->input_dev = NULL; | 264 | dev->input_dev = NULL; |
243 | } | 265 | } |
244 | 266 | ||
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index ac5666f4c6d5..967b823eace0 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c | |||
@@ -123,7 +123,6 @@ struct audioformat { | |||
123 | unsigned int rate_min, rate_max; /* min/max rates */ | 123 | unsigned int rate_min, rate_max; /* min/max rates */ |
124 | unsigned int nr_rates; /* number of rate table entries */ | 124 | unsigned int nr_rates; /* number of rate table entries */ |
125 | unsigned int *rate_table; /* rate table */ | 125 | unsigned int *rate_table; /* rate table */ |
126 | unsigned int needs_knot; /* any unusual rates? */ | ||
127 | }; | 126 | }; |
128 | 127 | ||
129 | struct snd_usb_substream; | 128 | struct snd_usb_substream; |
@@ -1309,7 +1308,11 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) | |||
1309 | 1308 | ||
1310 | /* close the old interface */ | 1309 | /* close the old interface */ |
1311 | if (subs->interface >= 0 && subs->interface != fmt->iface) { | 1310 | if (subs->interface >= 0 && subs->interface != fmt->iface) { |
1312 | usb_set_interface(subs->dev, subs->interface, 0); | 1311 | if (usb_set_interface(subs->dev, subs->interface, 0) < 0) { |
1312 | snd_printk(KERN_ERR "%d:%d:%d: return to setting 0 failed\n", | ||
1313 | dev->devnum, fmt->iface, fmt->altsetting); | ||
1314 | return -EIO; | ||
1315 | } | ||
1313 | subs->interface = -1; | 1316 | subs->interface = -1; |
1314 | subs->format = 0; | 1317 | subs->format = 0; |
1315 | } | 1318 | } |
@@ -1761,7 +1764,7 @@ static int check_hw_params_convention(struct snd_usb_substream *subs) | |||
1761 | channels[f->format] |= (1 << f->channels); | 1764 | channels[f->format] |= (1 << f->channels); |
1762 | rates[f->format] |= f->rates; | 1765 | rates[f->format] |= f->rates; |
1763 | /* needs knot? */ | 1766 | /* needs knot? */ |
1764 | if (f->needs_knot) | 1767 | if (f->rates & SNDRV_PCM_RATE_KNOT) |
1765 | goto __out; | 1768 | goto __out; |
1766 | } | 1769 | } |
1767 | /* check whether channels and rates match for all formats */ | 1770 | /* check whether channels and rates match for all formats */ |
@@ -1817,7 +1820,7 @@ static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime, | |||
1817 | if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS) | 1820 | if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS) |
1818 | return 0; | 1821 | return 0; |
1819 | count += fp->nr_rates; | 1822 | count += fp->nr_rates; |
1820 | if (fp->needs_knot) | 1823 | if (fp->rates & SNDRV_PCM_RATE_KNOT) |
1821 | needs_knot = 1; | 1824 | needs_knot = 1; |
1822 | } | 1825 | } |
1823 | if (!needs_knot) | 1826 | if (!needs_knot) |
@@ -2453,7 +2456,7 @@ static int parse_audio_format_rates(struct snd_usb_audio *chip, struct audioform | |||
2453 | unsigned char *fmt, int offset) | 2456 | unsigned char *fmt, int offset) |
2454 | { | 2457 | { |
2455 | int nr_rates = fmt[offset]; | 2458 | int nr_rates = fmt[offset]; |
2456 | int found; | 2459 | |
2457 | if (fmt[0] < offset + 1 + 3 * (nr_rates ? nr_rates : 2)) { | 2460 | if (fmt[0] < offset + 1 + 3 * (nr_rates ? nr_rates : 2)) { |
2458 | snd_printk(KERN_ERR "%d:%u:%d : invalid FORMAT_TYPE desc\n", | 2461 | snd_printk(KERN_ERR "%d:%u:%d : invalid FORMAT_TYPE desc\n", |
2459 | chip->dev->devnum, fp->iface, fp->altsetting); | 2462 | chip->dev->devnum, fp->iface, fp->altsetting); |
@@ -2464,20 +2467,15 @@ static int parse_audio_format_rates(struct snd_usb_audio *chip, struct audioform | |||
2464 | /* | 2467 | /* |
2465 | * build the rate table and bitmap flags | 2468 | * build the rate table and bitmap flags |
2466 | */ | 2469 | */ |
2467 | int r, idx, c; | 2470 | int r, idx; |
2468 | unsigned int nonzero_rates = 0; | 2471 | unsigned int nonzero_rates = 0; |
2469 | /* this table corresponds to the SNDRV_PCM_RATE_XXX bit */ | 2472 | |
2470 | static unsigned int conv_rates[] = { | ||
2471 | 5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, | ||
2472 | 64000, 88200, 96000, 176400, 192000 | ||
2473 | }; | ||
2474 | fp->rate_table = kmalloc(sizeof(int) * nr_rates, GFP_KERNEL); | 2473 | fp->rate_table = kmalloc(sizeof(int) * nr_rates, GFP_KERNEL); |
2475 | if (fp->rate_table == NULL) { | 2474 | if (fp->rate_table == NULL) { |
2476 | snd_printk(KERN_ERR "cannot malloc\n"); | 2475 | snd_printk(KERN_ERR "cannot malloc\n"); |
2477 | return -1; | 2476 | return -1; |
2478 | } | 2477 | } |
2479 | 2478 | ||
2480 | fp->needs_knot = 0; | ||
2481 | fp->nr_rates = nr_rates; | 2479 | fp->nr_rates = nr_rates; |
2482 | fp->rate_min = fp->rate_max = combine_triple(&fmt[8]); | 2480 | fp->rate_min = fp->rate_max = combine_triple(&fmt[8]); |
2483 | for (r = 0, idx = offset + 1; r < nr_rates; r++, idx += 3) { | 2481 | for (r = 0, idx = offset + 1; r < nr_rates; r++, idx += 3) { |
@@ -2493,23 +2491,12 @@ static int parse_audio_format_rates(struct snd_usb_audio *chip, struct audioform | |||
2493 | fp->rate_min = rate; | 2491 | fp->rate_min = rate; |
2494 | else if (rate > fp->rate_max) | 2492 | else if (rate > fp->rate_max) |
2495 | fp->rate_max = rate; | 2493 | fp->rate_max = rate; |
2496 | found = 0; | 2494 | fp->rates |= snd_pcm_rate_to_rate_bit(rate); |
2497 | for (c = 0; c < (int)ARRAY_SIZE(conv_rates); c++) { | ||
2498 | if (rate == conv_rates[c]) { | ||
2499 | found = 1; | ||
2500 | fp->rates |= (1 << c); | ||
2501 | break; | ||
2502 | } | ||
2503 | } | ||
2504 | if (!found) | ||
2505 | fp->needs_knot = 1; | ||
2506 | } | 2495 | } |
2507 | if (!nonzero_rates) { | 2496 | if (!nonzero_rates) { |
2508 | hwc_debug("All rates were zero. Skipping format!\n"); | 2497 | hwc_debug("All rates were zero. Skipping format!\n"); |
2509 | return -1; | 2498 | return -1; |
2510 | } | 2499 | } |
2511 | if (fp->needs_knot) | ||
2512 | fp->rates |= SNDRV_PCM_RATE_KNOT; | ||
2513 | } else { | 2500 | } else { |
2514 | /* continuous rates */ | 2501 | /* continuous rates */ |
2515 | fp->rates = SNDRV_PCM_RATE_CONTINUOUS; | 2502 | fp->rates = SNDRV_PCM_RATE_CONTINUOUS; |
@@ -2857,6 +2844,10 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif) | |||
2857 | /* skip non-supported classes */ | 2844 | /* skip non-supported classes */ |
2858 | continue; | 2845 | continue; |
2859 | } | 2846 | } |
2847 | if (snd_usb_get_speed(dev) == USB_SPEED_LOW) { | ||
2848 | snd_printk(KERN_ERR "low speed audio streaming not supported\n"); | ||
2849 | continue; | ||
2850 | } | ||
2860 | if (! parse_audio_endpoints(chip, j)) { | 2851 | if (! parse_audio_endpoints(chip, j)) { |
2861 | usb_set_interface(dev, j, 0); /* reset the current interface */ | 2852 | usb_set_interface(dev, j, 0); /* reset the current interface */ |
2862 | usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1L); | 2853 | usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1L); |
@@ -3399,7 +3390,8 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, | |||
3399 | 3390 | ||
3400 | *rchip = NULL; | 3391 | *rchip = NULL; |
3401 | 3392 | ||
3402 | if (snd_usb_get_speed(dev) != USB_SPEED_FULL && | 3393 | if (snd_usb_get_speed(dev) != USB_SPEED_LOW && |
3394 | snd_usb_get_speed(dev) != USB_SPEED_FULL && | ||
3403 | snd_usb_get_speed(dev) != USB_SPEED_HIGH) { | 3395 | snd_usb_get_speed(dev) != USB_SPEED_HIGH) { |
3404 | snd_printk(KERN_ERR "unknown device speed %d\n", snd_usb_get_speed(dev)); | 3396 | snd_printk(KERN_ERR "unknown device speed %d\n", snd_usb_get_speed(dev)); |
3405 | return -ENXIO; | 3397 | return -ENXIO; |
@@ -3473,7 +3465,9 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, | |||
3473 | usb_make_path(dev, card->longname + len, sizeof(card->longname) - len); | 3465 | usb_make_path(dev, card->longname + len, sizeof(card->longname) - len); |
3474 | 3466 | ||
3475 | strlcat(card->longname, | 3467 | strlcat(card->longname, |
3476 | snd_usb_get_speed(dev) == USB_SPEED_FULL ? ", full speed" : ", high speed", | 3468 | snd_usb_get_speed(dev) == USB_SPEED_LOW ? ", low speed" : |
3469 | snd_usb_get_speed(dev) == USB_SPEED_FULL ? ", full speed" : | ||
3470 | ", high speed", | ||
3477 | sizeof(card->longname)); | 3471 | sizeof(card->longname)); |
3478 | 3472 | ||
3479 | snd_usb_audio_create_proc(chip); | 3473 | snd_usb_audio_create_proc(chip); |
diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c index 99295f9b7691..6330788c1c2b 100644 --- a/sound/usb/usbmidi.c +++ b/sound/usb/usbmidi.c | |||
@@ -407,6 +407,20 @@ static void snd_usbmidi_maudio_broken_running_status_input( | |||
407 | } | 407 | } |
408 | 408 | ||
409 | /* | 409 | /* |
410 | * CME protocol: like the standard protocol, but SysEx commands are sent as a | ||
411 | * single USB packet preceded by a 0x0F byte. | ||
412 | */ | ||
413 | static void snd_usbmidi_cme_input(struct snd_usb_midi_in_endpoint *ep, | ||
414 | uint8_t *buffer, int buffer_length) | ||
415 | { | ||
416 | if (buffer_length < 2 || (buffer[0] & 0x0f) != 0x0f) | ||
417 | snd_usbmidi_standard_input(ep, buffer, buffer_length); | ||
418 | else | ||
419 | snd_usbmidi_input_data(ep, buffer[0] >> 4, | ||
420 | &buffer[1], buffer_length - 1); | ||
421 | } | ||
422 | |||
423 | /* | ||
410 | * Adds one USB MIDI packet to the output buffer. | 424 | * Adds one USB MIDI packet to the output buffer. |
411 | */ | 425 | */ |
412 | static void snd_usbmidi_output_standard_packet(struct urb* urb, uint8_t p0, | 426 | static void snd_usbmidi_output_standard_packet(struct urb* urb, uint8_t p0, |
@@ -572,6 +586,12 @@ static struct usb_protocol_ops snd_usbmidi_maudio_broken_running_status_ops = { | |||
572 | .output_packet = snd_usbmidi_output_standard_packet, | 586 | .output_packet = snd_usbmidi_output_standard_packet, |
573 | }; | 587 | }; |
574 | 588 | ||
589 | static struct usb_protocol_ops snd_usbmidi_cme_ops = { | ||
590 | .input = snd_usbmidi_cme_input, | ||
591 | .output = snd_usbmidi_standard_output, | ||
592 | .output_packet = snd_usbmidi_output_standard_packet, | ||
593 | }; | ||
594 | |||
575 | /* | 595 | /* |
576 | * Novation USB MIDI protocol: number of data bytes is in the first byte | 596 | * Novation USB MIDI protocol: number of data bytes is in the first byte |
577 | * (when receiving) (+1!) or in the second byte (when sending); data begins | 597 | * (when receiving) (+1!) or in the second byte (when sending); data begins |
@@ -963,8 +983,10 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi* umidi, | |||
963 | snd_usbmidi_out_endpoint_delete(ep); | 983 | snd_usbmidi_out_endpoint_delete(ep); |
964 | return -ENOMEM; | 984 | return -ENOMEM; |
965 | } | 985 | } |
966 | /* we never use interrupt output pipes */ | 986 | if (ep_info->out_interval) |
967 | pipe = usb_sndbulkpipe(umidi->chip->dev, ep_info->out_ep); | 987 | pipe = usb_sndintpipe(umidi->chip->dev, ep_info->out_ep); |
988 | else | ||
989 | pipe = usb_sndbulkpipe(umidi->chip->dev, ep_info->out_ep); | ||
968 | if (umidi->chip->usb_id == USB_ID(0x0a92, 0x1020)) /* ESI M4U */ | 990 | if (umidi->chip->usb_id == USB_ID(0x0a92, 0x1020)) /* ESI M4U */ |
969 | /* FIXME: we need more URBs to get reasonable bandwidth here: */ | 991 | /* FIXME: we need more URBs to get reasonable bandwidth here: */ |
970 | ep->max_transfer = 4; | 992 | ep->max_transfer = 4; |
@@ -976,8 +998,14 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi* umidi, | |||
976 | snd_usbmidi_out_endpoint_delete(ep); | 998 | snd_usbmidi_out_endpoint_delete(ep); |
977 | return -ENOMEM; | 999 | return -ENOMEM; |
978 | } | 1000 | } |
979 | usb_fill_bulk_urb(ep->urb, umidi->chip->dev, pipe, buffer, | 1001 | if (ep_info->out_interval) |
980 | ep->max_transfer, snd_usbmidi_out_urb_complete, ep); | 1002 | usb_fill_int_urb(ep->urb, umidi->chip->dev, pipe, buffer, |
1003 | ep->max_transfer, snd_usbmidi_out_urb_complete, | ||
1004 | ep, ep_info->out_interval); | ||
1005 | else | ||
1006 | usb_fill_bulk_urb(ep->urb, umidi->chip->dev, | ||
1007 | pipe, buffer, ep->max_transfer, | ||
1008 | snd_usbmidi_out_urb_complete, ep); | ||
981 | ep->urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; | 1009 | ep->urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; |
982 | 1010 | ||
983 | spin_lock_init(&ep->buffer_lock); | 1011 | spin_lock_init(&ep->buffer_lock); |
@@ -1323,6 +1351,13 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi* umidi, | |||
1323 | endpoints[epidx].out_ep = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; | 1351 | endpoints[epidx].out_ep = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; |
1324 | if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) | 1352 | if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) |
1325 | endpoints[epidx].out_interval = ep->bInterval; | 1353 | endpoints[epidx].out_interval = ep->bInterval; |
1354 | else if (snd_usb_get_speed(umidi->chip->dev) == USB_SPEED_LOW) | ||
1355 | /* | ||
1356 | * Low speed bulk transfers don't exist, so | ||
1357 | * force interrupt transfers for devices like | ||
1358 | * ESI MIDI Mate that try to use them anyway. | ||
1359 | */ | ||
1360 | endpoints[epidx].out_interval = 1; | ||
1326 | endpoints[epidx].out_cables = (1 << ms_ep->bNumEmbMIDIJack) - 1; | 1361 | endpoints[epidx].out_cables = (1 << ms_ep->bNumEmbMIDIJack) - 1; |
1327 | snd_printdd(KERN_INFO "EP %02X: %d jack(s)\n", | 1362 | snd_printdd(KERN_INFO "EP %02X: %d jack(s)\n", |
1328 | ep->bEndpointAddress, ms_ep->bNumEmbMIDIJack); | 1363 | ep->bEndpointAddress, ms_ep->bNumEmbMIDIJack); |
@@ -1336,6 +1371,8 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi* umidi, | |||
1336 | endpoints[epidx].in_ep = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; | 1371 | endpoints[epidx].in_ep = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; |
1337 | if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) | 1372 | if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) |
1338 | endpoints[epidx].in_interval = ep->bInterval; | 1373 | endpoints[epidx].in_interval = ep->bInterval; |
1374 | else if (snd_usb_get_speed(umidi->chip->dev) == USB_SPEED_LOW) | ||
1375 | endpoints[epidx].in_interval = 1; | ||
1339 | endpoints[epidx].in_cables = (1 << ms_ep->bNumEmbMIDIJack) - 1; | 1376 | endpoints[epidx].in_cables = (1 << ms_ep->bNumEmbMIDIJack) - 1; |
1340 | snd_printdd(KERN_INFO "EP %02X: %d jack(s)\n", | 1377 | snd_printdd(KERN_INFO "EP %02X: %d jack(s)\n", |
1341 | ep->bEndpointAddress, ms_ep->bNumEmbMIDIJack); | 1378 | ep->bEndpointAddress, ms_ep->bNumEmbMIDIJack); |
@@ -1690,6 +1727,7 @@ int snd_usb_create_midi_interface(struct snd_usb_audio* chip, | |||
1690 | err = snd_usbmidi_detect_endpoints(umidi, &endpoints[0], 1); | 1727 | err = snd_usbmidi_detect_endpoints(umidi, &endpoints[0], 1); |
1691 | break; | 1728 | break; |
1692 | case QUIRK_MIDI_CME: | 1729 | case QUIRK_MIDI_CME: |
1730 | umidi->usb_protocol_ops = &snd_usbmidi_cme_ops; | ||
1693 | err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); | 1731 | err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); |
1694 | break; | 1732 | break; |
1695 | default: | 1733 | default: |
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c index 325d4b6b54aa..5e329690cfb1 100644 --- a/sound/usb/usbmixer.c +++ b/sound/usb/usbmixer.c | |||
@@ -1483,7 +1483,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, unsi | |||
1483 | struct snd_kcontrol *kctl; | 1483 | struct snd_kcontrol *kctl; |
1484 | char **namelist; | 1484 | char **namelist; |
1485 | 1485 | ||
1486 | if (! num_ins || desc[0] < 6 + num_ins) { | 1486 | if (! num_ins || desc[0] < 5 + num_ins) { |
1487 | snd_printk(KERN_ERR "invalid SELECTOR UNIT descriptor %d\n", unitid); | 1487 | snd_printk(KERN_ERR "invalid SELECTOR UNIT descriptor %d\n", unitid); |
1488 | return -EINVAL; | 1488 | return -EINVAL; |
1489 | } | 1489 | } |
@@ -1888,14 +1888,7 @@ static int snd_usb_soundblaster_remote_init(struct usb_mixer_interface *mixer) | |||
1888 | return 0; | 1888 | return 0; |
1889 | } | 1889 | } |
1890 | 1890 | ||
1891 | static int snd_audigy2nx_led_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1891 | #define snd_audigy2nx_led_info snd_ctl_boolean_mono_info |
1892 | { | ||
1893 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1894 | uinfo->count = 1; | ||
1895 | uinfo->value.integer.min = 0; | ||
1896 | uinfo->value.integer.max = 1; | ||
1897 | return 0; | ||
1898 | } | ||
1899 | 1892 | ||
1900 | static int snd_audigy2nx_led_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1893 | static int snd_audigy2nx_led_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1901 | { | 1894 | { |
diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h index 5a2f518c6629..743568f89907 100644 --- a/sound/usb/usbquirks.h +++ b/sound/usb/usbquirks.h | |||
@@ -88,7 +88,19 @@ | |||
88 | .bInterfaceClass = USB_CLASS_AUDIO, | 88 | .bInterfaceClass = USB_CLASS_AUDIO, |
89 | .bInterfaceSubClass = USB_SUBCLASS_AUDIO_CONTROL | 89 | .bInterfaceSubClass = USB_SUBCLASS_AUDIO_CONTROL |
90 | }, | 90 | }, |
91 | 91 | /* E-Mu devices */ | |
92 | { | ||
93 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE, | ||
94 | .idVendor = 0x041e, | ||
95 | .idProduct = 0x3f02, | ||
96 | .bInterfaceClass = USB_CLASS_AUDIO, | ||
97 | }, | ||
98 | { | ||
99 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE, | ||
100 | .idVendor = 0x041e, | ||
101 | .idProduct = 0x3f04, | ||
102 | .bInterfaceClass = USB_CLASS_AUDIO, | ||
103 | }, | ||
92 | /* | 104 | /* |
93 | * Yamaha devices | 105 | * Yamaha devices |
94 | */ | 106 | */ |
@@ -1254,7 +1266,28 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
1254 | } | 1266 | } |
1255 | }, | 1267 | }, |
1256 | /* TODO: add Edirol PC-80 support */ | 1268 | /* TODO: add Edirol PC-80 support */ |
1257 | /* TODO: add Edirol UA-1EX support */ | 1269 | { |
1270 | USB_DEVICE(0x0582, 0x0096), | ||
1271 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
1272 | .vendor_name = "EDIROL", | ||
1273 | .product_name = "UA-1EX", | ||
1274 | .ifnum = QUIRK_ANY_INTERFACE, | ||
1275 | .type = QUIRK_COMPOSITE, | ||
1276 | .data = (const struct snd_usb_audio_quirk[]) { | ||
1277 | { | ||
1278 | .ifnum = 0, | ||
1279 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
1280 | }, | ||
1281 | { | ||
1282 | .ifnum = 1, | ||
1283 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
1284 | }, | ||
1285 | { | ||
1286 | .ifnum = -1 | ||
1287 | } | ||
1288 | } | ||
1289 | } | ||
1290 | }, | ||
1258 | { | 1291 | { |
1259 | USB_DEVICE(0x0582, 0x009a), | 1292 | USB_DEVICE(0x0582, 0x009a), |
1260 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | 1293 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { |
@@ -1567,6 +1600,40 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
1567 | } | 1600 | } |
1568 | } | 1601 | } |
1569 | }, | 1602 | }, |
1603 | { | ||
1604 | USB_DEVICE(0x0763, 0x2019), | ||
1605 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
1606 | /* .vendor_name = "M-Audio", */ | ||
1607 | /* .product_name = "Ozone Academic", */ | ||
1608 | .ifnum = QUIRK_ANY_INTERFACE, | ||
1609 | .type = QUIRK_COMPOSITE, | ||
1610 | .data = & (const struct snd_usb_audio_quirk[]) { | ||
1611 | { | ||
1612 | .ifnum = 0, | ||
1613 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
1614 | }, | ||
1615 | { | ||
1616 | .ifnum = 1, | ||
1617 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
1618 | }, | ||
1619 | { | ||
1620 | .ifnum = 2, | ||
1621 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
1622 | }, | ||
1623 | { | ||
1624 | .ifnum = 3, | ||
1625 | .type = QUIRK_MIDI_MIDIMAN, | ||
1626 | .data = & (const struct snd_usb_midi_endpoint_info) { | ||
1627 | .out_cables = 0x0001, | ||
1628 | .in_cables = 0x0001 | ||
1629 | } | ||
1630 | }, | ||
1631 | { | ||
1632 | .ifnum = -1 | ||
1633 | } | ||
1634 | } | ||
1635 | } | ||
1636 | }, | ||
1570 | 1637 | ||
1571 | /* Casio devices */ | 1638 | /* Casio devices */ |
1572 | { | 1639 | { |
@@ -1709,6 +1776,24 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
1709 | } | 1776 | } |
1710 | }, | 1777 | }, |
1711 | 1778 | ||
1779 | /* Stanton/N2IT Final Scratch v1 device ('Scratchamp') */ | ||
1780 | { | ||
1781 | USB_DEVICE(0x103d, 0x0100), | ||
1782 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
1783 | .vendor_name = "Stanton", | ||
1784 | .product_name = "ScratchAmp", | ||
1785 | .ifnum = QUIRK_NO_INTERFACE | ||
1786 | } | ||
1787 | }, | ||
1788 | { | ||
1789 | USB_DEVICE(0x103d, 0x0101), | ||
1790 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
1791 | .vendor_name = "Stanton", | ||
1792 | .product_name = "ScratchAmp", | ||
1793 | .ifnum = QUIRK_NO_INTERFACE | ||
1794 | } | ||
1795 | }, | ||
1796 | |||
1712 | /* Novation EMS devices */ | 1797 | /* Novation EMS devices */ |
1713 | { | 1798 | { |
1714 | USB_DEVICE_VENDOR_SPEC(0x1235, 0x0001), | 1799 | USB_DEVICE_VENDOR_SPEC(0x1235, 0x0001), |
@@ -1738,6 +1823,17 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
1738 | } | 1823 | } |
1739 | }, | 1824 | }, |
1740 | 1825 | ||
1826 | /* */ | ||
1827 | { | ||
1828 | /* aka. Serato Scratch Live DJ Box */ | ||
1829 | USB_DEVICE(0x13e5, 0x0001), | ||
1830 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
1831 | .vendor_name = "Rane", | ||
1832 | .product_name = "SL-1", | ||
1833 | .ifnum = QUIRK_NO_INTERFACE | ||
1834 | } | ||
1835 | }, | ||
1836 | |||
1741 | /* Miditech devices */ | 1837 | /* Miditech devices */ |
1742 | { | 1838 | { |
1743 | USB_DEVICE(0x4752, 0x0011), | 1839 | USB_DEVICE(0x4752, 0x0011), |