• Home
  • Raw
  • Download

Lines Matching refs:pcm

244 struct pcm {  struct
262 unsigned int pcm_get_buffer_size(struct pcm *pcm) in pcm_get_buffer_size() argument
264 return pcm->buffer_size; in pcm_get_buffer_size()
267 const char* pcm_get_error(struct pcm *pcm) in pcm_get_error() argument
269 return pcm->error; in pcm_get_error()
272 static int oops(struct pcm *pcm, int e, const char *fmt, ...) in oops() argument
278 vsnprintf(pcm->error, PCM_ERROR_MAX, fmt, ap); in oops()
280 sz = strlen(pcm->error); in oops()
283 snprintf(pcm->error + sz, PCM_ERROR_MAX - sz, in oops()
319 unsigned int pcm_bytes_to_frames(struct pcm *pcm, unsigned int bytes) in pcm_bytes_to_frames() argument
321 return bytes / (pcm->config.channels * in pcm_bytes_to_frames()
322 (pcm_format_to_bits(pcm->config.format) >> 3)); in pcm_bytes_to_frames()
325 unsigned int pcm_frames_to_bytes(struct pcm *pcm, unsigned int frames) in pcm_frames_to_bytes() argument
327 return frames * pcm->config.channels * in pcm_frames_to_bytes()
328 (pcm_format_to_bits(pcm->config.format) >> 3); in pcm_frames_to_bytes()
331 static int pcm_sync_ptr(struct pcm *pcm, int flags) { in pcm_sync_ptr() argument
332 if (pcm->sync_ptr) { in pcm_sync_ptr()
333 pcm->sync_ptr->flags = flags; in pcm_sync_ptr()
334 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_SYNC_PTR, pcm->sync_ptr) < 0) in pcm_sync_ptr()
340 static int pcm_hw_mmap_status(struct pcm *pcm) { in pcm_hw_mmap_status() argument
342 if (pcm->sync_ptr) in pcm_hw_mmap_status()
346 pcm->mmap_status = mmap(NULL, page_size, PROT_READ, MAP_FILE | MAP_SHARED, in pcm_hw_mmap_status()
347 pcm->fd, SNDRV_PCM_MMAP_OFFSET_STATUS); in pcm_hw_mmap_status()
348 if (pcm->mmap_status == MAP_FAILED) in pcm_hw_mmap_status()
349 pcm->mmap_status = NULL; in pcm_hw_mmap_status()
350 if (!pcm->mmap_status) in pcm_hw_mmap_status()
353 pcm->mmap_control = mmap(NULL, page_size, PROT_READ | PROT_WRITE, in pcm_hw_mmap_status()
354 MAP_FILE | MAP_SHARED, pcm->fd, SNDRV_PCM_MMAP_OFFSET_CONTROL); in pcm_hw_mmap_status()
355 if (pcm->mmap_control == MAP_FAILED) in pcm_hw_mmap_status()
356 pcm->mmap_control = NULL; in pcm_hw_mmap_status()
357 if (!pcm->mmap_control) { in pcm_hw_mmap_status()
358 munmap(pcm->mmap_status, page_size); in pcm_hw_mmap_status()
359 pcm->mmap_status = NULL; in pcm_hw_mmap_status()
362 if (pcm->flags & PCM_MMAP) in pcm_hw_mmap_status()
363 pcm->mmap_control->avail_min = pcm->config.avail_min; in pcm_hw_mmap_status()
365 pcm->mmap_control->avail_min = 1; in pcm_hw_mmap_status()
371 pcm->sync_ptr = calloc(1, sizeof(*pcm->sync_ptr)); in pcm_hw_mmap_status()
372 if (!pcm->sync_ptr) in pcm_hw_mmap_status()
374 pcm->mmap_status = &pcm->sync_ptr->s.status; in pcm_hw_mmap_status()
375 pcm->mmap_control = &pcm->sync_ptr->c.control; in pcm_hw_mmap_status()
376 if (pcm->flags & PCM_MMAP) in pcm_hw_mmap_status()
377 pcm->mmap_control->avail_min = pcm->config.avail_min; in pcm_hw_mmap_status()
379 pcm->mmap_control->avail_min = 1; in pcm_hw_mmap_status()
381 pcm_sync_ptr(pcm, 0); in pcm_hw_mmap_status()
386 static void pcm_hw_munmap_status(struct pcm *pcm) { in pcm_hw_munmap_status() argument
387 if (pcm->sync_ptr) { in pcm_hw_munmap_status()
388 free(pcm->sync_ptr); in pcm_hw_munmap_status()
389 pcm->sync_ptr = NULL; in pcm_hw_munmap_status()
392 if (pcm->mmap_status) in pcm_hw_munmap_status()
393 munmap(pcm->mmap_status, page_size); in pcm_hw_munmap_status()
394 if (pcm->mmap_control) in pcm_hw_munmap_status()
395 munmap(pcm->mmap_control, page_size); in pcm_hw_munmap_status()
397 pcm->mmap_status = NULL; in pcm_hw_munmap_status()
398 pcm->mmap_control = NULL; in pcm_hw_munmap_status()
401 static int pcm_areas_copy(struct pcm *pcm, unsigned int pcm_offset, in pcm_areas_copy() argument
405 int size_bytes = pcm_frames_to_bytes(pcm, frames); in pcm_areas_copy()
406 int pcm_offset_bytes = pcm_frames_to_bytes(pcm, pcm_offset); in pcm_areas_copy()
407 int src_offset_bytes = pcm_frames_to_bytes(pcm, src_offset); in pcm_areas_copy()
410 if (pcm->flags & PCM_IN) in pcm_areas_copy()
412 (char*)pcm->mmap_buffer + pcm_offset_bytes, in pcm_areas_copy()
415 memcpy((char*)pcm->mmap_buffer + pcm_offset_bytes, in pcm_areas_copy()
421 static int pcm_mmap_transfer_areas(struct pcm *pcm, char *buf, in pcm_mmap_transfer_areas() argument
430 pcm_mmap_begin(pcm, &pcm_areas, &pcm_offset, &frames); in pcm_mmap_transfer_areas()
431 pcm_areas_copy(pcm, pcm_offset, buf, offset, frames); in pcm_mmap_transfer_areas()
432 commit = pcm_mmap_commit(pcm, pcm_offset, frames); in pcm_mmap_transfer_areas()
434 oops(pcm, commit, "failed to commit %d frames\n", frames); in pcm_mmap_transfer_areas()
445 int pcm_get_htimestamp(struct pcm *pcm, unsigned int *avail, in pcm_get_htimestamp() argument
452 if (!pcm_is_ready(pcm)) in pcm_get_htimestamp()
455 rc = pcm_sync_ptr(pcm, SNDRV_PCM_SYNC_PTR_APPL|SNDRV_PCM_SYNC_PTR_HWSYNC); in pcm_get_htimestamp()
459 if ((pcm->mmap_status->state != PCM_STATE_RUNNING) && in pcm_get_htimestamp()
460 (pcm->mmap_status->state != PCM_STATE_DRAINING)) in pcm_get_htimestamp()
463 *tstamp = pcm->mmap_status->tstamp; in pcm_get_htimestamp()
467 hw_ptr = pcm->mmap_status->hw_ptr; in pcm_get_htimestamp()
468 if (pcm->flags & PCM_IN) in pcm_get_htimestamp()
469 frames = hw_ptr - pcm->mmap_control->appl_ptr; in pcm_get_htimestamp()
471 frames = hw_ptr + pcm->buffer_size - pcm->mmap_control->appl_ptr; in pcm_get_htimestamp()
474 frames += pcm->boundary; in pcm_get_htimestamp()
475 else if (frames > (int)pcm->boundary) in pcm_get_htimestamp()
476 frames -= pcm->boundary; in pcm_get_htimestamp()
483 int pcm_write(struct pcm *pcm, const void *data, unsigned int count) in pcm_write() argument
487 if (pcm->flags & PCM_IN) in pcm_write()
491 x.frames = count / (pcm->config.channels * in pcm_write()
492 pcm_format_to_bits(pcm->config.format) / 8); in pcm_write()
495 if (!pcm->running) { in pcm_write()
496 int prepare_error = pcm_prepare(pcm); in pcm_write()
499 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &x)) in pcm_write()
500 return oops(pcm, errno, "cannot write initial data"); in pcm_write()
501 pcm->running = 1; in pcm_write()
504 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &x)) { in pcm_write()
505 pcm->prepared = 0; in pcm_write()
506 pcm->running = 0; in pcm_write()
511 pcm->underruns++; in pcm_write()
512 if (pcm->flags & PCM_NORESTART) in pcm_write()
516 return oops(pcm, errno, "cannot write stream data"); in pcm_write()
522 int pcm_read(struct pcm *pcm, void *data, unsigned int count) in pcm_read() argument
526 if (!(pcm->flags & PCM_IN)) in pcm_read()
530 x.frames = count / (pcm->config.channels * in pcm_read()
531 pcm_format_to_bits(pcm->config.format) / 8); in pcm_read()
534 if (!pcm->running) { in pcm_read()
535 if (pcm_start(pcm) < 0) { in pcm_read()
540 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_READI_FRAMES, &x)) { in pcm_read()
541 pcm->prepared = 0; in pcm_read()
542 pcm->running = 0; in pcm_read()
545 pcm->underruns++; in pcm_read()
548 return oops(pcm, errno, "cannot read stream data"); in pcm_read()
554 static struct pcm bad_pcm = {
817 int pcm_close(struct pcm *pcm) in pcm_close() argument
819 if (pcm == &bad_pcm) in pcm_close()
822 pcm_hw_munmap_status(pcm); in pcm_close()
824 if (pcm->flags & PCM_MMAP) { in pcm_close()
825 pcm_stop(pcm); in pcm_close()
826 munmap(pcm->mmap_buffer, pcm_frames_to_bytes(pcm, pcm->buffer_size)); in pcm_close()
829 if (pcm->fd >= 0) in pcm_close()
830 close(pcm->fd); in pcm_close()
831 pcm->prepared = 0; in pcm_close()
832 pcm->running = 0; in pcm_close()
833 pcm->buffer_size = 0; in pcm_close()
834 pcm->fd = -1; in pcm_close()
835 free(pcm); in pcm_close()
839 struct pcm *pcm_open(unsigned int card, unsigned int device, in pcm_open()
842 struct pcm *pcm; in pcm_open() local
849 pcm = calloc(1, sizeof(struct pcm)); in pcm_open()
850 if (!pcm || !config) in pcm_open()
853 pcm->config = *config; in pcm_open()
858 pcm->flags = flags; in pcm_open()
859 pcm->fd = open(fn, O_RDWR); in pcm_open()
860 if (pcm->fd < 0) { in pcm_open()
861 oops(pcm, errno, "cannot open device '%s'", fn); in pcm_open()
862 return pcm; in pcm_open()
865 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_INFO, &info)) { in pcm_open()
866 oops(pcm, errno, "cannot get info"); in pcm_open()
887 oops(pcm, -EINVAL, "noirq only currently supported with mmap()."); in pcm_open()
892 pcm->noirq_frames_per_msec = config->rate / 1000; in pcm_open()
902 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_HW_PARAMS, &params)) { in pcm_open()
903 oops(pcm, errno, "cannot set hw params"); in pcm_open()
910 pcm->buffer_size = config->period_count * config->period_size; in pcm_open()
913 pcm->mmap_buffer = mmap(NULL, pcm_frames_to_bytes(pcm, pcm->buffer_size), in pcm_open()
914 PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, pcm->fd, 0); in pcm_open()
915 if (pcm->mmap_buffer == MAP_FAILED) { in pcm_open()
916 oops(pcm, -errno, "failed to mmap buffer %d bytes\n", in pcm_open()
917 pcm_frames_to_bytes(pcm, pcm->buffer_size)); in pcm_open()
927 if (pcm->flags & PCM_IN) in pcm_open()
928 pcm->config.start_threshold = sparams.start_threshold = 1; in pcm_open()
930 pcm->config.start_threshold = sparams.start_threshold = in pcm_open()
937 if (pcm->flags & PCM_IN) in pcm_open()
938 pcm->config.stop_threshold = sparams.stop_threshold = in pcm_open()
941 pcm->config.stop_threshold = sparams.stop_threshold = in pcm_open()
947 if (!pcm->config.avail_min) { in pcm_open()
948 if (pcm->flags & PCM_MMAP) in pcm_open()
949 pcm->config.avail_min = sparams.avail_min = pcm->config.period_size; in pcm_open()
951 pcm->config.avail_min = sparams.avail_min = 1; in pcm_open()
958 pcm->boundary = sparams.boundary = pcm->buffer_size; in pcm_open()
960 while (pcm->boundary * 2 <= INT_MAX - pcm->buffer_size) in pcm_open()
961 pcm->boundary *= 2; in pcm_open()
963 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_SW_PARAMS, &sparams)) { in pcm_open()
964 oops(pcm, errno, "cannot set sw params"); in pcm_open()
968 rc = pcm_hw_mmap_status(pcm); in pcm_open()
970 oops(pcm, rc, "mmap status failed"); in pcm_open()
975 if (pcm->flags & PCM_MONOTONIC) { in pcm_open()
977 rc = ioctl(pcm->fd, SNDRV_PCM_IOCTL_TTSTAMP, &arg); in pcm_open()
979 oops(pcm, rc, "cannot set timestamp type"); in pcm_open()
985 pcm->underruns = 0; in pcm_open()
986 return pcm; in pcm_open()
990 munmap(pcm->mmap_buffer, pcm_frames_to_bytes(pcm, pcm->buffer_size)); in pcm_open()
992 close(pcm->fd); in pcm_open()
993 pcm->fd = -1; in pcm_open()
994 return pcm; in pcm_open()
997 int pcm_is_ready(struct pcm *pcm) in pcm_is_ready() argument
999 return pcm->fd >= 0; in pcm_is_ready()
1002 int pcm_prepare(struct pcm *pcm) in pcm_prepare() argument
1004 if (pcm->prepared) in pcm_prepare()
1007 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_PREPARE) < 0) in pcm_prepare()
1008 return oops(pcm, errno, "cannot prepare channel"); in pcm_prepare()
1010 pcm->prepared = 1; in pcm_prepare()
1014 int pcm_start(struct pcm *pcm) in pcm_start() argument
1016 int prepare_error = pcm_prepare(pcm); in pcm_start()
1020 if (pcm->flags & PCM_MMAP) in pcm_start()
1021 pcm_sync_ptr(pcm, 0); in pcm_start()
1023 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_START) < 0) in pcm_start()
1024 return oops(pcm, errno, "cannot start channel"); in pcm_start()
1026 pcm->running = 1; in pcm_start()
1030 int pcm_stop(struct pcm *pcm) in pcm_stop() argument
1032 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_DROP) < 0) in pcm_stop()
1033 return oops(pcm, errno, "cannot stop channel"); in pcm_stop()
1035 pcm->prepared = 0; in pcm_stop()
1036 pcm->running = 0; in pcm_stop()
1040 static inline int pcm_mmap_playback_avail(struct pcm *pcm) in pcm_mmap_playback_avail() argument
1044 avail = pcm->mmap_status->hw_ptr + pcm->buffer_size - pcm->mmap_control->appl_ptr; in pcm_mmap_playback_avail()
1047 avail += pcm->boundary; in pcm_mmap_playback_avail()
1048 else if (avail > (int)pcm->boundary) in pcm_mmap_playback_avail()
1049 avail -= pcm->boundary; in pcm_mmap_playback_avail()
1054 static inline int pcm_mmap_capture_avail(struct pcm *pcm) in pcm_mmap_capture_avail() argument
1056 int avail = pcm->mmap_status->hw_ptr - pcm->mmap_control->appl_ptr; in pcm_mmap_capture_avail()
1058 avail += pcm->boundary; in pcm_mmap_capture_avail()
1062 int pcm_mmap_avail(struct pcm *pcm) in pcm_mmap_avail() argument
1064 pcm_sync_ptr(pcm, SNDRV_PCM_SYNC_PTR_HWSYNC); in pcm_mmap_avail()
1065 if (pcm->flags & PCM_IN) in pcm_mmap_avail()
1066 return pcm_mmap_capture_avail(pcm); in pcm_mmap_avail()
1068 return pcm_mmap_playback_avail(pcm); in pcm_mmap_avail()
1071 static void pcm_mmap_appl_forward(struct pcm *pcm, int frames) in pcm_mmap_appl_forward() argument
1073 unsigned int appl_ptr = pcm->mmap_control->appl_ptr; in pcm_mmap_appl_forward()
1077 if (appl_ptr > pcm->boundary) in pcm_mmap_appl_forward()
1078 appl_ptr -= pcm->boundary; in pcm_mmap_appl_forward()
1079 pcm->mmap_control->appl_ptr = appl_ptr; in pcm_mmap_appl_forward()
1082 int pcm_mmap_begin(struct pcm *pcm, void **areas, unsigned int *offset, in pcm_mmap_begin() argument
1088 *areas = pcm->mmap_buffer; in pcm_mmap_begin()
1091 *offset = pcm->mmap_control->appl_ptr % pcm->buffer_size; in pcm_mmap_begin()
1093 avail = pcm_mmap_avail(pcm); in pcm_mmap_begin()
1094 if (avail > pcm->buffer_size) in pcm_mmap_begin()
1095 avail = pcm->buffer_size; in pcm_mmap_begin()
1096 continuous = pcm->buffer_size - *offset; in pcm_mmap_begin()
1109 int pcm_mmap_commit(struct pcm *pcm, unsigned int offset, unsigned int frames) in pcm_mmap_commit() argument
1112 pcm_mmap_appl_forward(pcm, frames); in pcm_mmap_commit()
1113 pcm_sync_ptr(pcm, 0); in pcm_mmap_commit()
1118 int pcm_avail_update(struct pcm *pcm) in pcm_avail_update() argument
1120 pcm_sync_ptr(pcm, 0); in pcm_avail_update()
1121 return pcm_mmap_avail(pcm); in pcm_avail_update()
1124 int pcm_state(struct pcm *pcm) in pcm_state() argument
1126 int err = pcm_sync_ptr(pcm, 0); in pcm_state()
1130 return pcm->mmap_status->state; in pcm_state()
1133 int pcm_set_avail_min(struct pcm *pcm, int avail_min) in pcm_set_avail_min() argument
1135 if ((~pcm->flags) & (PCM_MMAP | PCM_NOIRQ)) in pcm_set_avail_min()
1138 pcm->config.avail_min = avail_min; in pcm_set_avail_min()
1142 int pcm_wait(struct pcm *pcm, int timeout) in pcm_wait() argument
1147 pfd.fd = pcm->fd; in pcm_wait()
1166 switch (pcm_state(pcm)) { in pcm_wait()
1183 int pcm_get_poll_fd(struct pcm *pcm) in pcm_get_poll_fd() argument
1185 return pcm->fd; in pcm_get_poll_fd()
1188 int pcm_mmap_transfer(struct pcm *pcm, const void *buffer, unsigned int bytes) in pcm_mmap_transfer() argument
1196 count = pcm_bytes_to_frames(pcm, bytes); in pcm_mmap_transfer()
1201 avail = pcm_avail_update(pcm); in pcm_mmap_transfer()
1208 if (!pcm->running && in pcm_mmap_transfer()
1209 (pcm->buffer_size - avail) >= pcm->config.start_threshold) { in pcm_mmap_transfer()
1210 if (pcm_start(pcm) < 0) { in pcm_mmap_transfer()
1212 (unsigned int)pcm->mmap_status->hw_ptr, in pcm_mmap_transfer()
1213 (unsigned int)pcm->mmap_control->appl_ptr, in pcm_mmap_transfer()
1217 pcm->wait_for_avail_min = 0; in pcm_mmap_transfer()
1221 if (pcm->running) { in pcm_mmap_transfer()
1224 if (!pcm->wait_for_avail_min && (count > (unsigned int)avail)) in pcm_mmap_transfer()
1225 pcm->wait_for_avail_min = 1; in pcm_mmap_transfer()
1227 if (pcm->wait_for_avail_min && (avail < pcm->config.avail_min)) { in pcm_mmap_transfer()
1232 pcm->wait_for_avail_min = 0; in pcm_mmap_transfer()
1234 if (pcm->flags & PCM_NOIRQ) in pcm_mmap_transfer()
1235 time = (pcm->config.avail_min - avail) / pcm->noirq_frames_per_msec; in pcm_mmap_transfer()
1237 err = pcm_wait(pcm, time); in pcm_mmap_transfer()
1239 pcm->prepared = 0; in pcm_mmap_transfer()
1240 pcm->running = 0; in pcm_mmap_transfer()
1241 oops(pcm, err, "wait error: hw 0x%x app 0x%x avail 0x%x\n", in pcm_mmap_transfer()
1242 (unsigned int)pcm->mmap_status->hw_ptr, in pcm_mmap_transfer()
1243 (unsigned int)pcm->mmap_control->appl_ptr, in pcm_mmap_transfer()
1245 pcm->mmap_control->appl_ptr = 0; in pcm_mmap_transfer()
1260 frames = pcm_mmap_transfer_areas(pcm, (void *)buffer, offset, frames); in pcm_mmap_transfer()
1263 (unsigned int)pcm->mmap_status->hw_ptr, in pcm_mmap_transfer()
1264 (unsigned int)pcm->mmap_control->appl_ptr, in pcm_mmap_transfer()
1276 int pcm_mmap_write(struct pcm *pcm, const void *data, unsigned int count) in pcm_mmap_write() argument
1278 if ((~pcm->flags) & (PCM_OUT | PCM_MMAP)) in pcm_mmap_write()
1281 return pcm_mmap_transfer(pcm, (void *)data, count); in pcm_mmap_write()
1284 int pcm_mmap_read(struct pcm *pcm, void *data, unsigned int count) in pcm_mmap_read() argument
1286 if ((~pcm->flags) & (PCM_IN | PCM_MMAP)) in pcm_mmap_read()
1289 return pcm_mmap_transfer(pcm, data, count); in pcm_mmap_read()
1292 int pcm_ioctl(struct pcm *pcm, int request, ...) in pcm_ioctl() argument
1297 if (!pcm_is_ready(pcm)) in pcm_ioctl()
1304 return ioctl(pcm->fd, request, arg); in pcm_ioctl()