Lines Matching +full:chip +full:- +full:to +full:- +full:chip
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 * IBL size, typically 126 samples. at each end of chunk, the end-of-buffer
29 * pipe->transferred is the counter of data which has been already transferred.
30 * if this counter reaches to the period size, snd_pcm_period_elapsed() will
34 * to get a low latency response, we'll check the capture streams at each
36 * data is accumulated to the period size, snd_pcm_period_elapsed() is
39 * the current point of read buffer is kept in pipe->hw_ptr. note that
44 * - linked trigger for full-duplex mode.
45 * - scheduled action on the stream.
60 static void vx_pcm_read_per_bytes(struct vx_core *chip, struct snd_pcm_runtime *runtime, in vx_pcm_read_per_bytes() argument
63 int offset = pipe->hw_ptr; in vx_pcm_read_per_bytes()
64 unsigned char *buf = (unsigned char *)(runtime->dma_area + offset); in vx_pcm_read_per_bytes()
65 *buf++ = vx_inb(chip, RXH); in vx_pcm_read_per_bytes()
66 if (++offset >= pipe->buffer_bytes) { in vx_pcm_read_per_bytes()
68 buf = (unsigned char *)runtime->dma_area; in vx_pcm_read_per_bytes()
70 *buf++ = vx_inb(chip, RXM); in vx_pcm_read_per_bytes()
71 if (++offset >= pipe->buffer_bytes) { in vx_pcm_read_per_bytes()
73 buf = (unsigned char *)runtime->dma_area; in vx_pcm_read_per_bytes()
75 *buf++ = vx_inb(chip, RXL); in vx_pcm_read_per_bytes()
76 if (++offset >= pipe->buffer_bytes) { in vx_pcm_read_per_bytes()
78 buf = (unsigned char *)runtime->dma_area; in vx_pcm_read_per_bytes()
80 pipe->hw_ptr = offset; in vx_pcm_read_per_bytes()
84 * vx_set_pcx_time - convert from the PC time to the RMH status time.
85 * @pc_time: the pointer for the PC-time to set
88 static void vx_set_pcx_time(struct vx_core *chip, pcx_time_t *pc_time, in vx_set_pcx_time() argument
96 * vx_set_differed_time - set the differed time if specified
97 * @rmh: the rmh record to modify
98 * @pipe: the pipe to be checked
105 static int vx_set_differed_time(struct vx_core *chip, struct vx_rmh *rmh, in vx_set_differed_time() argument
108 /* Update The length added to the RMH command by the timestamp */ in vx_set_differed_time()
109 if (! (pipe->differed_type & DC_DIFFERED_DELAY)) in vx_set_differed_time()
113 rmh->Cmd[0] |= DSP_DIFFERED_COMMAND_MASK; in vx_set_differed_time()
116 vx_set_pcx_time(chip, &pipe->pcx_time, &rmh->Cmd[1]); in vx_set_differed_time()
118 /* Add the flags to a notified differed command */ in vx_set_differed_time()
119 if (pipe->differed_type & DC_NOTIFY_DELAY) in vx_set_differed_time()
120 rmh->Cmd[1] |= NOTIFY_MASK_TIME_HIGH ; in vx_set_differed_time()
122 /* Add the flags to a multiple differed command */ in vx_set_differed_time()
123 if (pipe->differed_type & DC_MULTIPLE_DELAY) in vx_set_differed_time()
124 rmh->Cmd[1] |= MULTIPLE_MASK_TIME_HIGH; in vx_set_differed_time()
126 /* Add the flags to a stream-time differed command */ in vx_set_differed_time()
127 if (pipe->differed_type & DC_STREAM_TIME_DELAY) in vx_set_differed_time()
128 rmh->Cmd[1] |= STREAM_MASK_TIME_HIGH; in vx_set_differed_time()
130 rmh->LgCmd += 2; in vx_set_differed_time()
135 * vx_set_stream_format - send the stream format command
139 static int vx_set_stream_format(struct vx_core *chip, struct vx_pipe *pipe, in vx_set_stream_format() argument
144 vx_init_rmh(&rmh, pipe->is_capture ? in vx_set_stream_format()
146 rmh.Cmd[0] |= pipe->number << FIELD_SIZE; in vx_set_stream_format()
148 /* Command might be longer since we may have to add a timestamp */ in vx_set_stream_format()
149 vx_set_differed_time(chip, &rmh, pipe); in vx_set_stream_format()
155 return vx_send_msg(chip, &rmh); in vx_set_stream_format()
160 * vx_set_format - set the format of a pipe
162 * @runtime: pcm runtime instance to be referred
166 static int vx_set_format(struct vx_core *chip, struct vx_pipe *pipe, in vx_set_format() argument
171 if (runtime->channels == 1) in vx_set_format()
173 if (snd_pcm_format_little_endian(runtime->format)) in vx_set_format()
175 if (runtime->rate < 32000 && runtime->rate > 11025) in vx_set_format()
177 else if (runtime->rate <= 11025) in vx_set_format()
180 switch (snd_pcm_format_physical_width(runtime->format)) { in vx_set_format()
186 return -EINVAL; in vx_set_format()
189 return vx_set_stream_format(chip, pipe, header); in vx_set_format()
195 static int vx_set_ibl(struct vx_core *chip, struct vx_ibl_info *info) in vx_set_ibl() argument
201 rmh.Cmd[0] |= info->size & 0x03ffff; in vx_set_ibl()
202 err = vx_send_msg(chip, &rmh); in vx_set_ibl()
205 info->size = rmh.Stat[0]; in vx_set_ibl()
206 info->max_size = rmh.Stat[1]; in vx_set_ibl()
207 info->min_size = rmh.Stat[2]; in vx_set_ibl()
208 info->granularity = rmh.Stat[3]; in vx_set_ibl()
210 info->size, info->max_size, info->min_size, info->granularity); in vx_set_ibl()
216 * vx_get_pipe_state - get the state of a pipe
217 * @pipe: the pipe to be checked
225 static int vx_get_pipe_state(struct vx_core *chip, struct vx_pipe *pipe, int *state) in vx_get_pipe_state() argument
231 vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0); in vx_get_pipe_state()
232 err = vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */ in vx_get_pipe_state()
234 *state = (rmh.Stat[0] & (1 << pipe->number)) ? 1 : 0; in vx_get_pipe_state()
240 * vx_query_hbuffer_size - query available h-buffer size in bytes
241 * @pipe: the pipe to be checked
243 * return the available size on h-buffer in bytes,
246 * NOTE: calling this function always switches to the stream mode.
247 * you'll need to disconnect the host to get back to the
250 static int vx_query_hbuffer_size(struct vx_core *chip, struct vx_pipe *pipe) in vx_query_hbuffer_size() argument
256 vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0); in vx_query_hbuffer_size()
257 if (pipe->is_capture) in vx_query_hbuffer_size()
259 result = vx_send_msg(chip, &rmh); in vx_query_hbuffer_size()
267 * vx_pipe_can_start - query whether a pipe is ready for start
268 * @pipe: the pipe to be checked
274 static int vx_pipe_can_start(struct vx_core *chip, struct vx_pipe *pipe) in vx_pipe_can_start() argument
280 vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0); in vx_pipe_can_start()
283 err = vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */ in vx_pipe_can_start()
292 * vx_conf_pipe - tell the pipe to stand by and wait for IRQA.
293 * @pipe: the pipe to be configured
295 static int vx_conf_pipe(struct vx_core *chip, struct vx_pipe *pipe) in vx_conf_pipe() argument
300 if (pipe->is_capture) in vx_conf_pipe()
302 rmh.Cmd[1] = 1 << pipe->number; in vx_conf_pipe()
303 return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */ in vx_conf_pipe()
307 * vx_send_irqa - trigger IRQA
309 static int vx_send_irqa(struct vx_core *chip) in vx_send_irqa() argument
314 return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */ in vx_send_irqa()
320 * vx boards do not support inter-card sync, besides
321 * only 126 samples require to be prepared before a pipe can start
327 * vx_toggle_pipe - start / pause a pipe
328 * @pipe: the pipe to be triggered
334 static int vx_toggle_pipe(struct vx_core *chip, struct vx_pipe *pipe, int state) in vx_toggle_pipe() argument
339 if (vx_get_pipe_state(chip, pipe, &cur_state) < 0) in vx_toggle_pipe()
340 return -EBADFD; in vx_toggle_pipe()
344 /* If a start is requested, ask the DSP to get prepared in vx_toggle_pipe()
350 err = vx_pipe_can_start(chip, pipe); in vx_toggle_pipe()
354 * to avoid flooding the DSP with our requests in vx_toggle_pipe()
360 if ((err = vx_conf_pipe(chip, pipe)) < 0) in vx_toggle_pipe()
363 if ((err = vx_send_irqa(chip)) < 0) in vx_toggle_pipe()
371 err = vx_get_pipe_state(chip, pipe, &cur_state); in vx_toggle_pipe()
374 err = -EIO; in vx_toggle_pipe()
377 return err < 0 ? -EIO : 0; in vx_toggle_pipe()
382 * vx_stop_pipe - stop a pipe
383 * @pipe: the pipe to be stopped
387 static int vx_stop_pipe(struct vx_core *chip, struct vx_pipe *pipe) in vx_stop_pipe() argument
391 vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0); in vx_stop_pipe()
392 return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */ in vx_stop_pipe()
397 * vx_alloc_pipe - allocate a pipe and initialize the pipe instance
399 * @audioid: the audio id to be assigned
405 static int vx_alloc_pipe(struct vx_core *chip, int capture, in vx_alloc_pipe() argument
421 data_mode = (chip->uer_bits & IEC958_AES0_NONAUDIO) != 0; in vx_alloc_pipe()
424 err = vx_send_msg(chip, &rmh); in vx_alloc_pipe()
434 vx_send_msg(chip, &rmh); in vx_alloc_pipe()
435 return -ENOMEM; in vx_alloc_pipe()
439 pipe->number = audioid; in vx_alloc_pipe()
440 pipe->is_capture = capture; in vx_alloc_pipe()
441 pipe->channels = num_audio; in vx_alloc_pipe()
442 pipe->differed_type = 0; in vx_alloc_pipe()
443 pipe->pcx_time = 0; in vx_alloc_pipe()
444 pipe->data_mode = data_mode; in vx_alloc_pipe()
452 * vx_free_pipe - release a pipe
453 * @pipe: pipe to be released
455 static int vx_free_pipe(struct vx_core *chip, struct vx_pipe *pipe) in vx_free_pipe() argument
460 vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0); in vx_free_pipe()
461 vx_send_msg(chip, &rmh); in vx_free_pipe()
469 * vx_start_stream - start the stream
473 static int vx_start_stream(struct vx_core *chip, struct vx_pipe *pipe) in vx_start_stream() argument
478 vx_set_stream_cmd_params(&rmh, pipe->is_capture, pipe->number); in vx_start_stream()
479 vx_set_differed_time(chip, &rmh, pipe); in vx_start_stream()
480 return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */ in vx_start_stream()
485 * vx_stop_stream - stop the stream
489 static int vx_stop_stream(struct vx_core *chip, struct vx_pipe *pipe) in vx_stop_stream() argument
494 vx_set_stream_cmd_params(&rmh, pipe->is_capture, pipe->number); in vx_stop_stream()
495 return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */ in vx_stop_stream()
526 * vx_pcm_playback_open - open callback for playback
530 struct snd_pcm_runtime *runtime = subs->runtime; in vx_pcm_playback_open()
531 struct vx_core *chip = snd_pcm_substream_chip(subs); in vx_pcm_playback_open() local
536 if (chip->chip_status & VX_STAT_IS_STALE) in vx_pcm_playback_open()
537 return -EBUSY; in vx_pcm_playback_open()
539 audio = subs->pcm->device * 2; in vx_pcm_playback_open()
540 if (snd_BUG_ON(audio >= chip->audio_outs)) in vx_pcm_playback_open()
541 return -EINVAL; in vx_pcm_playback_open()
544 pipe = chip->playback_pipes[audio]; in vx_pcm_playback_open()
547 err = vx_alloc_pipe(chip, 0, audio, 2, &pipe); /* stereo playback */ in vx_pcm_playback_open()
550 chip->playback_pipes[audio] = pipe; in vx_pcm_playback_open()
553 pipe->references++; in vx_pcm_playback_open()
555 pipe->substream = subs; in vx_pcm_playback_open()
556 tasklet_init(&pipe->start_tq, vx_pcm_delayed_start, (unsigned long)subs); in vx_pcm_playback_open()
557 chip->playback_pipes[audio] = pipe; in vx_pcm_playback_open()
559 runtime->hw = vx_pcm_playback_hw; in vx_pcm_playback_open()
560 runtime->hw.period_bytes_min = chip->ibl.size; in vx_pcm_playback_open()
561 runtime->private_data = pipe; in vx_pcm_playback_open()
563 /* align to 4 bytes (otherwise will be problematic when 24bit is used) */ in vx_pcm_playback_open()
571 * vx_pcm_playback_close - close callback for playback
575 struct vx_core *chip = snd_pcm_substream_chip(subs); in vx_pcm_playback_close() local
578 if (! subs->runtime->private_data) in vx_pcm_playback_close()
579 return -EINVAL; in vx_pcm_playback_close()
581 pipe = subs->runtime->private_data; in vx_pcm_playback_close()
583 if (--pipe->references == 0) { in vx_pcm_playback_close()
584 chip->playback_pipes[pipe->number] = NULL; in vx_pcm_playback_close()
585 vx_free_pipe(chip, pipe); in vx_pcm_playback_close()
594 * vx_notify_end_of_buffer - send "end-of-buffer" notifier at the given pipe
595 * @pipe: the pipe to notify
599 static int vx_notify_end_of_buffer(struct vx_core *chip, struct vx_pipe *pipe) in vx_notify_end_of_buffer() argument
605 vx_send_rih_nolock(chip, IRQ_PAUSE_START_CONNECT); in vx_notify_end_of_buffer()
607 vx_set_stream_cmd_params(&rmh, 0, pipe->number); in vx_notify_end_of_buffer()
608 err = vx_send_msg_nolock(chip, &rmh); in vx_notify_end_of_buffer()
611 /* Toggle Dsp Host Interface back to sound transfer mode */ in vx_notify_end_of_buffer()
612 vx_send_rih_nolock(chip, IRQ_PAUSE_START_CONNECT); in vx_notify_end_of_buffer()
617 * vx_pcm_playback_transfer_chunk - transfer a single chunk
619 * @pipe: the pipe to transfer
627 static int vx_pcm_playback_transfer_chunk(struct vx_core *chip, in vx_pcm_playback_transfer_chunk() argument
633 space = vx_query_hbuffer_size(chip, pipe); in vx_pcm_playback_transfer_chunk()
635 /* disconnect the host, SIZE_HBUF command always switches to the stream mode */ in vx_pcm_playback_transfer_chunk()
636 vx_send_rih(chip, IRQ_CONNECT_STREAM_NEXT); in vx_pcm_playback_transfer_chunk()
641 vx_send_rih(chip, IRQ_CONNECT_STREAM_NEXT); in vx_pcm_playback_transfer_chunk()
643 return -EIO; /* XRUN */ in vx_pcm_playback_transfer_chunk()
649 spin_lock(&chip->lock); in vx_pcm_playback_transfer_chunk()
650 vx_pseudo_dma_write(chip, runtime, pipe, size); in vx_pcm_playback_transfer_chunk()
651 err = vx_notify_end_of_buffer(chip, pipe); in vx_pcm_playback_transfer_chunk()
652 /* disconnect the host, SIZE_HBUF command always switches to the stream mode */ in vx_pcm_playback_transfer_chunk()
653 vx_send_rih_nolock(chip, IRQ_CONNECT_STREAM_NEXT); in vx_pcm_playback_transfer_chunk()
654 spin_unlock(&chip->lock); in vx_pcm_playback_transfer_chunk()
660 * pipe->position is updated and wrapped within the buffer size.
661 * pipe->transferred is updated, too, but the size is not wrapped,
663 * (to call snd_pcm_period_elapsed).
665 static int vx_update_pipe_position(struct vx_core *chip, in vx_update_pipe_position() argument
674 vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0); in vx_update_pipe_position()
675 err = vx_send_msg(chip, &rmh); in vx_update_pipe_position()
680 update = (int)(count - pipe->cur_count); in vx_update_pipe_position()
681 pipe->cur_count = count; in vx_update_pipe_position()
682 pipe->position += update; in vx_update_pipe_position()
683 if (pipe->position >= (int)runtime->buffer_size) in vx_update_pipe_position()
684 pipe->position %= runtime->buffer_size; in vx_update_pipe_position()
685 pipe->transferred += update; in vx_update_pipe_position()
690 * transfer the pending playback buffer data to DSP
693 static void vx_pcm_playback_transfer(struct vx_core *chip, in vx_pcm_playback_transfer() argument
698 struct snd_pcm_runtime *runtime = subs->runtime; in vx_pcm_playback_transfer()
700 if (! pipe->prepared || (chip->chip_status & VX_STAT_IS_STALE)) in vx_pcm_playback_transfer()
703 if ((err = vx_pcm_playback_transfer_chunk(chip, runtime, pipe, in vx_pcm_playback_transfer()
704 chip->ibl.size)) < 0) in vx_pcm_playback_transfer()
713 static void vx_pcm_playback_update(struct vx_core *chip, in vx_pcm_playback_update() argument
718 struct snd_pcm_runtime *runtime = subs->runtime; in vx_pcm_playback_update()
720 if (pipe->running && ! (chip->chip_status & VX_STAT_IS_STALE)) { in vx_pcm_playback_update()
721 if ((err = vx_update_pipe_position(chip, runtime, pipe)) < 0) in vx_pcm_playback_update()
723 if (pipe->transferred >= (int)runtime->period_size) { in vx_pcm_playback_update()
724 pipe->transferred %= runtime->period_size; in vx_pcm_playback_update()
738 struct vx_core *chip = subs->pcm->private_data; in vx_pcm_delayed_start() local
739 struct vx_pipe *pipe = subs->runtime->private_data; in vx_pcm_delayed_start()
744 if ((err = vx_start_stream(chip, pipe)) < 0) { in vx_pcm_delayed_start()
748 if ((err = vx_toggle_pipe(chip, pipe, 1)) < 0) { in vx_pcm_delayed_start()
756 * vx_pcm_playback_trigger - trigger callback for playback
760 struct vx_core *chip = snd_pcm_substream_chip(subs); in vx_pcm_trigger() local
761 struct vx_pipe *pipe = subs->runtime->private_data; in vx_pcm_trigger()
764 if (chip->chip_status & VX_STAT_IS_STALE) in vx_pcm_trigger()
765 return -EBUSY; in vx_pcm_trigger()
770 if (! pipe->is_capture) in vx_pcm_trigger()
771 vx_pcm_playback_transfer(chip, subs, pipe, 2); in vx_pcm_trigger()
776 tasklet_schedule(&pipe->start_tq); in vx_pcm_trigger()
777 chip->pcm_running++; in vx_pcm_trigger()
778 pipe->running = 1; in vx_pcm_trigger()
782 vx_toggle_pipe(chip, pipe, 0); in vx_pcm_trigger()
783 vx_stop_pipe(chip, pipe); in vx_pcm_trigger()
784 vx_stop_stream(chip, pipe); in vx_pcm_trigger()
785 chip->pcm_running--; in vx_pcm_trigger()
786 pipe->running = 0; in vx_pcm_trigger()
789 if ((err = vx_toggle_pipe(chip, pipe, 0)) < 0) in vx_pcm_trigger()
793 if ((err = vx_toggle_pipe(chip, pipe, 1)) < 0) in vx_pcm_trigger()
797 return -EINVAL; in vx_pcm_trigger()
803 * vx_pcm_playback_pointer - pointer callback for playback
807 struct snd_pcm_runtime *runtime = subs->runtime; in vx_pcm_playback_pointer()
808 struct vx_pipe *pipe = runtime->private_data; in vx_pcm_playback_pointer()
809 return pipe->position; in vx_pcm_playback_pointer()
813 * vx_pcm_hw_params - hw_params callback for playback and capture
823 * vx_pcm_hw_free - hw_free callback for playback and capture
831 * vx_pcm_prepare - prepare callback for playback and capture
835 struct vx_core *chip = snd_pcm_substream_chip(subs); in vx_pcm_prepare() local
836 struct snd_pcm_runtime *runtime = subs->runtime; in vx_pcm_prepare()
837 struct vx_pipe *pipe = runtime->private_data; in vx_pcm_prepare()
841 if (chip->chip_status & VX_STAT_IS_STALE) in vx_pcm_prepare()
842 return -EBUSY; in vx_pcm_prepare()
844 data_mode = (chip->uer_bits & IEC958_AES0_NONAUDIO) != 0; in vx_pcm_prepare()
845 if (data_mode != pipe->data_mode && ! pipe->is_capture) { in vx_pcm_prepare()
846 /* IEC958 status (raw-mode) was changed */ in vx_pcm_prepare()
851 vx_set_pipe_cmd_params(&rmh, 0, pipe->number, 0); in vx_pcm_prepare()
852 if ((err = vx_send_msg(chip, &rmh)) < 0) in vx_pcm_prepare()
855 vx_set_pipe_cmd_params(&rmh, 0, pipe->number, pipe->channels); in vx_pcm_prepare()
858 if ((err = vx_send_msg(chip, &rmh)) < 0) in vx_pcm_prepare()
860 pipe->data_mode = data_mode; in vx_pcm_prepare()
863 if (chip->pcm_running && chip->freq != runtime->rate) { in vx_pcm_prepare()
865 "from the current %d\n", runtime->rate, chip->freq); in vx_pcm_prepare()
866 return -EINVAL; in vx_pcm_prepare()
868 vx_set_clock(chip, runtime->rate); in vx_pcm_prepare()
870 if ((err = vx_set_format(chip, pipe, runtime)) < 0) in vx_pcm_prepare()
873 if (vx_is_pcmcia(chip)) { in vx_pcm_prepare()
874 pipe->align = 2; /* 16bit word */ in vx_pcm_prepare()
876 pipe->align = 4; /* 32bit word */ in vx_pcm_prepare()
879 pipe->buffer_bytes = frames_to_bytes(runtime, runtime->buffer_size); in vx_pcm_prepare()
880 pipe->period_bytes = frames_to_bytes(runtime, runtime->period_size); in vx_pcm_prepare()
881 pipe->hw_ptr = 0; in vx_pcm_prepare()
884 vx_update_pipe_position(chip, runtime, pipe); in vx_pcm_prepare()
886 pipe->transferred = 0; in vx_pcm_prepare()
887 pipe->position = 0; in vx_pcm_prepare()
889 pipe->prepared = 1; in vx_pcm_prepare()
937 * vx_pcm_capture_open - open callback for capture
941 struct snd_pcm_runtime *runtime = subs->runtime; in vx_pcm_capture_open()
942 struct vx_core *chip = snd_pcm_substream_chip(subs); in vx_pcm_capture_open() local
948 if (chip->chip_status & VX_STAT_IS_STALE) in vx_pcm_capture_open()
949 return -EBUSY; in vx_pcm_capture_open()
951 audio = subs->pcm->device * 2; in vx_pcm_capture_open()
952 if (snd_BUG_ON(audio >= chip->audio_ins)) in vx_pcm_capture_open()
953 return -EINVAL; in vx_pcm_capture_open()
954 err = vx_alloc_pipe(chip, 1, audio, 2, &pipe); in vx_pcm_capture_open()
957 pipe->substream = subs; in vx_pcm_capture_open()
958 tasklet_init(&pipe->start_tq, vx_pcm_delayed_start, (unsigned long)subs); in vx_pcm_capture_open()
959 chip->capture_pipes[audio] = pipe; in vx_pcm_capture_open()
962 if (chip->audio_monitor_active[audio]) { in vx_pcm_capture_open()
963 pipe_out_monitoring = chip->playback_pipes[audio]; in vx_pcm_capture_open()
966 err = vx_alloc_pipe(chip, 0, audio, 2, &pipe_out_monitoring); in vx_pcm_capture_open()
969 chip->playback_pipes[audio] = pipe_out_monitoring; in vx_pcm_capture_open()
971 pipe_out_monitoring->references++; in vx_pcm_capture_open()
973 if an output pipe is available, it's audios still may need to be in vx_pcm_capture_open()
974 unmuted. hence we'll have to call a mixer entry point. in vx_pcm_capture_open()
976 vx_set_monitor_level(chip, audio, chip->audio_monitor[audio], in vx_pcm_capture_open()
977 chip->audio_monitor_active[audio]); in vx_pcm_capture_open()
979 vx_set_monitor_level(chip, audio+1, chip->audio_monitor[audio+1], in vx_pcm_capture_open()
980 chip->audio_monitor_active[audio+1]); in vx_pcm_capture_open()
983 pipe->monitoring_pipe = pipe_out_monitoring; /* default value NULL */ in vx_pcm_capture_open()
985 runtime->hw = vx_pcm_capture_hw; in vx_pcm_capture_open()
986 runtime->hw.period_bytes_min = chip->ibl.size; in vx_pcm_capture_open()
987 runtime->private_data = pipe; in vx_pcm_capture_open()
989 /* align to 4 bytes (otherwise will be problematic when 24bit is used) */ in vx_pcm_capture_open()
997 * vx_pcm_capture_close - close callback for capture
1001 struct vx_core *chip = snd_pcm_substream_chip(subs); in vx_pcm_capture_close() local
1005 if (! subs->runtime->private_data) in vx_pcm_capture_close()
1006 return -EINVAL; in vx_pcm_capture_close()
1007 pipe = subs->runtime->private_data; in vx_pcm_capture_close()
1008 chip->capture_pipes[pipe->number] = NULL; in vx_pcm_capture_close()
1010 pipe_out_monitoring = pipe->monitoring_pipe; in vx_pcm_capture_close()
1013 if an output pipe is attached to this input, in vx_pcm_capture_close()
1014 check if it needs to be released. in vx_pcm_capture_close()
1017 if (--pipe_out_monitoring->references == 0) { in vx_pcm_capture_close()
1018 vx_free_pipe(chip, pipe_out_monitoring); in vx_pcm_capture_close()
1019 chip->playback_pipes[pipe->number] = NULL; in vx_pcm_capture_close()
1020 pipe->monitoring_pipe = NULL; in vx_pcm_capture_close()
1024 vx_free_pipe(chip, pipe); in vx_pcm_capture_close()
1033 * vx_pcm_capture_update - update the capture buffer
1035 static void vx_pcm_capture_update(struct vx_core *chip, struct snd_pcm_substream *subs, in vx_pcm_capture_update() argument
1039 struct snd_pcm_runtime *runtime = subs->runtime; in vx_pcm_capture_update()
1041 if (! pipe->prepared || (chip->chip_status & VX_STAT_IS_STALE)) in vx_pcm_capture_update()
1044 size = runtime->buffer_size - snd_pcm_capture_avail(runtime); in vx_pcm_capture_update()
1048 space = vx_query_hbuffer_size(chip, pipe); in vx_pcm_capture_update()
1053 size = (size / 3) * 3; /* align to 3 bytes */ in vx_pcm_capture_update()
1058 count = size - DMA_READ_ALIGN; in vx_pcm_capture_update()
1059 /* read bytes until the current pointer reaches to the aligned position in vx_pcm_capture_update()
1060 * for word-transfer in vx_pcm_capture_update()
1063 if ((pipe->hw_ptr % pipe->align) == 0) in vx_pcm_capture_update()
1065 if (vx_wait_for_rx_full(chip) < 0) in vx_pcm_capture_update()
1067 vx_pcm_read_per_bytes(chip, runtime, pipe); in vx_pcm_capture_update()
1068 count -= 3; in vx_pcm_capture_update()
1072 int align = pipe->align * 3; in vx_pcm_capture_update()
1074 vx_pseudo_dma_read(chip, runtime, pipe, space); in vx_pcm_capture_update()
1075 count -= space; in vx_pcm_capture_update()
1079 if (vx_wait_for_rx_full(chip) < 0) in vx_pcm_capture_update()
1081 vx_pcm_read_per_bytes(chip, runtime, pipe); in vx_pcm_capture_update()
1082 count -= 3; in vx_pcm_capture_update()
1084 /* disconnect the host, SIZE_HBUF command always switches to the stream mode */ in vx_pcm_capture_update()
1085 vx_send_rih_nolock(chip, IRQ_CONNECT_STREAM_NEXT); in vx_pcm_capture_update()
1089 vx_pcm_read_per_bytes(chip, runtime, pipe); in vx_pcm_capture_update()
1090 count -= 3; in vx_pcm_capture_update()
1093 pipe->transferred += size; in vx_pcm_capture_update()
1094 if (pipe->transferred >= pipe->period_bytes) { in vx_pcm_capture_update()
1095 pipe->transferred %= pipe->period_bytes; in vx_pcm_capture_update()
1101 /* disconnect the host, SIZE_HBUF command always switches to the stream mode */ in vx_pcm_capture_update()
1102 vx_send_rih_nolock(chip, IRQ_CONNECT_STREAM_NEXT); in vx_pcm_capture_update()
1107 * vx_pcm_capture_pointer - pointer callback for capture
1111 struct snd_pcm_runtime *runtime = subs->runtime; in vx_pcm_capture_pointer()
1112 struct vx_pipe *pipe = runtime->private_data; in vx_pcm_capture_pointer()
1113 return bytes_to_frames(runtime, pipe->hw_ptr); in vx_pcm_capture_pointer()
1136 void vx_pcm_update_intr(struct vx_core *chip, unsigned int events) in vx_pcm_update_intr() argument
1144 vx_init_rmh(&chip->irq_rmh, CMD_ASYNC); in vx_pcm_update_intr()
1146 chip->irq_rmh.Cmd[0] |= 0x00000001; /* SEL_ASYNC_EVENTS */ in vx_pcm_update_intr()
1148 chip->irq_rmh.Cmd[0] |= 0x00000002; /* SEL_END_OF_BUF_EVENTS */ in vx_pcm_update_intr()
1150 if (vx_send_msg(chip, &chip->irq_rmh) < 0) { in vx_pcm_update_intr()
1156 while (i < chip->irq_rmh.LgStat) { in vx_pcm_update_intr()
1158 p = chip->irq_rmh.Stat[i] & MASK_FIRST_FIELD; in vx_pcm_update_intr()
1159 capture = (chip->irq_rmh.Stat[i] & 0x400000) ? 1 : 0; in vx_pcm_update_intr()
1160 eob = (chip->irq_rmh.Stat[i] & 0x800000) ? 1 : 0; in vx_pcm_update_intr()
1164 buf = 1; /* force to transfer */ in vx_pcm_update_intr()
1167 buf = chip->irq_rmh.Stat[i]; in vx_pcm_update_intr()
1172 if (snd_BUG_ON(p < 0 || p >= chip->audio_outs)) in vx_pcm_update_intr()
1174 pipe = chip->playback_pipes[p]; in vx_pcm_update_intr()
1175 if (pipe && pipe->substream) { in vx_pcm_update_intr()
1176 vx_pcm_playback_update(chip, pipe->substream, pipe); in vx_pcm_update_intr()
1177 vx_pcm_playback_transfer(chip, pipe->substream, pipe, buf); in vx_pcm_update_intr()
1183 for (i = 0; i < chip->audio_ins; i++) { in vx_pcm_update_intr()
1184 pipe = chip->capture_pipes[i]; in vx_pcm_update_intr()
1185 if (pipe && pipe->substream) in vx_pcm_update_intr()
1186 vx_pcm_capture_update(chip, pipe->substream, pipe); in vx_pcm_update_intr()
1192 * vx_init_audio_io - check the available audio i/o and allocate pipe arrays
1194 static int vx_init_audio_io(struct vx_core *chip) in vx_init_audio_io() argument
1200 if (vx_send_msg(chip, &rmh) < 0) { in vx_init_audio_io()
1202 return -ENXIO; in vx_init_audio_io()
1205 chip->audio_outs = rmh.Stat[0] & MASK_FIRST_FIELD; in vx_init_audio_io()
1206 chip->audio_ins = (rmh.Stat[0] >> (FIELD_SIZE*2)) & MASK_FIRST_FIELD; in vx_init_audio_io()
1207 chip->audio_info = rmh.Stat[1]; in vx_init_audio_io()
1210 chip->playback_pipes = kcalloc(chip->audio_outs, sizeof(struct vx_pipe *), GFP_KERNEL); in vx_init_audio_io()
1211 if (!chip->playback_pipes) in vx_init_audio_io()
1212 return -ENOMEM; in vx_init_audio_io()
1213 chip->capture_pipes = kcalloc(chip->audio_ins, sizeof(struct vx_pipe *), GFP_KERNEL); in vx_init_audio_io()
1214 if (!chip->capture_pipes) { in vx_init_audio_io()
1215 kfree(chip->playback_pipes); in vx_init_audio_io()
1216 return -ENOMEM; in vx_init_audio_io()
1219 preferred = chip->ibl.size; in vx_init_audio_io()
1220 chip->ibl.size = 0; in vx_init_audio_io()
1221 vx_set_ibl(chip, &chip->ibl); /* query the info */ in vx_init_audio_io()
1223 chip->ibl.size = ((preferred + chip->ibl.granularity - 1) / in vx_init_audio_io()
1224 chip->ibl.granularity) * chip->ibl.granularity; in vx_init_audio_io()
1225 if (chip->ibl.size > chip->ibl.max_size) in vx_init_audio_io()
1226 chip->ibl.size = chip->ibl.max_size; in vx_init_audio_io()
1228 chip->ibl.size = chip->ibl.min_size; /* set to the minimum */ in vx_init_audio_io()
1229 vx_set_ibl(chip, &chip->ibl); in vx_init_audio_io()
1240 struct vx_core *chip = pcm->private_data; in snd_vx_pcm_free() local
1241 chip->pcm[pcm->device] = NULL; in snd_vx_pcm_free()
1242 kfree(chip->playback_pipes); in snd_vx_pcm_free()
1243 chip->playback_pipes = NULL; in snd_vx_pcm_free()
1244 kfree(chip->capture_pipes); in snd_vx_pcm_free()
1245 chip->capture_pipes = NULL; in snd_vx_pcm_free()
1249 * snd_vx_pcm_new - create and initialize a pcm
1251 int snd_vx_pcm_new(struct vx_core *chip) in snd_vx_pcm_new() argument
1257 if ((err = vx_init_audio_io(chip)) < 0) in snd_vx_pcm_new()
1260 for (i = 0; i < chip->hw->num_codecs; i++) { in snd_vx_pcm_new()
1262 outs = chip->audio_outs > i * 2 ? 1 : 0; in snd_vx_pcm_new()
1263 ins = chip->audio_ins > i * 2 ? 1 : 0; in snd_vx_pcm_new()
1266 err = snd_pcm_new(chip->card, "VX PCM", i, in snd_vx_pcm_new()
1275 pcm->private_data = chip; in snd_vx_pcm_new()
1276 pcm->private_free = snd_vx_pcm_free; in snd_vx_pcm_new()
1277 pcm->info_flags = 0; in snd_vx_pcm_new()
1278 strcpy(pcm->name, chip->card->shortname); in snd_vx_pcm_new()
1279 chip->pcm[i] = pcm; in snd_vx_pcm_new()