diff options
-rw-r--r-- | include/sound/sb.h | 8 | ||||
-rw-r--r-- | sound/isa/sb/sb16_main.c | 4 | ||||
-rw-r--r-- | sound/isa/sb/sb_common.c | 4 | ||||
-rw-r--r-- | sound/isa/sb/sb_mixer.c | 137 |
4 files changed, 153 insertions, 0 deletions
diff --git a/include/sound/sb.h b/include/sound/sb.h index 8e82460c4d34..431d06675e36 100644 --- a/include/sound/sb.h +++ b/include/sound/sb.h | |||
@@ -107,6 +107,10 @@ struct snd_sb { | |||
107 | spinlock_t midi_input_lock; | 107 | spinlock_t midi_input_lock; |
108 | 108 | ||
109 | struct snd_info_entry *proc_entry; | 109 | struct snd_info_entry *proc_entry; |
110 | |||
111 | #ifdef CONFIG_PM | ||
112 | unsigned char saved_regs[0x20]; | ||
113 | #endif | ||
110 | }; | 114 | }; |
111 | 115 | ||
112 | /* I/O ports */ | 116 | /* I/O ports */ |
@@ -290,6 +294,10 @@ int snd_sbdsp_create(struct snd_card *card, | |||
290 | void snd_sbmixer_write(struct snd_sb *chip, unsigned char reg, unsigned char data); | 294 | void snd_sbmixer_write(struct snd_sb *chip, unsigned char reg, unsigned char data); |
291 | unsigned char snd_sbmixer_read(struct snd_sb *chip, unsigned char reg); | 295 | unsigned char snd_sbmixer_read(struct snd_sb *chip, unsigned char reg); |
292 | int snd_sbmixer_new(struct snd_sb *chip); | 296 | int snd_sbmixer_new(struct snd_sb *chip); |
297 | #ifdef CONFIG_PM | ||
298 | void snd_sbmixer_suspend(struct snd_sb *chip); | ||
299 | void snd_sbmixer_resume(struct snd_sb *chip); | ||
300 | #endif | ||
293 | 301 | ||
294 | /* sb8_init.c */ | 302 | /* sb8_init.c */ |
295 | int snd_sb8dsp_pcm(struct snd_sb *chip, int device, struct snd_pcm ** rpcm); | 303 | int snd_sb8dsp_pcm(struct snd_sb *chip, int device, struct snd_pcm ** rpcm); |
diff --git a/sound/isa/sb/sb16_main.c b/sound/isa/sb/sb16_main.c index 97786ed37dd6..f183f1845a36 100644 --- a/sound/isa/sb/sb16_main.c +++ b/sound/isa/sb/sb16_main.c | |||
@@ -307,10 +307,12 @@ static int snd_sb16_playback_trigger(struct snd_pcm_substream *substream, | |||
307 | spin_lock(&chip->reg_lock); | 307 | spin_lock(&chip->reg_lock); |
308 | switch (cmd) { | 308 | switch (cmd) { |
309 | case SNDRV_PCM_TRIGGER_START: | 309 | case SNDRV_PCM_TRIGGER_START: |
310 | case SNDRV_PCM_TRIGGER_RESUME: | ||
310 | chip->mode |= SB_RATE_LOCK_PLAYBACK; | 311 | chip->mode |= SB_RATE_LOCK_PLAYBACK; |
311 | snd_sbdsp_command(chip, chip->mode & SB_MODE_PLAYBACK_16 ? SB_DSP_DMA16_ON : SB_DSP_DMA8_ON); | 312 | snd_sbdsp_command(chip, chip->mode & SB_MODE_PLAYBACK_16 ? SB_DSP_DMA16_ON : SB_DSP_DMA8_ON); |
312 | break; | 313 | break; |
313 | case SNDRV_PCM_TRIGGER_STOP: | 314 | case SNDRV_PCM_TRIGGER_STOP: |
315 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
314 | snd_sbdsp_command(chip, chip->mode & SB_MODE_PLAYBACK_16 ? SB_DSP_DMA16_OFF : SB_DSP_DMA8_OFF); | 316 | snd_sbdsp_command(chip, chip->mode & SB_MODE_PLAYBACK_16 ? SB_DSP_DMA16_OFF : SB_DSP_DMA8_OFF); |
315 | /* next two lines are needed for some types of DSP4 (SB AWE 32 - 4.13) */ | 317 | /* next two lines are needed for some types of DSP4 (SB AWE 32 - 4.13) */ |
316 | if (chip->mode & SB_RATE_LOCK_CAPTURE) | 318 | if (chip->mode & SB_RATE_LOCK_CAPTURE) |
@@ -374,10 +376,12 @@ static int snd_sb16_capture_trigger(struct snd_pcm_substream *substream, | |||
374 | spin_lock(&chip->reg_lock); | 376 | spin_lock(&chip->reg_lock); |
375 | switch (cmd) { | 377 | switch (cmd) { |
376 | case SNDRV_PCM_TRIGGER_START: | 378 | case SNDRV_PCM_TRIGGER_START: |
379 | case SNDRV_PCM_TRIGGER_RESUME: | ||
377 | chip->mode |= SB_RATE_LOCK_CAPTURE; | 380 | chip->mode |= SB_RATE_LOCK_CAPTURE; |
378 | snd_sbdsp_command(chip, chip->mode & SB_MODE_CAPTURE_16 ? SB_DSP_DMA16_ON : SB_DSP_DMA8_ON); | 381 | snd_sbdsp_command(chip, chip->mode & SB_MODE_CAPTURE_16 ? SB_DSP_DMA16_ON : SB_DSP_DMA8_ON); |
379 | break; | 382 | break; |
380 | case SNDRV_PCM_TRIGGER_STOP: | 383 | case SNDRV_PCM_TRIGGER_STOP: |
384 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
381 | snd_sbdsp_command(chip, chip->mode & SB_MODE_CAPTURE_16 ? SB_DSP_DMA16_OFF : SB_DSP_DMA8_OFF); | 385 | snd_sbdsp_command(chip, chip->mode & SB_MODE_CAPTURE_16 ? SB_DSP_DMA16_OFF : SB_DSP_DMA8_OFF); |
382 | /* next two lines are needed for some types of DSP4 (SB AWE 32 - 4.13) */ | 386 | /* next two lines are needed for some types of DSP4 (SB AWE 32 - 4.13) */ |
383 | if (chip->mode & SB_RATE_LOCK_PLAYBACK) | 387 | if (chip->mode & SB_RATE_LOCK_PLAYBACK) |
diff --git a/sound/isa/sb/sb_common.c b/sound/isa/sb/sb_common.c index eb86b4456eef..f343a8211d2d 100644 --- a/sound/isa/sb/sb_common.c +++ b/sound/isa/sb/sb_common.c | |||
@@ -293,6 +293,10 @@ EXPORT_SYMBOL(snd_sbmixer_write); | |||
293 | EXPORT_SYMBOL(snd_sbmixer_read); | 293 | EXPORT_SYMBOL(snd_sbmixer_read); |
294 | EXPORT_SYMBOL(snd_sbmixer_new); | 294 | EXPORT_SYMBOL(snd_sbmixer_new); |
295 | EXPORT_SYMBOL(snd_sbmixer_add_ctl); | 295 | EXPORT_SYMBOL(snd_sbmixer_add_ctl); |
296 | #ifdef CONFIG_PM | ||
297 | EXPORT_SYMBOL(snd_sbmixer_suspend); | ||
298 | EXPORT_SYMBOL(snd_sbmixer_resume); | ||
299 | #endif | ||
296 | 300 | ||
297 | /* | 301 | /* |
298 | * INIT part | 302 | * INIT part |
diff --git a/sound/isa/sb/sb_mixer.c b/sound/isa/sb/sb_mixer.c index 6e0b935a8b85..1a6ee344dddb 100644 --- a/sound/isa/sb/sb_mixer.c +++ b/sound/isa/sb/sb_mixer.c | |||
@@ -853,3 +853,140 @@ int snd_sbmixer_new(struct snd_sb *chip) | |||
853 | } | 853 | } |
854 | return 0; | 854 | return 0; |
855 | } | 855 | } |
856 | |||
857 | #ifdef CONFIG_PM | ||
858 | static unsigned char sb20_saved_regs[] = { | ||
859 | SB_DSP20_MASTER_DEV, | ||
860 | SB_DSP20_PCM_DEV, | ||
861 | SB_DSP20_FM_DEV, | ||
862 | SB_DSP20_CD_DEV, | ||
863 | }; | ||
864 | |||
865 | static unsigned char sbpro_saved_regs[] = { | ||
866 | SB_DSP_MASTER_DEV, | ||
867 | SB_DSP_PCM_DEV, | ||
868 | SB_DSP_PLAYBACK_FILT, | ||
869 | SB_DSP_FM_DEV, | ||
870 | SB_DSP_CD_DEV, | ||
871 | SB_DSP_LINE_DEV, | ||
872 | SB_DSP_MIC_DEV, | ||
873 | SB_DSP_CAPTURE_SOURCE, | ||
874 | SB_DSP_CAPTURE_FILT, | ||
875 | }; | ||
876 | |||
877 | static unsigned char sb16_saved_regs[] = { | ||
878 | SB_DSP4_MASTER_DEV, SB_DSP4_MASTER_DEV + 1, | ||
879 | SB_DSP4_3DSE, | ||
880 | SB_DSP4_BASS_DEV, SB_DSP4_BASS_DEV + 1, | ||
881 | SB_DSP4_TREBLE_DEV, SB_DSP4_TREBLE_DEV + 1, | ||
882 | SB_DSP4_PCM_DEV, SB_DSP4_PCM_DEV + 1, | ||
883 | SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, | ||
884 | SB_DSP4_SYNTH_DEV, SB_DSP4_SYNTH_DEV + 1, | ||
885 | SB_DSP4_OUTPUT_SW, | ||
886 | SB_DSP4_CD_DEV, SB_DSP4_CD_DEV + 1, | ||
887 | SB_DSP4_LINE_DEV, SB_DSP4_LINE_DEV + 1, | ||
888 | SB_DSP4_MIC_DEV, | ||
889 | SB_DSP4_SPEAKER_DEV, | ||
890 | SB_DSP4_IGAIN_DEV, SB_DSP4_IGAIN_DEV + 1, | ||
891 | SB_DSP4_OGAIN_DEV, SB_DSP4_OGAIN_DEV + 1, | ||
892 | SB_DSP4_MIC_AGC | ||
893 | }; | ||
894 | |||
895 | static unsigned char dt019x_saved_regs[] = { | ||
896 | SB_DT019X_MASTER_DEV, | ||
897 | SB_DT019X_PCM_DEV, | ||
898 | SB_DT019X_SYNTH_DEV, | ||
899 | SB_DT019X_CD_DEV, | ||
900 | SB_DT019X_MIC_DEV, | ||
901 | SB_DT019X_SPKR_DEV, | ||
902 | SB_DT019X_LINE_DEV, | ||
903 | SB_DSP4_OUTPUT_SW, | ||
904 | SB_DT019X_OUTPUT_SW2, | ||
905 | SB_DT019X_CAPTURE_SW, | ||
906 | }; | ||
907 | |||
908 | static unsigned char als4000_saved_regs[] = { | ||
909 | SB_DSP4_MASTER_DEV, SB_DSP4_MASTER_DEV + 1, | ||
910 | SB_DSP4_OUTPUT_SW, | ||
911 | SB_DSP4_PCM_DEV, SB_DSP4_PCM_DEV + 1, | ||
912 | SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, | ||
913 | SB_DSP4_SYNTH_DEV, SB_DSP4_SYNTH_DEV + 1, | ||
914 | SB_DSP4_CD_DEV, SB_DSP4_CD_DEV + 1, | ||
915 | SB_DSP4_MIC_AGC, | ||
916 | SB_DSP4_MIC_DEV, | ||
917 | SB_DSP4_SPEAKER_DEV, | ||
918 | SB_DSP4_IGAIN_DEV, SB_DSP4_IGAIN_DEV + 1, | ||
919 | SB_DSP4_OGAIN_DEV, SB_DSP4_OGAIN_DEV + 1, | ||
920 | SB_DT019X_OUTPUT_SW2, | ||
921 | SB_ALS4000_MONO_IO_CTRL, | ||
922 | SB_ALS4000_MIC_IN_GAIN, | ||
923 | SB_ALS4000_3D_SND_FX, | ||
924 | SB_ALS4000_3D_TIME_DELAY, | ||
925 | }; | ||
926 | |||
927 | static void save_mixer(struct snd_sb *chip, unsigned char *regs, int num_regs) | ||
928 | { | ||
929 | unsigned char *val = chip->saved_regs; | ||
930 | snd_assert(num_regs > ARRAY_SIZE(chip->saved_regs), return); | ||
931 | for (; num_regs; num_regs--) | ||
932 | *val++ = snd_sbmixer_read(chip, *regs++); | ||
933 | } | ||
934 | |||
935 | static void restore_mixer(struct snd_sb *chip, unsigned char *regs, int num_regs) | ||
936 | { | ||
937 | unsigned char *val = chip->saved_regs; | ||
938 | snd_assert(num_regs > ARRAY_SIZE(chip->saved_regs), return); | ||
939 | for (; num_regs; num_regs--) | ||
940 | snd_sbmixer_write(chip, *regs++, *val++); | ||
941 | } | ||
942 | |||
943 | void snd_sbmixer_suspend(struct snd_sb *chip) | ||
944 | { | ||
945 | switch (chip->hardware) { | ||
946 | case SB_HW_20: | ||
947 | case SB_HW_201: | ||
948 | save_mixer(chip, sb20_saved_regs, ARRAY_SIZE(sb20_saved_regs)); | ||
949 | break; | ||
950 | case SB_HW_PRO: | ||
951 | save_mixer(chip, sbpro_saved_regs, ARRAY_SIZE(sbpro_saved_regs)); | ||
952 | break; | ||
953 | case SB_HW_16: | ||
954 | case SB_HW_ALS100: | ||
955 | save_mixer(chip, sb16_saved_regs, ARRAY_SIZE(sb16_saved_regs)); | ||
956 | break; | ||
957 | case SB_HW_ALS4000: | ||
958 | save_mixer(chip, als4000_saved_regs, ARRAY_SIZE(als4000_saved_regs)); | ||
959 | break; | ||
960 | case SB_HW_DT019X: | ||
961 | save_mixer(chip, dt019x_saved_regs, ARRAY_SIZE(dt019x_saved_regs)); | ||
962 | break; | ||
963 | default: | ||
964 | break; | ||
965 | } | ||
966 | } | ||
967 | |||
968 | void snd_sbmixer_resume(struct snd_sb *chip) | ||
969 | { | ||
970 | switch (chip->hardware) { | ||
971 | case SB_HW_20: | ||
972 | case SB_HW_201: | ||
973 | restore_mixer(chip, sb20_saved_regs, ARRAY_SIZE(sb20_saved_regs)); | ||
974 | break; | ||
975 | case SB_HW_PRO: | ||
976 | restore_mixer(chip, sbpro_saved_regs, ARRAY_SIZE(sbpro_saved_regs)); | ||
977 | break; | ||
978 | case SB_HW_16: | ||
979 | case SB_HW_ALS100: | ||
980 | restore_mixer(chip, sb16_saved_regs, ARRAY_SIZE(sb16_saved_regs)); | ||
981 | break; | ||
982 | case SB_HW_ALS4000: | ||
983 | restore_mixer(chip, als4000_saved_regs, ARRAY_SIZE(als4000_saved_regs)); | ||
984 | break; | ||
985 | case SB_HW_DT019X: | ||
986 | restore_mixer(chip, dt019x_saved_regs, ARRAY_SIZE(dt019x_saved_regs)); | ||
987 | break; | ||
988 | default: | ||
989 | break; | ||
990 | } | ||
991 | } | ||
992 | #endif | ||