aboutsummaryrefslogtreecommitdiffstats
path: root/sound/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'sound/drivers')
-rw-r--r--sound/drivers/dummy.c2
-rw-r--r--sound/drivers/opl3/opl3_midi.c28
-rw-r--r--sound/drivers/pcsp/pcsp_lib.c65
-rw-r--r--sound/drivers/pcsp/pcsp_mixer.c2
4 files changed, 55 insertions, 42 deletions
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index 6ba066c41d2e..146ef00f94a3 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -808,8 +808,6 @@ static int __devinit snd_card_dummy_new_mixer(struct snd_dummy *dummy)
808 unsigned int idx; 808 unsigned int idx;
809 int err; 809 int err;
810 810
811 if (snd_BUG_ON(!dummy))
812 return -EINVAL;
813 spin_lock_init(&dummy->mixer_lock); 811 spin_lock_init(&dummy->mixer_lock);
814 strcpy(card->mixername, "Dummy Mixer"); 812 strcpy(card->mixername, "Dummy Mixer");
815 813
diff --git a/sound/drivers/opl3/opl3_midi.c b/sound/drivers/opl3/opl3_midi.c
index 6e7d09ae0e82..7d722a025d0d 100644
--- a/sound/drivers/opl3/opl3_midi.c
+++ b/sound/drivers/opl3/opl3_midi.c
@@ -29,6 +29,8 @@ extern char snd_opl3_regmap[MAX_OPL2_VOICES][4];
29 29
30extern int use_internal_drums; 30extern int use_internal_drums;
31 31
32static void snd_opl3_note_off_unsafe(void *p, int note, int vel,
33 struct snd_midi_channel *chan);
32/* 34/*
33 * The next table looks magical, but it certainly is not. Its values have 35 * The next table looks magical, but it certainly is not. Its values have
34 * been calculated as table[i]=8*log(i/64)/log(2) with an obvious exception 36 * been calculated as table[i]=8*log(i/64)/log(2) with an obvious exception
@@ -242,16 +244,20 @@ void snd_opl3_timer_func(unsigned long data)
242 int again = 0; 244 int again = 0;
243 int i; 245 int i;
244 246
245 spin_lock_irqsave(&opl3->sys_timer_lock, flags); 247 spin_lock_irqsave(&opl3->voice_lock, flags);
246 for (i = 0; i < opl3->max_voices; i++) { 248 for (i = 0; i < opl3->max_voices; i++) {
247 struct snd_opl3_voice *vp = &opl3->voices[i]; 249 struct snd_opl3_voice *vp = &opl3->voices[i];
248 if (vp->state > 0 && vp->note_off_check) { 250 if (vp->state > 0 && vp->note_off_check) {
249 if (vp->note_off == jiffies) 251 if (vp->note_off == jiffies)
250 snd_opl3_note_off(opl3, vp->note, 0, vp->chan); 252 snd_opl3_note_off_unsafe(opl3, vp->note, 0,
253 vp->chan);
251 else 254 else
252 again++; 255 again++;
253 } 256 }
254 } 257 }
258 spin_unlock_irqrestore(&opl3->voice_lock, flags);
259
260 spin_lock_irqsave(&opl3->sys_timer_lock, flags);
255 if (again) { 261 if (again) {
256 opl3->tlist.expires = jiffies + 1; /* invoke again */ 262 opl3->tlist.expires = jiffies + 1; /* invoke again */
257 add_timer(&opl3->tlist); 263 add_timer(&opl3->tlist);
@@ -658,15 +664,14 @@ static void snd_opl3_kill_voice(struct snd_opl3 *opl3, int voice)
658/* 664/*
659 * Release a note in response to a midi note off. 665 * Release a note in response to a midi note off.
660 */ 666 */
661void snd_opl3_note_off(void *p, int note, int vel, struct snd_midi_channel *chan) 667static void snd_opl3_note_off_unsafe(void *p, int note, int vel,
668 struct snd_midi_channel *chan)
662{ 669{
663 struct snd_opl3 *opl3; 670 struct snd_opl3 *opl3;
664 671
665 int voice; 672 int voice;
666 struct snd_opl3_voice *vp; 673 struct snd_opl3_voice *vp;
667 674
668 unsigned long flags;
669
670 opl3 = p; 675 opl3 = p;
671 676
672#ifdef DEBUG_MIDI 677#ifdef DEBUG_MIDI
@@ -674,12 +679,9 @@ void snd_opl3_note_off(void *p, int note, int vel, struct snd_midi_channel *chan
674 chan->number, chan->midi_program, note); 679 chan->number, chan->midi_program, note);
675#endif 680#endif
676 681
677 spin_lock_irqsave(&opl3->voice_lock, flags);
678
679 if (opl3->synth_mode == SNDRV_OPL3_MODE_SEQ) { 682 if (opl3->synth_mode == SNDRV_OPL3_MODE_SEQ) {
680 if (chan->drum_channel && use_internal_drums) { 683 if (chan->drum_channel && use_internal_drums) {
681 snd_opl3_drum_switch(opl3, note, vel, 0, chan); 684 snd_opl3_drum_switch(opl3, note, vel, 0, chan);
682 spin_unlock_irqrestore(&opl3->voice_lock, flags);
683 return; 685 return;
684 } 686 }
685 /* this loop will hopefully kill all extra voices, because 687 /* this loop will hopefully kill all extra voices, because
@@ -697,6 +699,16 @@ void snd_opl3_note_off(void *p, int note, int vel, struct snd_midi_channel *chan
697 snd_opl3_kill_voice(opl3, voice); 699 snd_opl3_kill_voice(opl3, voice);
698 } 700 }
699 } 701 }
702}
703
704void snd_opl3_note_off(void *p, int note, int vel,
705 struct snd_midi_channel *chan)
706{
707 struct snd_opl3 *opl3 = p;
708 unsigned long flags;
709
710 spin_lock_irqsave(&opl3->voice_lock, flags);
711 snd_opl3_note_off_unsafe(p, note, vel, chan);
700 spin_unlock_irqrestore(&opl3->voice_lock, flags); 712 spin_unlock_irqrestore(&opl3->voice_lock, flags);
701} 713}
702 714
diff --git a/sound/drivers/pcsp/pcsp_lib.c b/sound/drivers/pcsp/pcsp_lib.c
index 84cc2658c05b..e1145ac6e908 100644
--- a/sound/drivers/pcsp/pcsp_lib.c
+++ b/sound/drivers/pcsp/pcsp_lib.c
@@ -39,25 +39,20 @@ static DECLARE_TASKLET(pcsp_pcm_tasklet, pcsp_call_pcm_elapsed, 0);
39/* write the port and returns the next expire time in ns; 39/* write the port and returns the next expire time in ns;
40 * called at the trigger-start and in hrtimer callback 40 * called at the trigger-start and in hrtimer callback
41 */ 41 */
42static unsigned long pcsp_timer_update(struct hrtimer *handle) 42static u64 pcsp_timer_update(struct snd_pcsp *chip)
43{ 43{
44 unsigned char timer_cnt, val; 44 unsigned char timer_cnt, val;
45 u64 ns; 45 u64 ns;
46 struct snd_pcm_substream *substream; 46 struct snd_pcm_substream *substream;
47 struct snd_pcm_runtime *runtime; 47 struct snd_pcm_runtime *runtime;
48 struct snd_pcsp *chip = container_of(handle, struct snd_pcsp, timer);
49 unsigned long flags; 48 unsigned long flags;
50 49
51 if (chip->thalf) { 50 if (chip->thalf) {
52 outb(chip->val61, 0x61); 51 outb(chip->val61, 0x61);
53 chip->thalf = 0; 52 chip->thalf = 0;
54 if (!atomic_read(&chip->timer_active))
55 return 0;
56 return chip->ns_rem; 53 return chip->ns_rem;
57 } 54 }
58 55
59 if (!atomic_read(&chip->timer_active))
60 return 0;
61 substream = chip->playback_substream; 56 substream = chip->playback_substream;
62 if (!substream) 57 if (!substream)
63 return 0; 58 return 0;
@@ -88,24 +83,17 @@ static unsigned long pcsp_timer_update(struct hrtimer *handle)
88 return ns; 83 return ns;
89} 84}
90 85
91enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) 86static void pcsp_pointer_update(struct snd_pcsp *chip)
92{ 87{
93 struct snd_pcsp *chip = container_of(handle, struct snd_pcsp, timer);
94 struct snd_pcm_substream *substream; 88 struct snd_pcm_substream *substream;
95 int periods_elapsed, pointer_update;
96 size_t period_bytes, buffer_bytes; 89 size_t period_bytes, buffer_bytes;
97 unsigned long ns; 90 int periods_elapsed;
98 unsigned long flags; 91 unsigned long flags;
99 92
100 pointer_update = !chip->thalf;
101 ns = pcsp_timer_update(handle);
102 if (!ns)
103 return HRTIMER_NORESTART;
104
105 /* update the playback position */ 93 /* update the playback position */
106 substream = chip->playback_substream; 94 substream = chip->playback_substream;
107 if (!substream) 95 if (!substream)
108 return HRTIMER_NORESTART; 96 return;
109 97
110 period_bytes = snd_pcm_lib_period_bytes(substream); 98 period_bytes = snd_pcm_lib_period_bytes(substream);
111 buffer_bytes = snd_pcm_lib_buffer_bytes(substream); 99 buffer_bytes = snd_pcm_lib_buffer_bytes(substream);
@@ -134,6 +122,26 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle)
134 122
135 if (periods_elapsed) 123 if (periods_elapsed)
136 tasklet_schedule(&pcsp_pcm_tasklet); 124 tasklet_schedule(&pcsp_pcm_tasklet);
125}
126
127enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle)
128{
129 struct snd_pcsp *chip = container_of(handle, struct snd_pcsp, timer);
130 int pointer_update;
131 u64 ns;
132
133 if (!atomic_read(&chip->timer_active) || !chip->playback_substream)
134 return HRTIMER_NORESTART;
135
136 pointer_update = !chip->thalf;
137 ns = pcsp_timer_update(chip);
138 if (!ns) {
139 printk(KERN_WARNING "PCSP: unexpected stop\n");
140 return HRTIMER_NORESTART;
141 }
142
143 if (pointer_update)
144 pcsp_pointer_update(chip);
137 145
138 hrtimer_forward(handle, hrtimer_get_expires(handle), ns_to_ktime(ns)); 146 hrtimer_forward(handle, hrtimer_get_expires(handle), ns_to_ktime(ns));
139 147
@@ -142,8 +150,6 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle)
142 150
143static int pcsp_start_playing(struct snd_pcsp *chip) 151static int pcsp_start_playing(struct snd_pcsp *chip)
144{ 152{
145 unsigned long ns;
146
147#if PCSP_DEBUG 153#if PCSP_DEBUG
148 printk(KERN_INFO "PCSP: start_playing called\n"); 154 printk(KERN_INFO "PCSP: start_playing called\n");
149#endif 155#endif
@@ -159,11 +165,7 @@ static int pcsp_start_playing(struct snd_pcsp *chip)
159 atomic_set(&chip->timer_active, 1); 165 atomic_set(&chip->timer_active, 1);
160 chip->thalf = 0; 166 chip->thalf = 0;
161 167
162 ns = pcsp_timer_update(&pcsp_chip.timer); 168 hrtimer_start(&pcsp_chip.timer, ktime_set(0, 0), HRTIMER_MODE_REL);
163 if (!ns)
164 return -EIO;
165
166 hrtimer_start(&pcsp_chip.timer, ktime_set(0, ns), HRTIMER_MODE_REL);
167 return 0; 169 return 0;
168} 170}
169 171
@@ -232,21 +234,22 @@ static int snd_pcsp_playback_hw_free(struct snd_pcm_substream *substream)
232static int snd_pcsp_playback_prepare(struct snd_pcm_substream *substream) 234static int snd_pcsp_playback_prepare(struct snd_pcm_substream *substream)
233{ 235{
234 struct snd_pcsp *chip = snd_pcm_substream_chip(substream); 236 struct snd_pcsp *chip = snd_pcm_substream_chip(substream);
237 pcsp_sync_stop(chip);
238 chip->playback_ptr = 0;
239 chip->period_ptr = 0;
240 chip->fmt_size =
241 snd_pcm_format_physical_width(substream->runtime->format) >> 3;
242 chip->is_signed = snd_pcm_format_signed(substream->runtime->format);
235#if PCSP_DEBUG 243#if PCSP_DEBUG
236 printk(KERN_INFO "PCSP: prepare called, " 244 printk(KERN_INFO "PCSP: prepare called, "
237 "size=%zi psize=%zi f=%zi f1=%i\n", 245 "size=%zi psize=%zi f=%zi f1=%i fsize=%i\n",
238 snd_pcm_lib_buffer_bytes(substream), 246 snd_pcm_lib_buffer_bytes(substream),
239 snd_pcm_lib_period_bytes(substream), 247 snd_pcm_lib_period_bytes(substream),
240 snd_pcm_lib_buffer_bytes(substream) / 248 snd_pcm_lib_buffer_bytes(substream) /
241 snd_pcm_lib_period_bytes(substream), 249 snd_pcm_lib_period_bytes(substream),
242 substream->runtime->periods); 250 substream->runtime->periods,
251 chip->fmt_size);
243#endif 252#endif
244 pcsp_sync_stop(chip);
245 chip->playback_ptr = 0;
246 chip->period_ptr = 0;
247 chip->fmt_size =
248 snd_pcm_format_physical_width(substream->runtime->format) >> 3;
249 chip->is_signed = snd_pcm_format_signed(substream->runtime->format);
250 return 0; 253 return 0;
251} 254}
252 255
diff --git a/sound/drivers/pcsp/pcsp_mixer.c b/sound/drivers/pcsp/pcsp_mixer.c
index 199b03377142..903bc846763f 100644
--- a/sound/drivers/pcsp/pcsp_mixer.c
+++ b/sound/drivers/pcsp/pcsp_mixer.c
@@ -72,7 +72,7 @@ static int pcsp_treble_put(struct snd_kcontrol *kcontrol,
72 if (treble != chip->treble) { 72 if (treble != chip->treble) {
73 chip->treble = treble; 73 chip->treble = treble;
74#if PCSP_DEBUG 74#if PCSP_DEBUG
75 printk(KERN_INFO "PCSP: rate set to %i\n", PCSP_RATE()); 75 printk(KERN_INFO "PCSP: rate set to %li\n", PCSP_RATE());
76#endif 76#endif
77 changed = 1; 77 changed = 1;
78 } 78 }