diff options
| -rw-r--r-- | sound/core/pcm_native.c | 73 | ||||
| -rw-r--r-- | sound/pci/lx6464es/lx6464es.h | 2 | ||||
| -rw-r--r-- | sound/pci/lx6464es/lx_core.c | 98 |
3 files changed, 21 insertions, 152 deletions
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 59e5fbe6af51..561d6d95a2d3 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c | |||
| @@ -1387,11 +1387,6 @@ static struct action_ops snd_pcm_action_drain_init = { | |||
| 1387 | .post_action = snd_pcm_post_drain_init | 1387 | .post_action = snd_pcm_post_drain_init |
| 1388 | }; | 1388 | }; |
| 1389 | 1389 | ||
| 1390 | struct drain_rec { | ||
| 1391 | struct snd_pcm_substream *substream; | ||
| 1392 | wait_queue_t wait; | ||
| 1393 | }; | ||
| 1394 | |||
| 1395 | static int snd_pcm_drop(struct snd_pcm_substream *substream); | 1390 | static int snd_pcm_drop(struct snd_pcm_substream *substream); |
| 1396 | 1391 | ||
| 1397 | /* | 1392 | /* |
| @@ -1407,10 +1402,9 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, | |||
| 1407 | struct snd_card *card; | 1402 | struct snd_card *card; |
| 1408 | struct snd_pcm_runtime *runtime; | 1403 | struct snd_pcm_runtime *runtime; |
| 1409 | struct snd_pcm_substream *s; | 1404 | struct snd_pcm_substream *s; |
| 1405 | wait_queue_t wait; | ||
| 1410 | int result = 0; | 1406 | int result = 0; |
| 1411 | int i, num_drecs; | ||
| 1412 | int nonblock = 0; | 1407 | int nonblock = 0; |
| 1413 | struct drain_rec *drec, drec_tmp, *d; | ||
| 1414 | 1408 | ||
| 1415 | card = substream->pcm->card; | 1409 | card = substream->pcm->card; |
| 1416 | runtime = substream->runtime; | 1410 | runtime = substream->runtime; |
| @@ -1433,38 +1427,10 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, | |||
| 1433 | } else if (substream->f_flags & O_NONBLOCK) | 1427 | } else if (substream->f_flags & O_NONBLOCK) |
| 1434 | nonblock = 1; | 1428 | nonblock = 1; |
| 1435 | 1429 | ||
| 1436 | if (nonblock) | ||
| 1437 | goto lock; /* no need to allocate waitqueues */ | ||
| 1438 | |||
| 1439 | /* allocate temporary record for drain sync */ | ||
| 1440 | down_read(&snd_pcm_link_rwsem); | 1430 | down_read(&snd_pcm_link_rwsem); |
| 1441 | if (snd_pcm_stream_linked(substream)) { | ||
| 1442 | drec = kmalloc(substream->group->count * sizeof(*drec), GFP_KERNEL); | ||
| 1443 | if (! drec) { | ||
| 1444 | up_read(&snd_pcm_link_rwsem); | ||
| 1445 | snd_power_unlock(card); | ||
| 1446 | return -ENOMEM; | ||
| 1447 | } | ||
| 1448 | } else | ||
| 1449 | drec = &drec_tmp; | ||
| 1450 | |||
| 1451 | /* count only playback streams */ | ||
| 1452 | num_drecs = 0; | ||
| 1453 | snd_pcm_group_for_each_entry(s, substream) { | ||
| 1454 | runtime = s->runtime; | ||
| 1455 | if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
| 1456 | d = &drec[num_drecs++]; | ||
| 1457 | d->substream = s; | ||
| 1458 | init_waitqueue_entry(&d->wait, current); | ||
| 1459 | add_wait_queue(&runtime->sleep, &d->wait); | ||
| 1460 | } | ||
| 1461 | } | ||
| 1462 | up_read(&snd_pcm_link_rwsem); | ||
| 1463 | |||
| 1464 | lock: | ||
| 1465 | snd_pcm_stream_lock_irq(substream); | 1431 | snd_pcm_stream_lock_irq(substream); |
| 1466 | /* resume pause */ | 1432 | /* resume pause */ |
| 1467 | if (substream->runtime->status->state == SNDRV_PCM_STATE_PAUSED) | 1433 | if (runtime->status->state == SNDRV_PCM_STATE_PAUSED) |
| 1468 | snd_pcm_pause(substream, 0); | 1434 | snd_pcm_pause(substream, 0); |
| 1469 | 1435 | ||
| 1470 | /* pre-start/stop - all running streams are changed to DRAINING state */ | 1436 | /* pre-start/stop - all running streams are changed to DRAINING state */ |
| @@ -1479,25 +1445,35 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, | |||
| 1479 | 1445 | ||
| 1480 | for (;;) { | 1446 | for (;;) { |
| 1481 | long tout; | 1447 | long tout; |
| 1448 | struct snd_pcm_runtime *to_check; | ||
| 1482 | if (signal_pending(current)) { | 1449 | if (signal_pending(current)) { |
| 1483 | result = -ERESTARTSYS; | 1450 | result = -ERESTARTSYS; |
| 1484 | break; | 1451 | break; |
| 1485 | } | 1452 | } |
| 1486 | /* all finished? */ | 1453 | /* find a substream to drain */ |
| 1487 | for (i = 0; i < num_drecs; i++) { | 1454 | to_check = NULL; |
| 1488 | runtime = drec[i].substream->runtime; | 1455 | snd_pcm_group_for_each_entry(s, substream) { |
| 1489 | if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) | 1456 | if (s->stream != SNDRV_PCM_STREAM_PLAYBACK) |
| 1457 | continue; | ||
| 1458 | runtime = s->runtime; | ||
| 1459 | if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { | ||
| 1460 | to_check = runtime; | ||
| 1490 | break; | 1461 | break; |
| 1462 | } | ||
| 1491 | } | 1463 | } |
| 1492 | if (i == num_drecs) | 1464 | if (!to_check) |
| 1493 | break; /* yes, all drained */ | 1465 | break; /* all drained */ |
| 1494 | 1466 | init_waitqueue_entry(&wait, current); | |
| 1467 | add_wait_queue(&to_check->sleep, &wait); | ||
| 1495 | set_current_state(TASK_INTERRUPTIBLE); | 1468 | set_current_state(TASK_INTERRUPTIBLE); |
| 1496 | snd_pcm_stream_unlock_irq(substream); | 1469 | snd_pcm_stream_unlock_irq(substream); |
| 1470 | up_read(&snd_pcm_link_rwsem); | ||
| 1497 | snd_power_unlock(card); | 1471 | snd_power_unlock(card); |
| 1498 | tout = schedule_timeout(10 * HZ); | 1472 | tout = schedule_timeout(10 * HZ); |
| 1499 | snd_power_lock(card); | 1473 | snd_power_lock(card); |
| 1474 | down_read(&snd_pcm_link_rwsem); | ||
| 1500 | snd_pcm_stream_lock_irq(substream); | 1475 | snd_pcm_stream_lock_irq(substream); |
| 1476 | remove_wait_queue(&to_check->sleep, &wait); | ||
| 1501 | if (tout == 0) { | 1477 | if (tout == 0) { |
| 1502 | if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) | 1478 | if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) |
| 1503 | result = -ESTRPIPE; | 1479 | result = -ESTRPIPE; |
| @@ -1512,16 +1488,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, | |||
| 1512 | 1488 | ||
| 1513 | unlock: | 1489 | unlock: |
| 1514 | snd_pcm_stream_unlock_irq(substream); | 1490 | snd_pcm_stream_unlock_irq(substream); |
| 1515 | 1491 | up_read(&snd_pcm_link_rwsem); | |
| 1516 | if (!nonblock) { | ||
| 1517 | for (i = 0; i < num_drecs; i++) { | ||
| 1518 | d = &drec[i]; | ||
| 1519 | runtime = d->substream->runtime; | ||
| 1520 | remove_wait_queue(&runtime->sleep, &d->wait); | ||
| 1521 | } | ||
| 1522 | if (drec != &drec_tmp) | ||
| 1523 | kfree(drec); | ||
| 1524 | } | ||
| 1525 | snd_power_unlock(card); | 1492 | snd_power_unlock(card); |
| 1526 | 1493 | ||
| 1527 | return result; | 1494 | return result; |
diff --git a/sound/pci/lx6464es/lx6464es.h b/sound/pci/lx6464es/lx6464es.h index 012c010c8c89..51afc048961d 100644 --- a/sound/pci/lx6464es/lx6464es.h +++ b/sound/pci/lx6464es/lx6464es.h | |||
| @@ -86,7 +86,6 @@ struct lx6464es { | |||
| 86 | 86 | ||
| 87 | /* messaging */ | 87 | /* messaging */ |
| 88 | spinlock_t msg_lock; /* message spinlock */ | 88 | spinlock_t msg_lock; /* message spinlock */ |
| 89 | atomic_t send_message_locked; | ||
| 90 | struct lx_rmh rmh; | 89 | struct lx_rmh rmh; |
| 91 | 90 | ||
| 92 | /* configuration */ | 91 | /* configuration */ |
| @@ -95,7 +94,6 @@ struct lx6464es { | |||
| 95 | uint hardware_running[2]; | 94 | uint hardware_running[2]; |
| 96 | u32 board_sample_rate; /* sample rate read from | 95 | u32 board_sample_rate; /* sample rate read from |
| 97 | * board */ | 96 | * board */ |
| 98 | u32 sample_rate; /* our sample rate */ | ||
| 99 | u16 pcm_granularity; /* board blocksize */ | 97 | u16 pcm_granularity; /* board blocksize */ |
| 100 | 98 | ||
| 101 | /* dma */ | 99 | /* dma */ |
diff --git a/sound/pci/lx6464es/lx_core.c b/sound/pci/lx6464es/lx_core.c index 5812780d6e89..3086b751da4a 100644 --- a/sound/pci/lx6464es/lx_core.c +++ b/sound/pci/lx6464es/lx_core.c | |||
| @@ -314,98 +314,6 @@ static inline void lx_message_dump(struct lx_rmh *rmh) | |||
| 314 | #define XILINX_POLL_NO_SLEEP 100 | 314 | #define XILINX_POLL_NO_SLEEP 100 |
| 315 | #define XILINX_POLL_ITERATIONS 150 | 315 | #define XILINX_POLL_ITERATIONS 150 |
| 316 | 316 | ||
| 317 | #if 0 /* not used now */ | ||
| 318 | static int lx_message_send(struct lx6464es *chip, struct lx_rmh *rmh) | ||
| 319 | { | ||
| 320 | u32 reg = ED_DSP_TIMED_OUT; | ||
| 321 | int dwloop; | ||
| 322 | int answer_received; | ||
| 323 | |||
| 324 | if (lx_dsp_reg_read(chip, eReg_CSM) & (Reg_CSM_MC | Reg_CSM_MR)) { | ||
| 325 | snd_printk(KERN_ERR LXP "PIOSendMessage eReg_CSM %x\n", reg); | ||
| 326 | return -EBUSY; | ||
| 327 | } | ||
| 328 | |||
| 329 | /* write command */ | ||
| 330 | lx_dsp_reg_writebuf(chip, eReg_CRM1, rmh->cmd, rmh->cmd_len); | ||
| 331 | |||
| 332 | snd_BUG_ON(atomic_read(&chip->send_message_locked) != 0); | ||
| 333 | atomic_set(&chip->send_message_locked, 1); | ||
| 334 | |||
| 335 | /* MicoBlaze gogogo */ | ||
| 336 | lx_dsp_reg_write(chip, eReg_CSM, Reg_CSM_MC); | ||
| 337 | |||
| 338 | /* wait for interrupt to answer */ | ||
| 339 | for (dwloop = 0; dwloop != XILINX_TIMEOUT_MS; ++dwloop) { | ||
| 340 | answer_received = atomic_read(&chip->send_message_locked); | ||
| 341 | if (answer_received == 0) | ||
| 342 | break; | ||
| 343 | msleep(1); | ||
| 344 | } | ||
| 345 | |||
| 346 | if (answer_received == 0) { | ||
| 347 | /* in Debug mode verify Reg_CSM_MR */ | ||
| 348 | snd_BUG_ON(!(lx_dsp_reg_read(chip, eReg_CSM) & Reg_CSM_MR)); | ||
| 349 | |||
| 350 | /* command finished, read status */ | ||
| 351 | if (rmh->dsp_stat == 0) | ||
| 352 | reg = lx_dsp_reg_read(chip, eReg_CRM1); | ||
| 353 | else | ||
| 354 | reg = 0; | ||
| 355 | } else { | ||
| 356 | int i; | ||
| 357 | snd_printk(KERN_WARNING LXP "TIMEOUT lx_message_send! " | ||
| 358 | "Interrupts disabled?\n"); | ||
| 359 | |||
| 360 | /* attente bit Reg_CSM_MR */ | ||
| 361 | for (i = 0; i != XILINX_POLL_ITERATIONS; i++) { | ||
| 362 | if ((lx_dsp_reg_read(chip, eReg_CSM) & Reg_CSM_MR)) { | ||
| 363 | if (rmh->dsp_stat == 0) | ||
| 364 | reg = lx_dsp_reg_read(chip, eReg_CRM1); | ||
| 365 | else | ||
| 366 | reg = 0; | ||
| 367 | goto polling_successful; | ||
| 368 | } | ||
| 369 | |||
| 370 | if (i > XILINX_POLL_NO_SLEEP) | ||
| 371 | msleep(1); | ||
| 372 | } | ||
| 373 | snd_printk(KERN_WARNING LXP "TIMEOUT lx_message_send! " | ||
| 374 | "polling failed\n"); | ||
| 375 | |||
| 376 | polling_successful: | ||
| 377 | atomic_set(&chip->send_message_locked, 0); | ||
| 378 | } | ||
| 379 | |||
| 380 | if ((reg & ERROR_VALUE) == 0) { | ||
| 381 | /* read response */ | ||
| 382 | if (rmh->stat_len) { | ||
| 383 | snd_BUG_ON(rmh->stat_len >= (REG_CRM_NUMBER-1)); | ||
| 384 | |||
| 385 | lx_dsp_reg_readbuf(chip, eReg_CRM2, rmh->stat, | ||
| 386 | rmh->stat_len); | ||
| 387 | } | ||
| 388 | } else | ||
| 389 | snd_printk(KERN_WARNING LXP "lx_message_send: error_value %x\n", | ||
| 390 | reg); | ||
| 391 | |||
| 392 | /* clear Reg_CSM_MR */ | ||
| 393 | lx_dsp_reg_write(chip, eReg_CSM, 0); | ||
| 394 | |||
| 395 | switch (reg) { | ||
| 396 | case ED_DSP_TIMED_OUT: | ||
| 397 | snd_printk(KERN_WARNING LXP "lx_message_send: dsp timeout\n"); | ||
| 398 | return -ETIMEDOUT; | ||
| 399 | |||
| 400 | case ED_DSP_CRASHED: | ||
| 401 | snd_printk(KERN_WARNING LXP "lx_message_send: dsp crashed\n"); | ||
| 402 | return -EAGAIN; | ||
| 403 | } | ||
| 404 | |||
| 405 | lx_message_dump(rmh); | ||
| 406 | return 0; | ||
| 407 | } | ||
| 408 | #endif /* not used now */ | ||
| 409 | 317 | ||
| 410 | static int lx_message_send_atomic(struct lx6464es *chip, struct lx_rmh *rmh) | 318 | static int lx_message_send_atomic(struct lx6464es *chip, struct lx_rmh *rmh) |
| 411 | { | 319 | { |
| @@ -423,7 +331,7 @@ static int lx_message_send_atomic(struct lx6464es *chip, struct lx_rmh *rmh) | |||
| 423 | /* MicoBlaze gogogo */ | 331 | /* MicoBlaze gogogo */ |
| 424 | lx_dsp_reg_write(chip, eReg_CSM, Reg_CSM_MC); | 332 | lx_dsp_reg_write(chip, eReg_CSM, Reg_CSM_MC); |
| 425 | 333 | ||
| 426 | /* wait for interrupt to answer */ | 334 | /* wait for device to answer */ |
| 427 | for (dwloop = 0; dwloop != XILINX_TIMEOUT_MS * 1000; ++dwloop) { | 335 | for (dwloop = 0; dwloop != XILINX_TIMEOUT_MS * 1000; ++dwloop) { |
| 428 | if (lx_dsp_reg_read(chip, eReg_CSM) & Reg_CSM_MR) { | 336 | if (lx_dsp_reg_read(chip, eReg_CSM) & Reg_CSM_MR) { |
| 429 | if (rmh->dsp_stat == 0) | 337 | if (rmh->dsp_stat == 0) |
| @@ -1175,10 +1083,6 @@ static int lx_interrupt_ack(struct lx6464es *chip, u32 *r_irqsrc, | |||
| 1175 | *r_async_escmd = 1; | 1083 | *r_async_escmd = 1; |
| 1176 | } | 1084 | } |
| 1177 | 1085 | ||
| 1178 | if (irqsrc & MASK_SYS_STATUS_CMD_DONE) | ||
| 1179 | /* xilinx command notification */ | ||
| 1180 | atomic_set(&chip->send_message_locked, 0); | ||
| 1181 | |||
| 1182 | if (irq_async) { | 1086 | if (irq_async) { |
| 1183 | /* snd_printd("interrupt: async event pending\n"); */ | 1087 | /* snd_printd("interrupt: async event pending\n"); */ |
| 1184 | *r_async_pending = 1; | 1088 | *r_async_pending = 1; |
