diff options
Diffstat (limited to 'sound/drivers/dummy.c')
-rw-r--r-- | sound/drivers/dummy.c | 126 |
1 files changed, 47 insertions, 79 deletions
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c index 64ef7f62851d..8dfe5d49eafc 100644 --- a/sound/drivers/dummy.c +++ b/sound/drivers/dummy.c | |||
@@ -172,47 +172,33 @@ typedef struct snd_card_dummy_pcm { | |||
172 | static snd_card_t *snd_dummy_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; | 172 | static snd_card_t *snd_dummy_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; |
173 | 173 | ||
174 | 174 | ||
175 | static void snd_card_dummy_pcm_timer_start(snd_pcm_substream_t * substream) | 175 | static inline void snd_card_dummy_pcm_timer_start(snd_card_dummy_pcm_t *dpcm) |
176 | { | 176 | { |
177 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
178 | snd_card_dummy_pcm_t *dpcm = runtime->private_data; | ||
179 | |||
180 | dpcm->timer.expires = 1 + jiffies; | 177 | dpcm->timer.expires = 1 + jiffies; |
181 | add_timer(&dpcm->timer); | 178 | add_timer(&dpcm->timer); |
182 | } | 179 | } |
183 | 180 | ||
184 | static void snd_card_dummy_pcm_timer_stop(snd_pcm_substream_t * substream) | 181 | static inline void snd_card_dummy_pcm_timer_stop(snd_card_dummy_pcm_t *dpcm) |
185 | { | 182 | { |
186 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
187 | snd_card_dummy_pcm_t *dpcm = runtime->private_data; | ||
188 | |||
189 | del_timer(&dpcm->timer); | 183 | del_timer(&dpcm->timer); |
190 | } | 184 | } |
191 | 185 | ||
192 | static int snd_card_dummy_playback_trigger(snd_pcm_substream_t * substream, | 186 | static int snd_card_dummy_pcm_trigger(snd_pcm_substream_t *substream, int cmd) |
193 | int cmd) | ||
194 | { | 187 | { |
195 | if (cmd == SNDRV_PCM_TRIGGER_START) { | 188 | snd_pcm_runtime_t *runtime = substream->runtime; |
196 | snd_card_dummy_pcm_timer_start(substream); | 189 | snd_dummy_card_pcm_t *dpcm = runtime->private_data; |
197 | } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { | 190 | int err = 0; |
198 | snd_card_dummy_pcm_timer_stop(substream); | ||
199 | } else { | ||
200 | return -EINVAL; | ||
201 | } | ||
202 | return 0; | ||
203 | } | ||
204 | 191 | ||
205 | static int snd_card_dummy_capture_trigger(snd_pcm_substream_t * substream, | 192 | spin_lock(&dpcm->lock); |
206 | int cmd) | ||
207 | { | ||
208 | if (cmd == SNDRV_PCM_TRIGGER_START) { | 193 | if (cmd == SNDRV_PCM_TRIGGER_START) { |
209 | snd_card_dummy_pcm_timer_start(substream); | 194 | snd_card_dummy_pcm_timer_start(dpcm); |
210 | } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { | 195 | } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { |
211 | snd_card_dummy_pcm_timer_stop(substream); | 196 | snd_card_dummy_pcm_timer_stop(dpcm); |
212 | } else { | 197 | } else { |
213 | return -EINVAL; | 198 | err = -EINVAL; |
214 | } | 199 | } |
215 | return 0; | 200 | spin_unlock(&dpcm->lock); |
201 | return err; | ||
216 | } | 202 | } |
217 | 203 | ||
218 | static int snd_card_dummy_pcm_prepare(snd_pcm_substream_t * substream) | 204 | static int snd_card_dummy_pcm_prepare(snd_pcm_substream_t * substream) |
@@ -235,42 +221,26 @@ static int snd_card_dummy_pcm_prepare(snd_pcm_substream_t * substream) | |||
235 | return 0; | 221 | return 0; |
236 | } | 222 | } |
237 | 223 | ||
238 | static int snd_card_dummy_playback_prepare(snd_pcm_substream_t * substream) | ||
239 | { | ||
240 | return snd_card_dummy_pcm_prepare(substream); | ||
241 | } | ||
242 | |||
243 | static int snd_card_dummy_capture_prepare(snd_pcm_substream_t * substream) | ||
244 | { | ||
245 | return snd_card_dummy_pcm_prepare(substream); | ||
246 | } | ||
247 | |||
248 | static void snd_card_dummy_pcm_timer_function(unsigned long data) | 224 | static void snd_card_dummy_pcm_timer_function(unsigned long data) |
249 | { | 225 | { |
250 | snd_card_dummy_pcm_t *dpcm = (snd_card_dummy_pcm_t *)data; | 226 | snd_card_dummy_pcm_t *dpcm = (snd_card_dummy_pcm_t *)data; |
251 | 227 | ||
228 | spin_lock(&dpcm->lock); | ||
252 | dpcm->timer.expires = 1 + jiffies; | 229 | dpcm->timer.expires = 1 + jiffies; |
253 | add_timer(&dpcm->timer); | 230 | add_timer(&dpcm->timer); |
254 | spin_lock_irq(&dpcm->lock); | ||
255 | dpcm->pcm_irq_pos += dpcm->pcm_jiffie; | 231 | dpcm->pcm_irq_pos += dpcm->pcm_jiffie; |
256 | dpcm->pcm_buf_pos += dpcm->pcm_jiffie; | 232 | dpcm->pcm_buf_pos += dpcm->pcm_jiffie; |
257 | dpcm->pcm_buf_pos %= dpcm->pcm_size; | 233 | dpcm->pcm_buf_pos %= dpcm->pcm_size; |
258 | if (dpcm->pcm_irq_pos >= dpcm->pcm_count) { | 234 | if (dpcm->pcm_irq_pos >= dpcm->pcm_count) { |
259 | dpcm->pcm_irq_pos %= dpcm->pcm_count; | 235 | dpcm->pcm_irq_pos %= dpcm->pcm_count; |
236 | spin_unlock(&dpcm->lock); | ||
260 | snd_pcm_period_elapsed(dpcm->substream); | 237 | snd_pcm_period_elapsed(dpcm->substream); |
238 | spin_lock(&dpcm->lock); | ||
261 | } | 239 | } |
262 | spin_unlock_irq(&dpcm->lock); | 240 | spin_unlock(&dpcm->lock); |
263 | } | 241 | } |
264 | 242 | ||
265 | static snd_pcm_uframes_t snd_card_dummy_playback_pointer(snd_pcm_substream_t * substream) | 243 | static snd_pcm_uframes_t snd_card_dummy_pcm_pointer(snd_pcm_substream_t * substream) |
266 | { | ||
267 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
268 | snd_card_dummy_pcm_t *dpcm = runtime->private_data; | ||
269 | |||
270 | return bytes_to_frames(runtime, dpcm->pcm_buf_pos); | ||
271 | } | ||
272 | |||
273 | static snd_pcm_uframes_t snd_card_dummy_capture_pointer(snd_pcm_substream_t * substream) | ||
274 | { | 244 | { |
275 | snd_pcm_runtime_t *runtime = substream->runtime; | 245 | snd_pcm_runtime_t *runtime = substream->runtime; |
276 | snd_card_dummy_pcm_t *dpcm = runtime->private_data; | 246 | snd_card_dummy_pcm_t *dpcm = runtime->private_data; |
@@ -316,8 +286,7 @@ static snd_pcm_hardware_t snd_card_dummy_capture = | |||
316 | 286 | ||
317 | static void snd_card_dummy_runtime_free(snd_pcm_runtime_t *runtime) | 287 | static void snd_card_dummy_runtime_free(snd_pcm_runtime_t *runtime) |
318 | { | 288 | { |
319 | snd_card_dummy_pcm_t *dpcm = runtime->private_data; | 289 | kfree(runtime->private_data); |
320 | kfree(dpcm); | ||
321 | } | 290 | } |
322 | 291 | ||
323 | static int snd_card_dummy_hw_params(snd_pcm_substream_t * substream, | 292 | static int snd_card_dummy_hw_params(snd_pcm_substream_t * substream, |
@@ -331,20 +300,29 @@ static int snd_card_dummy_hw_free(snd_pcm_substream_t * substream) | |||
331 | return snd_pcm_lib_free_pages(substream); | 300 | return snd_pcm_lib_free_pages(substream); |
332 | } | 301 | } |
333 | 302 | ||
334 | static int snd_card_dummy_playback_open(snd_pcm_substream_t * substream) | 303 | static snd_card_dummy_pcm_t *new_pcm_stream(snd_pcm_substream_t *substream) |
335 | { | 304 | { |
336 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
337 | snd_card_dummy_pcm_t *dpcm; | 305 | snd_card_dummy_pcm_t *dpcm; |
338 | int err; | ||
339 | 306 | ||
340 | dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL); | 307 | dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL); |
341 | if (dpcm == NULL) | 308 | if (! dpcm) |
342 | return -ENOMEM; | 309 | return dpcm; |
343 | init_timer(&dpcm->timer); | 310 | init_timer(&dpcm->timer); |
344 | dpcm->timer.data = (unsigned long) dpcm; | 311 | dpcm->timer.data = (unsigned long) dpcm; |
345 | dpcm->timer.function = snd_card_dummy_pcm_timer_function; | 312 | dpcm->timer.function = snd_card_dummy_pcm_timer_function; |
346 | spin_lock_init(&dpcm->lock); | 313 | spin_lock_init(&dpcm->lock); |
347 | dpcm->substream = substream; | 314 | dpcm->substream = substream; |
315 | return dpcm; | ||
316 | } | ||
317 | |||
318 | static int snd_card_dummy_playback_open(snd_pcm_substream_t * substream) | ||
319 | { | ||
320 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
321 | snd_card_dummy_pcm_t *dpcm; | ||
322 | int err; | ||
323 | |||
324 | if ((dpcm = new_pcm_stream(substream)) == NULL) | ||
325 | return -ENOMEM; | ||
348 | runtime->private_data = dpcm; | 326 | runtime->private_data = dpcm; |
349 | runtime->private_free = snd_card_dummy_runtime_free; | 327 | runtime->private_free = snd_card_dummy_runtime_free; |
350 | runtime->hw = snd_card_dummy_playback; | 328 | runtime->hw = snd_card_dummy_playback; |
@@ -368,14 +346,8 @@ static int snd_card_dummy_capture_open(snd_pcm_substream_t * substream) | |||
368 | snd_card_dummy_pcm_t *dpcm; | 346 | snd_card_dummy_pcm_t *dpcm; |
369 | int err; | 347 | int err; |
370 | 348 | ||
371 | dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL); | 349 | if ((dpcm = new_pcm_stream(substream)) == NULL) |
372 | if (dpcm == NULL) | ||
373 | return -ENOMEM; | 350 | return -ENOMEM; |
374 | init_timer(&dpcm->timer); | ||
375 | dpcm->timer.data = (unsigned long) dpcm; | ||
376 | dpcm->timer.function = snd_card_dummy_pcm_timer_function; | ||
377 | spin_lock_init(&dpcm->lock); | ||
378 | dpcm->substream = substream; | ||
379 | runtime->private_data = dpcm; | 351 | runtime->private_data = dpcm; |
380 | runtime->private_free = snd_card_dummy_runtime_free; | 352 | runtime->private_free = snd_card_dummy_runtime_free; |
381 | runtime->hw = snd_card_dummy_capture; | 353 | runtime->hw = snd_card_dummy_capture; |
@@ -409,9 +381,9 @@ static snd_pcm_ops_t snd_card_dummy_playback_ops = { | |||
409 | .ioctl = snd_pcm_lib_ioctl, | 381 | .ioctl = snd_pcm_lib_ioctl, |
410 | .hw_params = snd_card_dummy_hw_params, | 382 | .hw_params = snd_card_dummy_hw_params, |
411 | .hw_free = snd_card_dummy_hw_free, | 383 | .hw_free = snd_card_dummy_hw_free, |
412 | .prepare = snd_card_dummy_playback_prepare, | 384 | .prepare = snd_card_dummy_pcm_prepare, |
413 | .trigger = snd_card_dummy_playback_trigger, | 385 | .trigger = snd_card_dummy_pcm_trigger, |
414 | .pointer = snd_card_dummy_playback_pointer, | 386 | .pointer = snd_card_dummy_pcm_pointer, |
415 | }; | 387 | }; |
416 | 388 | ||
417 | static snd_pcm_ops_t snd_card_dummy_capture_ops = { | 389 | static snd_pcm_ops_t snd_card_dummy_capture_ops = { |
@@ -420,9 +392,9 @@ static snd_pcm_ops_t snd_card_dummy_capture_ops = { | |||
420 | .ioctl = snd_pcm_lib_ioctl, | 392 | .ioctl = snd_pcm_lib_ioctl, |
421 | .hw_params = snd_card_dummy_hw_params, | 393 | .hw_params = snd_card_dummy_hw_params, |
422 | .hw_free = snd_card_dummy_hw_free, | 394 | .hw_free = snd_card_dummy_hw_free, |
423 | .prepare = snd_card_dummy_capture_prepare, | 395 | .prepare = snd_card_dummy_pcm_prepare, |
424 | .trigger = snd_card_dummy_capture_trigger, | 396 | .trigger = snd_card_dummy_pcm_trigger, |
425 | .pointer = snd_card_dummy_capture_pointer, | 397 | .pointer = snd_card_dummy_pcm_pointer, |
426 | }; | 398 | }; |
427 | 399 | ||
428 | static int __init snd_card_dummy_pcm(snd_card_dummy_t *dummy, int device, int substreams) | 400 | static int __init snd_card_dummy_pcm(snd_card_dummy_t *dummy, int device, int substreams) |
@@ -461,20 +433,18 @@ static int snd_dummy_volume_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t | |||
461 | static int snd_dummy_volume_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) | 433 | static int snd_dummy_volume_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) |
462 | { | 434 | { |
463 | snd_card_dummy_t *dummy = snd_kcontrol_chip(kcontrol); | 435 | snd_card_dummy_t *dummy = snd_kcontrol_chip(kcontrol); |
464 | unsigned long flags; | ||
465 | int addr = kcontrol->private_value; | 436 | int addr = kcontrol->private_value; |
466 | 437 | ||
467 | spin_lock_irqsave(&dummy->mixer_lock, flags); | 438 | spin_lock_irq(&dummy->mixer_lock); |
468 | ucontrol->value.integer.value[0] = dummy->mixer_volume[addr][0]; | 439 | ucontrol->value.integer.value[0] = dummy->mixer_volume[addr][0]; |
469 | ucontrol->value.integer.value[1] = dummy->mixer_volume[addr][1]; | 440 | ucontrol->value.integer.value[1] = dummy->mixer_volume[addr][1]; |
470 | spin_unlock_irqrestore(&dummy->mixer_lock, flags); | 441 | spin_unlock_irq(&dummy->mixer_lock); |
471 | return 0; | 442 | return 0; |
472 | } | 443 | } |
473 | 444 | ||
474 | static int snd_dummy_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) | 445 | static int snd_dummy_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) |
475 | { | 446 | { |
476 | snd_card_dummy_t *dummy = snd_kcontrol_chip(kcontrol); | 447 | snd_card_dummy_t *dummy = snd_kcontrol_chip(kcontrol); |
477 | unsigned long flags; | ||
478 | int change, addr = kcontrol->private_value; | 448 | int change, addr = kcontrol->private_value; |
479 | int left, right; | 449 | int left, right; |
480 | 450 | ||
@@ -488,12 +458,12 @@ static int snd_dummy_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t | |||
488 | right = -50; | 458 | right = -50; |
489 | if (right > 100) | 459 | if (right > 100) |
490 | right = 100; | 460 | right = 100; |
491 | spin_lock_irqsave(&dummy->mixer_lock, flags); | 461 | spin_lock_irq(&dummy->mixer_lock); |
492 | change = dummy->mixer_volume[addr][0] != left || | 462 | change = dummy->mixer_volume[addr][0] != left || |
493 | dummy->mixer_volume[addr][1] != right; | 463 | dummy->mixer_volume[addr][1] != right; |
494 | dummy->mixer_volume[addr][0] = left; | 464 | dummy->mixer_volume[addr][0] = left; |
495 | dummy->mixer_volume[addr][1] = right; | 465 | dummy->mixer_volume[addr][1] = right; |
496 | spin_unlock_irqrestore(&dummy->mixer_lock, flags); | 466 | spin_unlock_irq(&dummy->mixer_lock); |
497 | return change; | 467 | return change; |
498 | } | 468 | } |
499 | 469 | ||
@@ -515,31 +485,29 @@ static int snd_dummy_capsrc_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t | |||
515 | static int snd_dummy_capsrc_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) | 485 | static int snd_dummy_capsrc_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) |
516 | { | 486 | { |
517 | snd_card_dummy_t *dummy = snd_kcontrol_chip(kcontrol); | 487 | snd_card_dummy_t *dummy = snd_kcontrol_chip(kcontrol); |
518 | unsigned long flags; | ||
519 | int addr = kcontrol->private_value; | 488 | int addr = kcontrol->private_value; |
520 | 489 | ||
521 | spin_lock_irqsave(&dummy->mixer_lock, flags); | 490 | spin_lock_irq(&dummy->mixer_lock); |
522 | ucontrol->value.integer.value[0] = dummy->capture_source[addr][0]; | 491 | ucontrol->value.integer.value[0] = dummy->capture_source[addr][0]; |
523 | ucontrol->value.integer.value[1] = dummy->capture_source[addr][1]; | 492 | ucontrol->value.integer.value[1] = dummy->capture_source[addr][1]; |
524 | spin_unlock_irqrestore(&dummy->mixer_lock, flags); | 493 | spin_unlock_irq(&dummy->mixer_lock); |
525 | return 0; | 494 | return 0; |
526 | } | 495 | } |
527 | 496 | ||
528 | static int snd_dummy_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) | 497 | static int snd_dummy_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) |
529 | { | 498 | { |
530 | snd_card_dummy_t *dummy = snd_kcontrol_chip(kcontrol); | 499 | snd_card_dummy_t *dummy = snd_kcontrol_chip(kcontrol); |
531 | unsigned long flags; | ||
532 | int change, addr = kcontrol->private_value; | 500 | int change, addr = kcontrol->private_value; |
533 | int left, right; | 501 | int left, right; |
534 | 502 | ||
535 | left = ucontrol->value.integer.value[0] & 1; | 503 | left = ucontrol->value.integer.value[0] & 1; |
536 | right = ucontrol->value.integer.value[1] & 1; | 504 | right = ucontrol->value.integer.value[1] & 1; |
537 | spin_lock_irqsave(&dummy->mixer_lock, flags); | 505 | spin_lock_irq(&dummy->mixer_lock); |
538 | change = dummy->capture_source[addr][0] != left && | 506 | change = dummy->capture_source[addr][0] != left && |
539 | dummy->capture_source[addr][1] != right; | 507 | dummy->capture_source[addr][1] != right; |
540 | dummy->capture_source[addr][0] = left; | 508 | dummy->capture_source[addr][0] = left; |
541 | dummy->capture_source[addr][1] = right; | 509 | dummy->capture_source[addr][1] = right; |
542 | spin_unlock_irqrestore(&dummy->mixer_lock, flags); | 510 | spin_unlock_irq(&dummy->mixer_lock); |
543 | return change; | 511 | return change; |
544 | } | 512 | } |
545 | 513 | ||