static int snd_sh_dac_pcm_silence(struct snd_pcm_substream *substream, int channel, snd_pcm_uframes_t pos, snd_pcm_uframes_t count) { struct snd_sh_dac *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; ssize_t b_count = frames_to_bytes(runtime , count); ssize_t b_pos = frames_to_bytes(runtime , pos); if (count < 0) return -EINVAL; if (!count) return 0; memset_io(chip->data_buffer + b_pos, 0, b_count); chip->buffer_end = chip->data_buffer + b_pos + b_count; if (chip->empty) { chip->empty = 0; dac_audio_start_timer(chip); } return 0; }
static int snd_sh_dac_pcm_copy(struct snd_pcm_substream *substream, int channel, snd_pcm_uframes_t pos, void __user *src, snd_pcm_uframes_t count) { /* channel is not used (interleaved data) */ struct snd_sh_dac *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; ssize_t b_count = frames_to_bytes(runtime , count); ssize_t b_pos = frames_to_bytes(runtime , pos); if (count < 0) return -EINVAL; if (!count) return 0; memcpy_toio(chip->data_buffer + b_pos, src, b_count); chip->buffer_end = chip->data_buffer + b_pos + b_count; if (chip->empty) { chip->empty = 0; dac_audio_start_timer(chip); } return 0; }
static ssize_t dac_audio_write(struct file *file, const char *buf, size_t count, loff_t * ppos) { int free; int nbytes; if (count < 0) return -EINVAL; if (!count) { dac_audio_sync(); return 0; } free = buffer_begin - buffer_end; if (free < 0) free += BUFFER_SIZE; if ((free == 0) && (empty)) free = BUFFER_SIZE; if (count > free) count = free; if (buffer_begin > buffer_end) { if (copy_from_user((void *)buffer_end, buf, count)) return -EFAULT; buffer_end += count; } else { nbytes = data_buffer + BUFFER_SIZE - buffer_end; if (nbytes > count) { if (copy_from_user((void *)buffer_end, buf, count)) return -EFAULT; buffer_end += count; } else { if (copy_from_user((void *)buffer_end, buf, nbytes)) return -EFAULT; if (copy_from_user ((void *)data_buffer, buf + nbytes, count - nbytes)) return -EFAULT; buffer_end = data_buffer + count - nbytes; } } if (empty) { empty = 0; dac_audio_start_timer(); } return count; }
static int snd_sh_dac_pcm_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_sh_dac *chip = snd_pcm_substream_chip(substream); switch (cmd) { case SNDRV_PCM_TRIGGER_START: dac_audio_start_timer(chip); break; case SNDRV_PCM_TRIGGER_STOP: chip->buffer_begin = chip->buffer_end = chip->data_buffer; chip->processed = 0; chip->empty = 1; dac_audio_stop_timer(chip); break; default: return -EINVAL; } return 0; }