00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifdef HAVE_CONFIG_H
00022 #include "config/config.h"
00023 #endif
00024 #include <linux/module.h>
00025 #include <linux/init.h>
00026
00027 #include <sound/driver.h>
00028 #include <sound/core.h>
00029 #include <sound/initval.h>
00030 #include <sound/pcm.h>
00031
00032 #include "most-constants.h"
00033 #include "most-base.h"
00034 #include "most-sync-common.h"
00035 #include "most-sync.h"
00036 #include "most-alsa.h"
00037
00038
00046
00047
00051 #define DRIVER_NAME "most-alsa"
00052
00056 #define PR DRIVER_NAME ": "
00057
00061 #define MOST_SYNC_DEV_TEMPLATE "/dev/mostsync%d"
00062
00063
00064
00065
00066
00070 static char *version = "$Rev: 641 $";
00071
00075 struct most_alsa_dev *most_alsa_devices[MOST_DEVICE_NUMBER];
00076
00077
00078
00079
00080
00084 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
00085
00089 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
00090
00094 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
00095
00103 static int playback_offset[SNDRV_CARDS] = { [0 ... SNDRV_CARDS-1] = 0 };
00104
00112 static int capture_offset[SNDRV_CARDS] = { [0 ... SNDRV_CARDS-1] = 0 };
00113
00114 #ifndef DOXYGEN
00115 module_param_array(index, int, NULL, 0444);
00116 MODULE_PARM_DESC(index, "Index value for MOST soundcard.");
00117
00118 module_param_array(id, charp, NULL, 0444);
00119 MODULE_PARM_DESC(id, "ID string for CS4281 soundcard.");
00120
00121 module_param_array(enable, bool, NULL, 0444);
00122 MODULE_PARM_DESC(enable, "Enable CS4281 soundcard.");
00123
00124 module_param_array(playback_offset, int, NULL, 0444);
00125 MODULE_PARM_DESC(playback_offset,
00126 "Offset for accessing the synchronous data in playback direction");
00127
00128 module_param_array(capture_offset, int, NULL, 0444);
00129 MODULE_PARM_DESC(capture_offset,
00130 "Offset for accessing the synchronous data in capture direction");
00131 #endif
00132
00133
00134
00135
00136
00137
00138
00139
00147 static int snd_most_playback_setup_sync_file(struct most_alsa_dev *alsa_dev,
00148 struct file **filp)
00149 {
00150 struct frame_part frame_part;
00151 struct file *most_sync_filp;
00152 char syncdev[32];
00153 int err;
00154
00155 snd_assert(filp != NULL);
00156
00157
00158 snprintf(syncdev, PATH_MAX, MOST_SYNC_DEV_TEMPLATE,
00159 MOST_DEV_CARDNUMBER(alsa_dev->most_dev));
00160 most_sync_filp = filp_open(syncdev, O_WRONLY, 0);
00161 if (!unlikely(most_sync_filp)) {
00162 rtnrt_warn(PR "Couldn't open %s in kernelspace\n", syncdev);
00163 return -EIO;
00164 }
00165
00166 frame_part.count = 4;
00167 frame_part.offset = playback_offset[alsa_dev->card->number];
00168
00169 err = most_sync_setup_tx(most_sync_filp, &frame_part);
00170 if (unlikely(err != 0)) {
00171 rtnrt_warn(PR "most_sync_setup_tx failed with %d\n", err);
00172 goto out;
00173 }
00174
00175 *filp = most_sync_filp;
00176
00177 return 0;
00178 out:
00179 filp_close(most_sync_filp, current->files);
00180 return err;
00181 }
00182
00190 static int snd_most_playback_thread(void *data)
00191 {
00192 struct rtnrt_memcopy_desc copy = { rtnrt_memmove, NULL };
00193 struct most_alsa_dev *alsa_dev = (struct most_alsa_dev *)data;
00194 struct snd_pcm_runtime *runtime = alsa_dev->p_substream->runtime;
00195 unsigned int period_bytes, initial_fill, i;
00196 unsigned char *zero_buffer = NULL;
00197 int err;
00198 struct file *most_sync_filp = NULL;
00199 void *dma_buf;
00200
00201 pr_alsa_debug(PR "snd_most_playback_thread started\n");
00202 daemonize("most_alsa_playback");
00203 allow_signal(SIGTERM);
00204 up(&alsa_dev->p_thread_sema);
00205
00206
00207 err = snd_most_playback_setup_sync_file(alsa_dev, &most_sync_filp);
00208 if (unlikely(err != 0)) {
00209 goto out;
00210 }
00211
00212
00213 err = down_interruptible(&alsa_dev->p_buf_setup_sema);
00214 if (unlikely(err < 0)) {
00215 pr_alsa_debug(PR "snd_most_playback_thread: wait_event_interruptible "
00216 "returned with %d", err);
00217 goto out_close;
00218 }
00219
00220
00221 period_bytes = frames_to_bytes(runtime, runtime->period_size);
00222 initial_fill = max(2U, runtime->periods/2);
00223
00224
00225 zero_buffer = kmalloc(period_bytes, GFP_KERNEL);
00226 if (unlikely(!zero_buffer)) {
00227 rtnrt_warn(PR "snd_most_playback_thread: alloc zero buffer failed\n");
00228 goto out_close;
00229 }
00230 memset(zero_buffer, 0, period_bytes);
00231
00232
00233 for (i = 0; i < initial_fill; i++) {
00234 err = most_sync_write(most_sync_filp, zero_buffer, period_bytes, ©);
00235 if (unlikely(err < 0)) {
00236 pr_alsa_debug(PR "snd_most_playback_thread, break write\n");
00237 break;
00238 }
00239 atomic_inc(&alsa_dev->p_cur_period);
00240 }
00241
00242
00243 err = down_interruptible(&alsa_dev->p_buffer_mutex);
00244 if (unlikely(err != 0)) {
00245 up(&alsa_dev->p_buffer_mutex);
00246 goto out_close;
00247 }
00248
00249 if (!runtime->dma_buffer_p) {
00250 up(&alsa_dev->p_buffer_mutex);
00251 goto out_close;
00252 }
00253 dma_buf = runtime->dma_buffer_p->area;
00254
00255 memset(dma_buf, 0, period_bytes * runtime->periods);
00256 up(&alsa_dev->p_buffer_mutex);
00257
00258 while (!signal_pending(current)) {
00259 unsigned long offset;
00260
00261 err = down_interruptible(&alsa_dev->p_event);
00262 if (unlikely(err != 0)) {
00263 break;
00264 }
00265
00266 err = down_interruptible(&alsa_dev->p_buffer_mutex);
00267 if (unlikely(err != 0)) {
00268 break;
00269 }
00270
00271 offset = (atomic_read(&alsa_dev->p_cur_period) % runtime->periods)
00272 * period_bytes;
00273
00274 if (!alsa_dev->p_silent) {
00275
00276 if (!runtime->dma_buffer_p) {
00277 up(&alsa_dev->p_buffer_mutex);
00278 break;
00279 }
00280 dma_buf = runtime->dma_buffer_p->area;
00281
00282
00283 if (snd_pcm_format_little_endian(runtime->format)) {
00284 swap_bytes(dma_buf + offset, period_bytes);
00285 }
00286 err = most_sync_write(most_sync_filp, dma_buf + offset,
00287 period_bytes, ©);
00288 if (unlikely(err < 0)) {
00289 up(&alsa_dev->p_buffer_mutex);
00290 break;
00291 }
00292
00293 atomic_inc(&alsa_dev->p_cur_period);
00294 snd_pcm_period_elapsed(alsa_dev->p_substream);
00295 } else {
00296 most_sync_write(most_sync_filp, zero_buffer, period_bytes, ©);
00297 }
00298
00299 up(&alsa_dev->p_buffer_mutex);
00300 }
00301
00302 out_close:
00303 filp_close(most_sync_filp, current->files);
00304 out:
00305 kfree(zero_buffer);
00306 alsa_dev->p_thread_id = 0;
00307 pr_alsa_debug(PR "snd_most_playback_thread finished\n");
00308 complete_and_exit(&alsa_dev->p_completion, 0);
00309 }
00310
00314 static struct snd_pcm_hardware snd_most_playback_hw = {
00315 .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP),
00316 .formats = SNDRV_PCM_FMTBIT_S16_LE,
00317 .rates = SNDRV_PCM_RATE_44100,
00318 .rate_min = 44100,
00319 .rate_max = 44100,
00320 .channels_min = 2,
00321 .channels_max = 2,
00322 .periods_min = 2,
00323 .periods_max = 8
00324 };
00325
00334 static int snd_most_playback_open(struct snd_pcm_substream *substream)
00335 {
00336 struct most_alsa_dev *alsa_dev = snd_pcm_substream_chip(substream);
00337 struct snd_pcm_runtime *runtime = substream->runtime;
00338 int err;
00339
00340 pr_alsa_debug(PR "snd_most_playback_open\n");
00341
00342
00343 snd_most_playback_hw.buffer_bytes_max = (hw_tx_buffer_size * 4 * 8);
00344 snd_most_playback_hw.period_bytes_min = (hw_tx_buffer_size * 4);
00345 snd_most_playback_hw.period_bytes_max = (hw_tx_buffer_size * 4);
00346 snd_most_playback_hw.periods_max = min(snd_most_playback_hw.periods_max,
00347 (unsigned int)(sw_tx_buffer_size / hw_tx_buffer_size));
00348
00349
00350 runtime->hw = snd_most_playback_hw;
00351
00352
00353 alsa_dev->p_substream = substream;
00354 alsa_dev->p_thread_id = 0;
00355 atomic_set(&alsa_dev->p_cur_period, 0);
00356 init_MUTEX_LOCKED(&alsa_dev->p_event);
00357 init_MUTEX_LOCKED(&alsa_dev->p_thread_sema);
00358 init_MUTEX(&alsa_dev->p_buffer_mutex);
00359 init_MUTEX_LOCKED(&alsa_dev->p_buf_setup_sema);
00360 init_completion(&alsa_dev->p_completion);
00361 alsa_dev->p_silent = true;
00362
00363
00364 alsa_dev->p_thread_id = kernel_thread(snd_most_playback_thread,
00365 alsa_dev, CLONE_KERNEL);
00366 if (unlikely(alsa_dev->p_thread_id == 0)) {
00367 rtnrt_warn(PR "playback kernel_thread creation failed\n");
00368 err = -EIO;
00369 goto out;
00370 }
00371
00372
00373 err = down_interruptible(&alsa_dev->p_thread_sema);
00374 if (unlikely(err != 0)) {
00375 pr_alsa_debug(PR "snd_most_playback_open interrupted %d\n", err);
00376 goto out_proc;
00377 }
00378
00379 return 0;
00380 out_proc:
00381 kill_proc(alsa_dev->p_thread_id, SIGTERM, 1);
00382 wait_for_completion(&alsa_dev->p_completion);
00383 out:
00384 return err;
00385 }
00386
00393 static int snd_most_playback_close(struct snd_pcm_substream *substream)
00394 {
00395 struct most_alsa_dev *alsa_dev = snd_pcm_substream_chip(substream);
00396
00397 pr_alsa_debug(PR "snd_most_playback_close\n");
00398
00399
00400 if (likely(alsa_dev->p_thread_id != 0)) {
00401 kill_proc(alsa_dev->p_thread_id, SIGTERM, 1);
00402 wait_for_completion(&alsa_dev->p_completion);
00403 }
00404 alsa_dev->p_substream = NULL;
00405
00406 return 0;
00407 }
00408
00417 static int snd_most_playback_hw_params(struct snd_pcm_substream *substream,
00418 struct snd_pcm_hw_params *hw_params)
00419 {
00420 struct most_alsa_dev *alsa_dev = snd_pcm_substream_chip(substream);
00421 int ret;
00422
00423 BUG_ON(alsa_dev->most_dev == NULL);
00424 pr_alsa_debug(PR "snd_most_pcm_hw_params\n");
00425
00426 ret = down_interruptible(&alsa_dev->p_buffer_mutex);
00427 if (unlikely(ret != 0)) {
00428 rtnrt_warn(PR "snd_most_pcm_hw_params: down_interruptible failed\n");
00429 return ret;
00430 }
00431
00432 ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
00433 up(&alsa_dev->p_buffer_mutex);
00434
00435 if (unlikely(ret < 0)) {
00436 rtnrt_warn(PR "snd_most_pcm_hw_params: snd_pcm_lib_malloc_pages "
00437 "failed with %d\n", ret);
00438 return ret;
00439 }
00440
00441 alsa_dev->p_silent = false;
00442 up(&alsa_dev->p_buf_setup_sema);
00443
00444 return 0;
00445 }
00446
00453 static int snd_most_playback_hw_free(struct snd_pcm_substream *substream)
00454 {
00455 struct most_alsa_dev *alsa_dev = snd_pcm_substream_chip(substream);
00456
00457 pr_alsa_debug(PR "snd_most_playback_hw_free\n");
00458
00459 alsa_dev->p_silent = true;
00460
00461 return snd_pcm_lib_free_pages(substream);
00462 }
00463
00470 static int snd_most_playback_prepare(struct snd_pcm_substream *substream)
00471 {
00472 struct most_alsa_dev *alsa_dev = snd_pcm_substream_chip(substream);
00473
00474 atomic_set(&alsa_dev->p_cur_period, 0);
00475
00476 pr_alsa_debug(PR "snd_most_pcm_prepare\n");
00477
00478 #if 0
00479 pr_info("rate = %d, channels = %d\n",
00480 substream->runtime->rate, substream->runtime->channels);
00481 pr_info("period_size = %lu, periods = %d\n",
00482 substream->runtime->period_size, substream->runtime->periods);
00483 pr_info("buffer_size = %lu, tick_time = %d\n",
00484 substream->runtime->buffer_size, substream->runtime->tick_time);
00485 pr_info("frame_bits = %d, sample_bits = %d\n",
00486 substream->runtime->frame_bits, substream->runtime->sample_bits);
00487 #endif
00488
00489 return 0;
00490 }
00491
00501 static int snd_most_playback_trigger(struct snd_pcm_substream *substream, int cmd)
00502 {
00503 struct most_alsa_dev *alsa_dev = snd_pcm_substream_chip(substream);
00504
00505 switch (cmd) {
00506 case SNDRV_PCM_TRIGGER_START:
00507 pr_alsa_debug(PR "SNDRV_PCM_TRIGGER_START\n");
00508 alsa_dev->p_silent = false;
00509 break;
00510
00511 case SNDRV_PCM_TRIGGER_STOP:
00512 pr_alsa_debug(PR "SNDRV_PCM_TRIGGER_STOP\n");
00513 alsa_dev->p_silent = true;
00514 }
00515
00516 return 0;
00517 }
00518
00526 static snd_pcm_uframes_t snd_most_playback_pointer(struct snd_pcm_substream *substream)
00527 {
00528 struct most_alsa_dev *alsa_dev = snd_pcm_substream_chip(substream);
00529 struct snd_pcm_runtime *runtime = substream->runtime;
00530
00531 return runtime->period_size *
00532 (atomic_read(&alsa_dev->p_cur_period) % runtime->periods);
00533 }
00534
00535
00536
00537
00538
00539
00547 static int snd_most_capture_setup_sync_file(struct most_alsa_dev *alsa_dev,
00548 struct file **filp)
00549 {
00550 struct frame_part frame_part;
00551 struct file *most_sync_filp;
00552 char syncdev[32];
00553 int err;
00554
00555 snd_assert(filp != NULL);
00556
00557
00558 snprintf(syncdev, PATH_MAX, MOST_SYNC_DEV_TEMPLATE,
00559 MOST_DEV_CARDNUMBER(alsa_dev->most_dev));
00560 most_sync_filp = filp_open(syncdev, O_RDONLY, 0);
00561 if (!unlikely(most_sync_filp)) {
00562 rtnrt_warn(PR "Couldn't open %s in kernelspace\n", syncdev);
00563 return -EIO;
00564 }
00565
00566 frame_part.count = 4;
00567 frame_part.offset = capture_offset[alsa_dev->card->number];
00568
00569 err = most_sync_setup_rx(most_sync_filp, &frame_part);
00570 if (unlikely(err != 0)) {
00571 rtnrt_warn(PR "most_sync_setup_rx failed with %d\n", err);
00572 goto out;
00573 }
00574
00575 *filp = most_sync_filp;
00576
00577 return 0;
00578 out:
00579 filp_close(most_sync_filp, current->files);
00580 return err;
00581 }
00582
00590 static int snd_most_capture_thread(void *data)
00591 {
00592 struct rtnrt_memcopy_desc copy = { rtnrt_memmove, NULL };
00593 struct most_alsa_dev *alsa_dev = (struct most_alsa_dev *)data;
00594 struct snd_pcm_runtime *runtime = alsa_dev->c_substream->runtime;
00595 unsigned int period_bytes;
00596 int err;
00597 struct file *most_sync_filp = NULL;
00598 void *dma_buf;
00599
00600 pr_alsa_debug(PR "snd_most_capture_thread started\n");
00601 daemonize("most_alsa_capture");
00602 allow_signal(SIGTERM);
00603 up(&alsa_dev->c_thread_sema);
00604
00605
00606 err = snd_most_capture_setup_sync_file(alsa_dev, &most_sync_filp);
00607 if (unlikely(err != 0)) {
00608 goto out;
00609 }
00610
00611
00612 err = down_interruptible(&alsa_dev->c_buf_setup_sema);
00613 if (unlikely(err < 0)) {
00614 pr_alsa_debug(PR "snd_most_capture_thread: wait_event_interruptible "
00615 "returned with %d\n", err);
00616 goto out_close;
00617 }
00618
00619
00620 period_bytes = frames_to_bytes(runtime, runtime->period_size);
00621
00622
00623 err = down_interruptible(&alsa_dev->c_buffer_mutex);
00624 if (unlikely(err != 0)) {
00625 up(&alsa_dev->c_buffer_mutex);
00626 goto out_close;
00627 }
00628
00629 if (!runtime->dma_buffer_p) {
00630 up(&alsa_dev->c_buffer_mutex);
00631 goto out_close;
00632 }
00633 dma_buf = runtime->dma_buffer_p->area;
00634
00635 memset(dma_buf, 0, period_bytes * runtime->periods);
00636 up(&alsa_dev->c_buffer_mutex);
00637
00638 while (!signal_pending(current)) {
00639 unsigned long offset;
00640
00641 err = down_interruptible(&alsa_dev->c_buffer_mutex);
00642 if (unlikely(err != 0)) {
00643 break;
00644 }
00645
00646 if (!runtime->dma_buffer_p) {
00647 up(&alsa_dev->c_buffer_mutex);
00648 break;
00649 }
00650 dma_buf = runtime->dma_buffer_p->area;
00651 offset = (atomic_read(&alsa_dev->c_cur_period) % runtime->periods)
00652 * period_bytes;
00653
00654 if (!alsa_dev->c_silent) {
00655 err = most_sync_read(most_sync_filp, dma_buf + offset, period_bytes, ©);
00656 if (unlikely(err < 0)) {
00657 up(&alsa_dev->c_buffer_mutex);
00658 break;
00659 }
00660 snd_assert(err == period_bytes);
00661
00662
00663 if (snd_pcm_format_little_endian(runtime->format)) {
00664 swap_bytes(dma_buf + offset, period_bytes);
00665 }
00666 atomic_inc(&alsa_dev->c_cur_period);
00667 snd_pcm_period_elapsed(alsa_dev->c_substream);
00668 } else {
00669 memset(dma_buf, 0, period_bytes * runtime->periods);
00670 }
00671
00672 up(&alsa_dev->c_buffer_mutex);
00673 }
00674
00675 out_close:
00676 filp_close(most_sync_filp, current->files);
00677 out:
00678 alsa_dev->c_thread_id = 0;
00679 pr_alsa_debug(PR "snd_most_capture_thread finished\n");
00680 complete_and_exit(&alsa_dev->c_completion, 0);
00681 }
00682
00686 static struct snd_pcm_hardware snd_most_capture_hw = {
00687 .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP),
00688 .formats = SNDRV_PCM_FMTBIT_S16_LE,
00689 .rates = SNDRV_PCM_RATE_44100,
00690 .rate_min = 44100,
00691 .rate_max = 44100,
00692 .channels_min = 2,
00693 .channels_max = 2,
00694 .periods_min = 2,
00695 .periods_max = 8
00696 };
00697
00706 static int snd_most_capture_open(struct snd_pcm_substream *substream)
00707 {
00708 struct most_alsa_dev *alsa_dev = snd_pcm_substream_chip(substream);
00709 struct snd_pcm_runtime *runtime = substream->runtime;
00710 int err;
00711
00712 pr_alsa_debug(PR "snd_most_capture_open\n");
00713
00714
00715 snd_most_capture_hw.buffer_bytes_max = (hw_tx_buffer_size * 4 * 8);
00716 snd_most_capture_hw.period_bytes_min = (hw_tx_buffer_size * 4);
00717 snd_most_capture_hw.period_bytes_max = (hw_tx_buffer_size * 4);
00718 snd_most_capture_hw.periods_max = min(snd_most_capture_hw.periods_max,
00719 (unsigned int)(sw_tx_buffer_size / hw_tx_buffer_size));
00720
00721
00722 runtime->hw = snd_most_capture_hw;
00723
00724
00725 alsa_dev->c_substream = substream;
00726 alsa_dev->c_thread_id = 0;
00727 atomic_set(&alsa_dev->c_cur_period, 0);
00728 init_MUTEX(&alsa_dev->c_buffer_mutex);
00729 init_MUTEX_LOCKED(&alsa_dev->c_thread_sema);
00730 init_MUTEX_LOCKED(&alsa_dev->c_buf_setup_sema);
00731 init_completion(&alsa_dev->c_completion);
00732 alsa_dev->c_silent = true;
00733
00734
00735 alsa_dev->c_thread_id = kernel_thread(snd_most_capture_thread,
00736 alsa_dev, CLONE_KERNEL);
00737 if (unlikely(alsa_dev->c_thread_id == 0)) {
00738 rtnrt_warn(PR "capture kernel_thread creation failed\n");
00739 err = -EIO;
00740 goto out;
00741 }
00742
00743
00744 err = down_interruptible(&alsa_dev->c_thread_sema);
00745 if (unlikely(err != 0)) {
00746 pr_alsa_debug(PR "snd_most_capture_open interrupted %d\n", err);
00747 goto out_proc;
00748 }
00749
00750 return 0;
00751 out_proc:
00752 kill_proc(alsa_dev->c_thread_id, SIGTERM, 1);
00753 wait_for_completion(&alsa_dev->c_completion);
00754 out:
00755 return err;
00756 }
00757
00764 static int snd_most_capture_close(struct snd_pcm_substream *substream)
00765 {
00766 struct most_alsa_dev *alsa_dev = snd_pcm_substream_chip(substream);
00767
00768 pr_alsa_debug(PR "snd_most_capture_close\n");
00769
00770
00771 if (likely(alsa_dev->c_thread_id != 0)) {
00772 kill_proc(alsa_dev->c_thread_id, SIGTERM, 1);
00773 wait_for_completion(&alsa_dev->c_completion);
00774 }
00775 alsa_dev->c_substream = NULL;
00776
00777 return 0;
00778 }
00779
00788 static int snd_most_capture_hw_params(struct snd_pcm_substream *substream,
00789 struct snd_pcm_hw_params *hw_params)
00790 {
00791 struct most_alsa_dev *alsa_dev = snd_pcm_substream_chip(substream);
00792 int ret;
00793
00794 BUG_ON(alsa_dev->most_dev == NULL);
00795 pr_alsa_debug(PR "snd_most_pcm_hw_params\n");
00796
00797 ret = down_interruptible(&alsa_dev->c_buffer_mutex);
00798 if (unlikely(ret != 0)) {
00799 rtnrt_warn(PR "snd_most_pcm_hw_params: down_interruptible failed\n");
00800 return ret;
00801 }
00802
00803 ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
00804 up(&alsa_dev->c_buffer_mutex);
00805
00806 if (unlikely(ret < 0)) {
00807 rtnrt_warn(PR "snd_most_pcm_hw_params: snd_pcm_lib_malloc_pages "
00808 "failed with %d\n", ret);
00809 return ret;
00810 }
00811
00812 alsa_dev->c_silent = false;
00813 up(&alsa_dev->c_buf_setup_sema);
00814
00815 return 0;
00816 }
00817
00824 static int snd_most_capture_hw_free(struct snd_pcm_substream *substream)
00825 {
00826 struct most_alsa_dev *alsa_dev = snd_pcm_substream_chip(substream);
00827
00828 pr_alsa_debug(PR "snd_most_capture_hw_free\n");
00829
00830 alsa_dev->c_silent = true;
00831
00832 return snd_pcm_lib_free_pages(substream);
00833 }
00834
00841 static int snd_most_capture_prepare(struct snd_pcm_substream *substream)
00842 {
00843 struct most_alsa_dev *alsa_dev = snd_pcm_substream_chip(substream);
00844
00845 atomic_set(&alsa_dev->c_cur_period, 0);
00846
00847 pr_alsa_debug(PR "snd_most_pcm_prepare\n");
00848
00849 #if 0
00850 pr_alsa_debug(PR "rate = %d, channels = %d\n",
00851 substream->runtime->rate, substream->runtime->channels);
00852 pr_alsa_debug(PR p"eriod_size = %lu, periods = %d\n",
00853 substream->runtime->period_size, substream->runtime->periods);
00854 pr_alsa_debug(PR "buffer_size = %lu, tick_time = %d\n",
00855 substream->runtime->buffer_size, substream->runtime->tick_time);
00856 pr_alsa_debug(PR "frame_bits = %d, sample_bits = %d\n",
00857 substream->runtime->frame_bits, substream->runtime->sample_bits);
00858 #endif
00859
00860 return 0;
00861 }
00862
00872 static int snd_most_capture_trigger(struct snd_pcm_substream *substream, int cmd)
00873 {
00874 struct most_alsa_dev *alsa_dev = snd_pcm_substream_chip(substream);
00875
00876 switch (cmd) {
00877 case SNDRV_PCM_TRIGGER_START:
00878 pr_alsa_debug(PR "SNDRV_PCM_TRIGGER_START\n");
00879 alsa_dev->c_silent = false;
00880 break;
00881
00882 case SNDRV_PCM_TRIGGER_STOP:
00883 pr_alsa_debug(PR "SNDRV_PCM_TRIGGER_STOP\n");
00884 alsa_dev->c_silent = true;
00885 }
00886
00887 return 0;
00888 }
00889
00897 static snd_pcm_uframes_t snd_most_capture_pointer(
00898 struct snd_pcm_substream *substream)
00899 {
00900 struct most_alsa_dev *alsa_dev = snd_pcm_substream_chip(substream);
00901 struct snd_pcm_runtime *runtime = substream->runtime;
00902
00903 return runtime->period_size *
00904 (atomic_read(&alsa_dev->c_cur_period) % runtime->periods);
00905 }
00906
00907
00908
00909
00910
00914 static struct snd_pcm_ops snd_most_playback_ops = {
00915 .open = snd_most_playback_open,
00916 .close = snd_most_playback_close,
00917 .ioctl = snd_pcm_lib_ioctl,
00918 .hw_params = snd_most_playback_hw_params,
00919 .hw_free = snd_most_playback_hw_free,
00920 .prepare = snd_most_playback_prepare,
00921 .trigger = snd_most_playback_trigger,
00922 .pointer = snd_most_playback_pointer,
00923 };
00924
00928 static struct snd_pcm_ops snd_most_capture_ops = {
00929 .open = snd_most_capture_open,
00930 .close = snd_most_capture_close,
00931 .ioctl = snd_pcm_lib_ioctl,
00932 .hw_params = snd_most_capture_hw_params,
00933 .hw_free = snd_most_capture_hw_free,
00934 .prepare = snd_most_capture_prepare,
00935 .trigger = snd_most_capture_trigger,
00936 .pointer = snd_most_capture_pointer,
00937 };
00938
00939
00946 static int __devinit snd_most_new_pcm(struct most_alsa_dev *alsa_dev)
00947 {
00948 struct snd_pcm *pcm;
00949 int err;
00950
00951 err = snd_pcm_new(alsa_dev->card, "MOST PCM", 0, 1, 1, &pcm);
00952 if (unlikely(err != 0)) {
00953 return err;
00954 }
00955
00956 pcm->private_data = alsa_dev;
00957 strcpy(pcm->name, "MOST PCM");
00958 alsa_dev->pcm = pcm;
00959
00960
00961 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_most_playback_ops);
00962 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_most_capture_ops);
00963
00964
00965 err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
00966 snd_dma_continuous_data(GFP_KERNEL),
00967 max(hw_tx_buffer_size, hw_rx_buffer_size) * 8 * 4,
00968 max(hw_tx_buffer_size, hw_rx_buffer_size) * 8 * 4);
00969 if (unlikely(err != 0)) {
00970 rtnrt_warn(PR "snd_pcm_lib_preallocate_pages_for_all failed "
00971 "with %d\n", err);
00972 goto err_pcm;
00973 }
00974
00975 return 0;
00976
00977 err_pcm:
00978 return err;
00979 }
00980
00981
00982
00983
00984
00985
00986
00992 static void snd_most_free(struct snd_card *card)
00993 {
00994
00995
00996 }
00997
01004 static int __devinit snd_most_create(struct snd_card *card,
01005 struct most_dev *most_dev)
01006 {
01007 struct most_alsa_dev *alsa_dev = ALSA_DEV(card);
01008
01009 card->private_free = snd_most_free;
01010
01011
01012 memset(alsa_dev, 0, sizeof(struct most_alsa_dev));
01013 alsa_dev->most_dev = most_dev;
01014 alsa_dev->card = card;
01015
01016 return 0;
01017 }
01018
01025 static int most_alsa_remove(struct most_dev *most_dev)
01026 {
01027 int number = MOST_DEV_CARDNUMBER(most_dev);
01028 struct most_alsa_dev *alsa_dev = most_alsa_devices[number];
01029
01030 pr_alsa_debug(PR "alsa_remove called, number = %d\n", number);
01031
01032 most_alsa_devices[number] = NULL;
01033 snd_card_free(alsa_dev->card);
01034
01035 return 0;
01036 }
01037
01044 static int most_alsa_probe(struct most_dev *most_dev)
01045 {
01046 struct snd_card *card;
01047 int err;
01048 int number = MOST_DEV_CARDNUMBER(most_dev);
01049
01050 pr_alsa_debug(PR "alsa_probe called, number = %d\n", number);
01051
01052 if (most_dev->card_number >= SNDRV_CARDS) {
01053 return -ENODEV;
01054 }
01055 if (!enable[most_dev->card_number]) {
01056 return -ENOENT;
01057 }
01058
01059 card = snd_card_new(index[number], id[number],
01060 THIS_MODULE, sizeof(struct most_alsa_dev));
01061 if (unlikely(!card)) {
01062 return -ENOMEM;
01063 }
01064
01065 err = snd_most_create(card, most_dev);
01066 if (unlikely(err < 0)) {
01067 goto out_snd_most;
01068 }
01069
01070 strcpy(card->driver, "MOST");
01071 strcpy(card->shortname, "OASIS MOST PCI device");
01072 sprintf(card->longname, "%s number %d", card->shortname, most_dev->card_number);
01073
01074 err = snd_most_new_pcm(ALSA_DEV(card));
01075 if (unlikely(err < 0)) {
01076 goto out_snd_most;
01077 }
01078
01079 err = snd_card_register(card);
01080 if (unlikely(err < 0)) {
01081 goto out_snd_most;
01082 }
01083
01084 most_alsa_devices[number] = ALSA_DEV(card);
01085
01086 return 0;
01087
01088 out_snd_most:
01089 snd_card_free(card);
01090 return err;
01091 }
01092
01102 static void most_alsa_int_handler(struct most_dev *dev,
01103 unsigned int intstatus)
01104 {
01105 int number = MOST_DEV_CARDNUMBER(dev);
01106 struct most_alsa_dev *alsa_dev = most_alsa_devices[number];
01107
01108 BUG_ON(dev == NULL);
01109 if (alsa_dev) {
01110 if ((intstatus & IESTX) && alsa_dev->p_thread_id != 0) {
01111 up(&alsa_dev->p_event);
01112 }
01113 }
01114 }
01115
01120 static struct most_high_driver most_alsa_high_driver = {
01121 .name = "most-alsa",
01122 .sema_list = LIST_HEAD_INIT(most_alsa_high_driver.sema_list),
01123 .spin_list = LIST_HEAD_INIT(most_alsa_high_driver.spin_list),
01124 .probe = most_alsa_probe,
01125 .remove = most_alsa_remove,
01126 .int_handler = most_alsa_int_handler,
01127 .interrupt_mask = (IESTX | IESRX)
01128 };
01129
01130
01131
01132
01133
01139 static int __init most_alsa_init(void)
01140 {
01141 int err;
01142
01143 rtnrt_info(PR "Loading module %s, version %s\n", DRIVER_NAME, version);
01144
01145
01146 err = most_register_high_driver(&most_alsa_high_driver);
01147 if (unlikely(err != 0)) {
01148 return err;
01149 }
01150
01151 return 0;
01152 }
01153
01157 static void __exit most_alsa_exit(void)
01158 {
01159 most_deregister_high_driver(&most_alsa_high_driver);
01160
01161 rtnrt_info(PR "Unloading module %s, version %s\n", DRIVER_NAME, version);
01162 }
01163
01164
01165
01166
01167 #ifndef DOXYGEN
01168 MODULE_LICENSE("GPL");
01169 MODULE_AUTHOR("Bernhard Walle");
01170 MODULE_VERSION("$Rev: 641 $");
01171 MODULE_DESCRIPTION("ALSA Driver for MOST Synchronous data.");
01172 module_init(most_alsa_init);
01173 module_exit(most_alsa_exit);
01174 #endif
01175
01176