aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sound/sb.h8
-rw-r--r--sound/isa/sb/sb16_main.c4
-rw-r--r--sound/isa/sb/sb_common.c4
-rw-r--r--sound/isa/sb/sb_mixer.c137
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,
290void snd_sbmixer_write(struct snd_sb *chip, unsigned char reg, unsigned char data); 294void snd_sbmixer_write(struct snd_sb *chip, unsigned char reg, unsigned char data);
291unsigned char snd_sbmixer_read(struct snd_sb *chip, unsigned char reg); 295unsigned char snd_sbmixer_read(struct snd_sb *chip, unsigned char reg);
292int snd_sbmixer_new(struct snd_sb *chip); 296int snd_sbmixer_new(struct snd_sb *chip);
297#ifdef CONFIG_PM
298void snd_sbmixer_suspend(struct snd_sb *chip);
299void snd_sbmixer_resume(struct snd_sb *chip);
300#endif
293 301
294/* sb8_init.c */ 302/* sb8_init.c */
295int snd_sb8dsp_pcm(struct snd_sb *chip, int device, struct snd_pcm ** rpcm); 303int 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);
293EXPORT_SYMBOL(snd_sbmixer_read); 293EXPORT_SYMBOL(snd_sbmixer_read);
294EXPORT_SYMBOL(snd_sbmixer_new); 294EXPORT_SYMBOL(snd_sbmixer_new);
295EXPORT_SYMBOL(snd_sbmixer_add_ctl); 295EXPORT_SYMBOL(snd_sbmixer_add_ctl);
296#ifdef CONFIG_PM
297EXPORT_SYMBOL(snd_sbmixer_suspend);
298EXPORT_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
858static 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
865static 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
877static 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
895static 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
908static 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
927static 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
935static 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
943void 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
968void 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