diff options
Diffstat (limited to 'sound/drivers/pcsp/pcsp_lib.c')
-rw-r--r-- | sound/drivers/pcsp/pcsp_lib.c | 65 |
1 files changed, 34 insertions, 31 deletions
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 | */ |
42 | static unsigned long pcsp_timer_update(struct hrtimer *handle) | 42 | static 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 | ||
91 | enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) | 86 | static 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 | |||
127 | enum 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 | ||
143 | static int pcsp_start_playing(struct snd_pcsp *chip) | 151 | static 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) | |||
232 | static int snd_pcsp_playback_prepare(struct snd_pcm_substream *substream) | 234 | static 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 | ||