cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

vx_pcm.c (32350B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Driver for Digigram VX soundcards
      4 *
      5 * PCM part
      6 *
      7 * Copyright (c) 2002,2003 by Takashi Iwai <tiwai@suse.de>
      8 *
      9 * STRATEGY
     10 *  for playback, we send series of "chunks", which size is equal with the
     11 *  IBL size, typically 126 samples.  at each end of chunk, the end-of-buffer
     12 *  interrupt is notified, and the interrupt handler will feed the next chunk.
     13 *
     14 *  the current position is calculated from the sample count RMH.
     15 *  pipe->transferred is the counter of data which has been already transferred.
     16 *  if this counter reaches to the period size, snd_pcm_period_elapsed() will
     17 *  be issued.
     18 *
     19 *  for capture, the situation is much easier.
     20 *  to get a low latency response, we'll check the capture streams at each
     21 *  interrupt (capture stream has no EOB notification).  if the pending
     22 *  data is accumulated to the period size, snd_pcm_period_elapsed() is
     23 *  called and the pointer is updated.
     24 *
     25 *  the current point of read buffer is kept in pipe->hw_ptr.  note that
     26 *  this is in bytes.
     27 *
     28 * TODO
     29 *  - linked trigger for full-duplex mode.
     30 *  - scheduled action on the stream.
     31 */
     32
     33#include <linux/slab.h>
     34#include <linux/delay.h>
     35#include <sound/core.h>
     36#include <sound/asoundef.h>
     37#include <sound/pcm.h>
     38#include <sound/vx_core.h>
     39#include "vx_cmd.h"
     40
     41
     42/*
     43 * read three pending pcm bytes via inb()
     44 */
     45static void vx_pcm_read_per_bytes(struct vx_core *chip, struct snd_pcm_runtime *runtime,
     46				  struct vx_pipe *pipe)
     47{
     48	int offset = pipe->hw_ptr;
     49	unsigned char *buf = (unsigned char *)(runtime->dma_area + offset);
     50	*buf++ = vx_inb(chip, RXH);
     51	if (++offset >= pipe->buffer_bytes) {
     52		offset = 0;
     53		buf = (unsigned char *)runtime->dma_area;
     54	}
     55	*buf++ = vx_inb(chip, RXM);
     56	if (++offset >= pipe->buffer_bytes) {
     57		offset = 0;
     58		buf = (unsigned char *)runtime->dma_area;
     59	}
     60	*buf++ = vx_inb(chip, RXL);
     61	if (++offset >= pipe->buffer_bytes) {
     62		offset = 0;
     63	}
     64	pipe->hw_ptr = offset;
     65}
     66
     67/*
     68 * vx_set_pcx_time - convert from the PC time to the RMH status time.
     69 * @pc_time: the pointer for the PC-time to set
     70 * @dsp_time: the pointer for RMH status time array
     71 */
     72static void vx_set_pcx_time(struct vx_core *chip, pcx_time_t *pc_time,
     73			    unsigned int *dsp_time)
     74{
     75	dsp_time[0] = (unsigned int)((*pc_time) >> 24) & PCX_TIME_HI_MASK;
     76	dsp_time[1] = (unsigned int)(*pc_time) &  MASK_DSP_WORD;
     77}
     78
     79/*
     80 * vx_set_differed_time - set the differed time if specified
     81 * @rmh: the rmh record to modify
     82 * @pipe: the pipe to be checked
     83 *
     84 * if the pipe is programmed with the differed time, set the DSP time
     85 * on the rmh and changes its command length.
     86 *
     87 * returns the increase of the command length.
     88 */
     89static int vx_set_differed_time(struct vx_core *chip, struct vx_rmh *rmh,
     90				struct vx_pipe *pipe)
     91{
     92	/* Update The length added to the RMH command by the timestamp */
     93	if (! (pipe->differed_type & DC_DIFFERED_DELAY))
     94		return 0;
     95		
     96	/* Set the T bit */
     97	rmh->Cmd[0] |= DSP_DIFFERED_COMMAND_MASK;
     98
     99	/* Time stamp is the 1st following parameter */
    100	vx_set_pcx_time(chip, &pipe->pcx_time, &rmh->Cmd[1]);
    101
    102	/* Add the flags to a notified differed command */
    103	if (pipe->differed_type & DC_NOTIFY_DELAY)
    104		rmh->Cmd[1] |= NOTIFY_MASK_TIME_HIGH ;
    105
    106	/* Add the flags to a multiple differed command */
    107	if (pipe->differed_type & DC_MULTIPLE_DELAY)
    108		rmh->Cmd[1] |= MULTIPLE_MASK_TIME_HIGH;
    109
    110	/* Add the flags to a stream-time differed command */
    111	if (pipe->differed_type & DC_STREAM_TIME_DELAY)
    112		rmh->Cmd[1] |= STREAM_MASK_TIME_HIGH;
    113		
    114	rmh->LgCmd += 2;
    115	return 2;
    116}
    117
    118/*
    119 * vx_set_stream_format - send the stream format command
    120 * @pipe: the affected pipe
    121 * @data: format bitmask
    122 */
    123static int vx_set_stream_format(struct vx_core *chip, struct vx_pipe *pipe,
    124				unsigned int data)
    125{
    126	struct vx_rmh rmh;
    127
    128	vx_init_rmh(&rmh, pipe->is_capture ?
    129		    CMD_FORMAT_STREAM_IN : CMD_FORMAT_STREAM_OUT);
    130	rmh.Cmd[0] |= pipe->number << FIELD_SIZE;
    131
    132        /* Command might be longer since we may have to add a timestamp */
    133	vx_set_differed_time(chip, &rmh, pipe);
    134
    135	rmh.Cmd[rmh.LgCmd] = (data & 0xFFFFFF00) >> 8;
    136	rmh.Cmd[rmh.LgCmd + 1] = (data & 0xFF) << 16 /*| (datal & 0xFFFF00) >> 8*/;
    137	rmh.LgCmd += 2;
    138    
    139	return vx_send_msg(chip, &rmh);
    140}
    141
    142
    143/*
    144 * vx_set_format - set the format of a pipe
    145 * @pipe: the affected pipe
    146 * @runtime: pcm runtime instance to be referred
    147 *
    148 * returns 0 if successful, or a negative error code.
    149 */
    150static int vx_set_format(struct vx_core *chip, struct vx_pipe *pipe,
    151			 struct snd_pcm_runtime *runtime)
    152{
    153	unsigned int header = HEADER_FMT_BASE;
    154
    155	if (runtime->channels == 1)
    156		header |= HEADER_FMT_MONO;
    157	if (snd_pcm_format_little_endian(runtime->format))
    158		header |= HEADER_FMT_INTEL;
    159	if (runtime->rate < 32000 && runtime->rate > 11025)
    160		header |= HEADER_FMT_UPTO32;
    161	else if (runtime->rate <= 11025)
    162		header |= HEADER_FMT_UPTO11;
    163
    164	switch (snd_pcm_format_physical_width(runtime->format)) {
    165	// case 8: break;
    166	case 16: header |= HEADER_FMT_16BITS; break;
    167	case 24: header |= HEADER_FMT_24BITS; break;
    168	default : 
    169		snd_BUG();
    170		return -EINVAL;
    171	}
    172
    173	return vx_set_stream_format(chip, pipe, header);
    174}
    175
    176/*
    177 * set / query the IBL size
    178 */
    179static int vx_set_ibl(struct vx_core *chip, struct vx_ibl_info *info)
    180{
    181	int err;
    182	struct vx_rmh rmh;
    183
    184	vx_init_rmh(&rmh, CMD_IBL);
    185	rmh.Cmd[0] |= info->size & 0x03ffff;
    186	err = vx_send_msg(chip, &rmh);
    187	if (err < 0)
    188		return err;
    189	info->size = rmh.Stat[0];
    190	info->max_size = rmh.Stat[1];
    191	info->min_size = rmh.Stat[2];
    192	info->granularity = rmh.Stat[3];
    193	snd_printdd(KERN_DEBUG "vx_set_ibl: size = %d, max = %d, min = %d, gran = %d\n",
    194		   info->size, info->max_size, info->min_size, info->granularity);
    195	return 0;
    196}
    197
    198
    199/*
    200 * vx_get_pipe_state - get the state of a pipe
    201 * @pipe: the pipe to be checked
    202 * @state: the pointer for the returned state
    203 *
    204 * checks the state of a given pipe, and stores the state (1 = running,
    205 * 0 = paused) on the given pointer.
    206 *
    207 * called from trigger callback only
    208 */
    209static int vx_get_pipe_state(struct vx_core *chip, struct vx_pipe *pipe, int *state)
    210{
    211	int err;
    212	struct vx_rmh rmh;
    213
    214	vx_init_rmh(&rmh, CMD_PIPE_STATE);
    215	vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);
    216	err = vx_send_msg(chip, &rmh);
    217	if (! err)
    218		*state = (rmh.Stat[0] & (1 << pipe->number)) ? 1 : 0;
    219	return err;
    220}
    221
    222
    223/*
    224 * vx_query_hbuffer_size - query available h-buffer size in bytes
    225 * @pipe: the pipe to be checked
    226 *
    227 * return the available size on h-buffer in bytes,
    228 * or a negative error code.
    229 *
    230 * NOTE: calling this function always switches to the stream mode.
    231 *       you'll need to disconnect the host to get back to the
    232 *       normal mode.
    233 */
    234static int vx_query_hbuffer_size(struct vx_core *chip, struct vx_pipe *pipe)
    235{
    236	int result;
    237	struct vx_rmh rmh;
    238
    239	vx_init_rmh(&rmh, CMD_SIZE_HBUFFER);
    240	vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);
    241	if (pipe->is_capture)
    242		rmh.Cmd[0] |= 0x00000001;
    243	result = vx_send_msg(chip, &rmh);
    244	if (! result)
    245		result = rmh.Stat[0] & 0xffff;
    246	return result;
    247}
    248
    249
    250/*
    251 * vx_pipe_can_start - query whether a pipe is ready for start
    252 * @pipe: the pipe to be checked
    253 *
    254 * return 1 if ready, 0 if not ready, and negative value on error.
    255 *
    256 * called from trigger callback only
    257 */
    258static int vx_pipe_can_start(struct vx_core *chip, struct vx_pipe *pipe)
    259{
    260	int err;
    261	struct vx_rmh rmh;
    262        
    263	vx_init_rmh(&rmh, CMD_CAN_START_PIPE);
    264	vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);
    265	rmh.Cmd[0] |= 1;
    266
    267	err = vx_send_msg(chip, &rmh);
    268	if (! err) {
    269		if (rmh.Stat[0])
    270			err = 1;
    271	}
    272	return err;
    273}
    274
    275/*
    276 * vx_conf_pipe - tell the pipe to stand by and wait for IRQA.
    277 * @pipe: the pipe to be configured
    278 */
    279static int vx_conf_pipe(struct vx_core *chip, struct vx_pipe *pipe)
    280{
    281	struct vx_rmh rmh;
    282
    283	vx_init_rmh(&rmh, CMD_CONF_PIPE);
    284	if (pipe->is_capture)
    285		rmh.Cmd[0] |= COMMAND_RECORD_MASK;
    286	rmh.Cmd[1] = 1 << pipe->number;
    287	return vx_send_msg(chip, &rmh);
    288}
    289
    290/*
    291 * vx_send_irqa - trigger IRQA
    292 */
    293static int vx_send_irqa(struct vx_core *chip)
    294{
    295	struct vx_rmh rmh;
    296
    297	vx_init_rmh(&rmh, CMD_SEND_IRQA);
    298	return vx_send_msg(chip, &rmh);
    299}
    300
    301
    302#define MAX_WAIT_FOR_DSP        250
    303/*
    304 * vx boards do not support inter-card sync, besides
    305 * only 126 samples require to be prepared before a pipe can start
    306 */
    307#define CAN_START_DELAY         2	/* wait 2ms only before asking if the pipe is ready*/
    308#define WAIT_STATE_DELAY        2	/* wait 2ms after irqA was requested and check if the pipe state toggled*/
    309
    310/*
    311 * vx_toggle_pipe - start / pause a pipe
    312 * @pipe: the pipe to be triggered
    313 * @state: start = 1, pause = 0
    314 *
    315 * called from trigger callback only
    316 *
    317 */
    318static int vx_toggle_pipe(struct vx_core *chip, struct vx_pipe *pipe, int state)
    319{
    320	int err, i, cur_state;
    321
    322	/* Check the pipe is not already in the requested state */
    323	if (vx_get_pipe_state(chip, pipe, &cur_state) < 0)
    324		return -EBADFD;
    325	if (state == cur_state)
    326		return 0;
    327
    328	/* If a start is requested, ask the DSP to get prepared
    329	 * and wait for a positive acknowledge (when there are
    330	 * enough sound buffer for this pipe)
    331	 */
    332	if (state) {
    333		for (i = 0 ; i < MAX_WAIT_FOR_DSP; i++) {
    334			err = vx_pipe_can_start(chip, pipe);
    335			if (err > 0)
    336				break;
    337			/* Wait for a few, before asking again
    338			 * to avoid flooding the DSP with our requests
    339			 */
    340			mdelay(1);
    341		}
    342	}
    343    
    344	err = vx_conf_pipe(chip, pipe);
    345	if (err < 0)
    346		return err;
    347
    348	err = vx_send_irqa(chip);
    349	if (err < 0)
    350		return err;
    351    
    352	/* If it completes successfully, wait for the pipes
    353	 * reaching the expected state before returning
    354	 * Check one pipe only (since they are synchronous)
    355	 */
    356	for (i = 0; i < MAX_WAIT_FOR_DSP; i++) {
    357		err = vx_get_pipe_state(chip, pipe, &cur_state);
    358		if (err < 0 || cur_state == state)
    359			break;
    360		err = -EIO;
    361		mdelay(1);
    362	}
    363	return err < 0 ? -EIO : 0;
    364}
    365
    366    
    367/*
    368 * vx_stop_pipe - stop a pipe
    369 * @pipe: the pipe to be stopped
    370 *
    371 * called from trigger callback only
    372 */
    373static int vx_stop_pipe(struct vx_core *chip, struct vx_pipe *pipe)
    374{
    375	struct vx_rmh rmh;
    376	vx_init_rmh(&rmh, CMD_STOP_PIPE);
    377	vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);
    378	return vx_send_msg(chip, &rmh);
    379}
    380
    381
    382/*
    383 * vx_alloc_pipe - allocate a pipe and initialize the pipe instance
    384 * @capture: 0 = playback, 1 = capture operation
    385 * @audioid: the audio id to be assigned
    386 * @num_audio: number of audio channels
    387 * @pipep: the returned pipe instance
    388 *
    389 * return 0 on success, or a negative error code.
    390 */
    391static int vx_alloc_pipe(struct vx_core *chip, int capture,
    392			 int audioid, int num_audio,
    393			 struct vx_pipe **pipep)
    394{
    395	int err;
    396	struct vx_pipe *pipe;
    397	struct vx_rmh rmh;
    398	int data_mode;
    399
    400	*pipep = NULL;
    401	vx_init_rmh(&rmh, CMD_RES_PIPE);
    402	vx_set_pipe_cmd_params(&rmh, capture, audioid, num_audio);
    403#if 0	// NYI
    404	if (underrun_skip_sound)
    405		rmh.Cmd[0] |= BIT_SKIP_SOUND;
    406#endif	// NYI
    407	data_mode = (chip->uer_bits & IEC958_AES0_NONAUDIO) != 0;
    408	if (! capture && data_mode)
    409		rmh.Cmd[0] |= BIT_DATA_MODE;
    410	err = vx_send_msg(chip, &rmh);
    411	if (err < 0)
    412		return err;
    413
    414	/* initialize the pipe record */
    415	pipe = kzalloc(sizeof(*pipe), GFP_KERNEL);
    416	if (! pipe) {
    417		/* release the pipe */
    418		vx_init_rmh(&rmh, CMD_FREE_PIPE);
    419		vx_set_pipe_cmd_params(&rmh, capture, audioid, 0);
    420		vx_send_msg(chip, &rmh);
    421		return -ENOMEM;
    422	}
    423
    424	/* the pipe index should be identical with the audio index */
    425	pipe->number = audioid;
    426	pipe->is_capture = capture;
    427	pipe->channels = num_audio;
    428	pipe->differed_type = 0;
    429	pipe->pcx_time = 0;
    430	pipe->data_mode = data_mode;
    431	*pipep = pipe;
    432
    433	return 0;
    434}
    435
    436
    437/*
    438 * vx_free_pipe - release a pipe
    439 * @pipe: pipe to be released
    440 */
    441static int vx_free_pipe(struct vx_core *chip, struct vx_pipe *pipe)
    442{
    443	struct vx_rmh rmh;
    444
    445	vx_init_rmh(&rmh, CMD_FREE_PIPE);
    446	vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);
    447	vx_send_msg(chip, &rmh);
    448
    449	kfree(pipe);
    450	return 0;
    451}
    452
    453
    454/*
    455 * vx_start_stream - start the stream
    456 *
    457 * called from trigger callback only
    458 */
    459static int vx_start_stream(struct vx_core *chip, struct vx_pipe *pipe)
    460{
    461	struct vx_rmh rmh;
    462
    463	vx_init_rmh(&rmh, CMD_START_ONE_STREAM);
    464	vx_set_stream_cmd_params(&rmh, pipe->is_capture, pipe->number);
    465	vx_set_differed_time(chip, &rmh, pipe);
    466	return vx_send_msg(chip, &rmh);
    467}
    468
    469
    470/*
    471 * vx_stop_stream - stop the stream
    472 *
    473 * called from trigger callback only
    474 */
    475static int vx_stop_stream(struct vx_core *chip, struct vx_pipe *pipe)
    476{
    477	struct vx_rmh rmh;
    478
    479	vx_init_rmh(&rmh, CMD_STOP_STREAM);
    480	vx_set_stream_cmd_params(&rmh, pipe->is_capture, pipe->number);
    481	return vx_send_msg(chip, &rmh);
    482}
    483
    484
    485/*
    486 * playback hw information
    487 */
    488
    489static const struct snd_pcm_hardware vx_pcm_playback_hw = {
    490	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
    491				 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP_VALID /*|*/
    492				 /*SNDRV_PCM_INFO_RESUME*/),
    493	.formats =		(/*SNDRV_PCM_FMTBIT_U8 |*/
    494				 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_3LE),
    495	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
    496	.rate_min =		5000,
    497	.rate_max =		48000,
    498	.channels_min =		1,
    499	.channels_max =		2,
    500	.buffer_bytes_max =	(128*1024),
    501	.period_bytes_min =	126,
    502	.period_bytes_max =	(128*1024),
    503	.periods_min =		2,
    504	.periods_max =		VX_MAX_PERIODS,
    505	.fifo_size =		126,
    506};
    507
    508
    509/*
    510 * vx_pcm_playback_open - open callback for playback
    511 */
    512static int vx_pcm_playback_open(struct snd_pcm_substream *subs)
    513{
    514	struct snd_pcm_runtime *runtime = subs->runtime;
    515	struct vx_core *chip = snd_pcm_substream_chip(subs);
    516	struct vx_pipe *pipe = NULL;
    517	unsigned int audio;
    518	int err;
    519
    520	if (chip->chip_status & VX_STAT_IS_STALE)
    521		return -EBUSY;
    522
    523	audio = subs->pcm->device * 2;
    524	if (snd_BUG_ON(audio >= chip->audio_outs))
    525		return -EINVAL;
    526	
    527	/* playback pipe may have been already allocated for monitoring */
    528	pipe = chip->playback_pipes[audio];
    529	if (! pipe) {
    530		/* not allocated yet */
    531		err = vx_alloc_pipe(chip, 0, audio, 2, &pipe); /* stereo playback */
    532		if (err < 0)
    533			return err;
    534	}
    535	/* open for playback */
    536	pipe->references++;
    537
    538	pipe->substream = subs;
    539	chip->playback_pipes[audio] = pipe;
    540
    541	runtime->hw = vx_pcm_playback_hw;
    542	runtime->hw.period_bytes_min = chip->ibl.size;
    543	runtime->private_data = pipe;
    544
    545	/* align to 4 bytes (otherwise will be problematic when 24bit is used) */ 
    546	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 4);
    547	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4);
    548
    549	return 0;
    550}
    551
    552/*
    553 * vx_pcm_playback_close - close callback for playback
    554 */
    555static int vx_pcm_playback_close(struct snd_pcm_substream *subs)
    556{
    557	struct vx_core *chip = snd_pcm_substream_chip(subs);
    558	struct vx_pipe *pipe;
    559
    560	if (! subs->runtime->private_data)
    561		return -EINVAL;
    562
    563	pipe = subs->runtime->private_data;
    564
    565	if (--pipe->references == 0) {
    566		chip->playback_pipes[pipe->number] = NULL;
    567		vx_free_pipe(chip, pipe);
    568	}
    569
    570	return 0;
    571
    572}
    573
    574
    575/*
    576 * vx_notify_end_of_buffer - send "end-of-buffer" notifier at the given pipe
    577 * @pipe: the pipe to notify
    578 *
    579 * NB: call with a certain lock.
    580 */
    581static int vx_notify_end_of_buffer(struct vx_core *chip, struct vx_pipe *pipe)
    582{
    583	int err;
    584	struct vx_rmh rmh;  /* use a temporary rmh here */
    585
    586	/* Toggle Dsp Host Interface into Message mode */
    587	vx_send_rih_nolock(chip, IRQ_PAUSE_START_CONNECT);
    588	vx_init_rmh(&rmh, CMD_NOTIFY_END_OF_BUFFER);
    589	vx_set_stream_cmd_params(&rmh, 0, pipe->number);
    590	err = vx_send_msg_nolock(chip, &rmh);
    591	if (err < 0)
    592		return err;
    593	/* Toggle Dsp Host Interface back to sound transfer mode */
    594	vx_send_rih_nolock(chip, IRQ_PAUSE_START_CONNECT);
    595	return 0;
    596}
    597
    598/*
    599 * vx_pcm_playback_transfer_chunk - transfer a single chunk
    600 * @subs: substream
    601 * @pipe: the pipe to transfer
    602 * @size: chunk size in bytes
    603 *
    604 * transfer a single buffer chunk.  EOB notificaton is added after that.
    605 * called from the interrupt handler, too.
    606 *
    607 * return 0 if ok.
    608 */
    609static int vx_pcm_playback_transfer_chunk(struct vx_core *chip,
    610					  struct snd_pcm_runtime *runtime,
    611					  struct vx_pipe *pipe, int size)
    612{
    613	int space, err = 0;
    614
    615	space = vx_query_hbuffer_size(chip, pipe);
    616	if (space < 0) {
    617		/* disconnect the host, SIZE_HBUF command always switches to the stream mode */
    618		vx_send_rih(chip, IRQ_CONNECT_STREAM_NEXT);
    619		snd_printd("error hbuffer\n");
    620		return space;
    621	}
    622	if (space < size) {
    623		vx_send_rih(chip, IRQ_CONNECT_STREAM_NEXT);
    624		snd_printd("no enough hbuffer space %d\n", space);
    625		return -EIO; /* XRUN */
    626	}
    627		
    628	/* we don't need irqsave here, because this function
    629	 * is called from either trigger callback or irq handler
    630	 */
    631	mutex_lock(&chip->lock);
    632	vx_pseudo_dma_write(chip, runtime, pipe, size);
    633	err = vx_notify_end_of_buffer(chip, pipe);
    634	/* disconnect the host, SIZE_HBUF command always switches to the stream mode */
    635	vx_send_rih_nolock(chip, IRQ_CONNECT_STREAM_NEXT);
    636	mutex_unlock(&chip->lock);
    637	return err;
    638}
    639
    640/*
    641 * update the position of the given pipe.
    642 * pipe->position is updated and wrapped within the buffer size.
    643 * pipe->transferred is updated, too, but the size is not wrapped,
    644 * so that the caller can check the total transferred size later
    645 * (to call snd_pcm_period_elapsed).
    646 */
    647static int vx_update_pipe_position(struct vx_core *chip,
    648				   struct snd_pcm_runtime *runtime,
    649				   struct vx_pipe *pipe)
    650{
    651	struct vx_rmh rmh;
    652	int err, update;
    653	u64 count;
    654
    655	vx_init_rmh(&rmh, CMD_STREAM_SAMPLE_COUNT);
    656	vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);
    657	err = vx_send_msg(chip, &rmh);
    658	if (err < 0)
    659		return err;
    660
    661	count = ((u64)(rmh.Stat[0] & 0xfffff) << 24) | (u64)rmh.Stat[1];
    662	update = (int)(count - pipe->cur_count);
    663	pipe->cur_count = count;
    664	pipe->position += update;
    665	if (pipe->position >= (int)runtime->buffer_size)
    666		pipe->position %= runtime->buffer_size;
    667	pipe->transferred += update;
    668	return 0;
    669}
    670
    671/*
    672 * transfer the pending playback buffer data to DSP
    673 * called from interrupt handler
    674 */
    675static void vx_pcm_playback_transfer(struct vx_core *chip,
    676				     struct snd_pcm_substream *subs,
    677				     struct vx_pipe *pipe, int nchunks)
    678{
    679	int i, err;
    680	struct snd_pcm_runtime *runtime = subs->runtime;
    681
    682	if (! pipe->prepared || (chip->chip_status & VX_STAT_IS_STALE))
    683		return;
    684	for (i = 0; i < nchunks; i++) {
    685		err = vx_pcm_playback_transfer_chunk(chip, runtime, pipe,
    686						     chip->ibl.size);
    687		if (err < 0)
    688			return;
    689	}
    690}
    691
    692/*
    693 * update the playback position and call snd_pcm_period_elapsed() if necessary
    694 * called from interrupt handler
    695 */
    696static void vx_pcm_playback_update(struct vx_core *chip,
    697				   struct snd_pcm_substream *subs,
    698				   struct vx_pipe *pipe)
    699{
    700	int err;
    701	struct snd_pcm_runtime *runtime = subs->runtime;
    702
    703	if (pipe->running && ! (chip->chip_status & VX_STAT_IS_STALE)) {
    704		err = vx_update_pipe_position(chip, runtime, pipe);
    705		if (err < 0)
    706			return;
    707		if (pipe->transferred >= (int)runtime->period_size) {
    708			pipe->transferred %= runtime->period_size;
    709			snd_pcm_period_elapsed(subs);
    710		}
    711	}
    712}
    713
    714/*
    715 * vx_pcm_playback_trigger - trigger callback for playback
    716 */
    717static int vx_pcm_trigger(struct snd_pcm_substream *subs, int cmd)
    718{
    719	struct vx_core *chip = snd_pcm_substream_chip(subs);
    720	struct vx_pipe *pipe = subs->runtime->private_data;
    721	int err;
    722
    723	if (chip->chip_status & VX_STAT_IS_STALE)
    724		return -EBUSY;
    725		
    726	switch (cmd) {
    727	case SNDRV_PCM_TRIGGER_START:
    728	case SNDRV_PCM_TRIGGER_RESUME:
    729		if (! pipe->is_capture)
    730			vx_pcm_playback_transfer(chip, subs, pipe, 2);
    731		err = vx_start_stream(chip, pipe);
    732		if (err < 0) {
    733			pr_debug("vx: cannot start stream\n");
    734			return err;
    735		}
    736		err = vx_toggle_pipe(chip, pipe, 1);
    737		if (err < 0) {
    738			pr_debug("vx: cannot start pipe\n");
    739			vx_stop_stream(chip, pipe);
    740			return err;
    741		}
    742		chip->pcm_running++;
    743		pipe->running = 1;
    744		break;
    745	case SNDRV_PCM_TRIGGER_STOP:
    746	case SNDRV_PCM_TRIGGER_SUSPEND:
    747		vx_toggle_pipe(chip, pipe, 0);
    748		vx_stop_pipe(chip, pipe);
    749		vx_stop_stream(chip, pipe);
    750		chip->pcm_running--;
    751		pipe->running = 0;
    752		break;
    753	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
    754		err = vx_toggle_pipe(chip, pipe, 0);
    755		if (err < 0)
    756			return err;
    757		break;
    758	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
    759		err = vx_toggle_pipe(chip, pipe, 1);
    760		if (err < 0)
    761			return err;
    762		break;
    763	default:
    764		return -EINVAL;
    765	}
    766	return 0;
    767}
    768
    769/*
    770 * vx_pcm_playback_pointer - pointer callback for playback
    771 */
    772static snd_pcm_uframes_t vx_pcm_playback_pointer(struct snd_pcm_substream *subs)
    773{
    774	struct snd_pcm_runtime *runtime = subs->runtime;
    775	struct vx_pipe *pipe = runtime->private_data;
    776	return pipe->position;
    777}
    778
    779/*
    780 * vx_pcm_prepare - prepare callback for playback and capture
    781 */
    782static int vx_pcm_prepare(struct snd_pcm_substream *subs)
    783{
    784	struct vx_core *chip = snd_pcm_substream_chip(subs);
    785	struct snd_pcm_runtime *runtime = subs->runtime;
    786	struct vx_pipe *pipe = runtime->private_data;
    787	int err, data_mode;
    788	// int max_size, nchunks;
    789
    790	if (chip->chip_status & VX_STAT_IS_STALE)
    791		return -EBUSY;
    792
    793	data_mode = (chip->uer_bits & IEC958_AES0_NONAUDIO) != 0;
    794	if (data_mode != pipe->data_mode && ! pipe->is_capture) {
    795		/* IEC958 status (raw-mode) was changed */
    796		/* we reopen the pipe */
    797		struct vx_rmh rmh;
    798		snd_printdd(KERN_DEBUG "reopen the pipe with data_mode = %d\n", data_mode);
    799		vx_init_rmh(&rmh, CMD_FREE_PIPE);
    800		vx_set_pipe_cmd_params(&rmh, 0, pipe->number, 0);
    801		err = vx_send_msg(chip, &rmh);
    802		if (err < 0)
    803			return err;
    804		vx_init_rmh(&rmh, CMD_RES_PIPE);
    805		vx_set_pipe_cmd_params(&rmh, 0, pipe->number, pipe->channels);
    806		if (data_mode)
    807			rmh.Cmd[0] |= BIT_DATA_MODE;
    808		err = vx_send_msg(chip, &rmh);
    809		if (err < 0)
    810			return err;
    811		pipe->data_mode = data_mode;
    812	}
    813
    814	if (chip->pcm_running && chip->freq != runtime->rate) {
    815		snd_printk(KERN_ERR "vx: cannot set different clock %d "
    816			   "from the current %d\n", runtime->rate, chip->freq);
    817		return -EINVAL;
    818	}
    819	vx_set_clock(chip, runtime->rate);
    820
    821	err = vx_set_format(chip, pipe, runtime);
    822	if (err < 0)
    823		return err;
    824
    825	if (vx_is_pcmcia(chip)) {
    826		pipe->align = 2; /* 16bit word */
    827	} else {
    828		pipe->align = 4; /* 32bit word */
    829	}
    830
    831	pipe->buffer_bytes = frames_to_bytes(runtime, runtime->buffer_size);
    832	pipe->period_bytes = frames_to_bytes(runtime, runtime->period_size);
    833	pipe->hw_ptr = 0;
    834
    835	/* set the timestamp */
    836	vx_update_pipe_position(chip, runtime, pipe);
    837	/* clear again */
    838	pipe->transferred = 0;
    839	pipe->position = 0;
    840
    841	pipe->prepared = 1;
    842
    843	return 0;
    844}
    845
    846
    847/*
    848 * operators for PCM playback
    849 */
    850static const struct snd_pcm_ops vx_pcm_playback_ops = {
    851	.open =		vx_pcm_playback_open,
    852	.close =	vx_pcm_playback_close,
    853	.prepare =	vx_pcm_prepare,
    854	.trigger =	vx_pcm_trigger,
    855	.pointer =	vx_pcm_playback_pointer,
    856};
    857
    858
    859/*
    860 * playback hw information
    861 */
    862
    863static const struct snd_pcm_hardware vx_pcm_capture_hw = {
    864	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
    865				 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP_VALID /*|*/
    866				 /*SNDRV_PCM_INFO_RESUME*/),
    867	.formats =		(/*SNDRV_PCM_FMTBIT_U8 |*/
    868				 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_3LE),
    869	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
    870	.rate_min =		5000,
    871	.rate_max =		48000,
    872	.channels_min =		1,
    873	.channels_max =		2,
    874	.buffer_bytes_max =	(128*1024),
    875	.period_bytes_min =	126,
    876	.period_bytes_max =	(128*1024),
    877	.periods_min =		2,
    878	.periods_max =		VX_MAX_PERIODS,
    879	.fifo_size =		126,
    880};
    881
    882
    883/*
    884 * vx_pcm_capture_open - open callback for capture
    885 */
    886static int vx_pcm_capture_open(struct snd_pcm_substream *subs)
    887{
    888	struct snd_pcm_runtime *runtime = subs->runtime;
    889	struct vx_core *chip = snd_pcm_substream_chip(subs);
    890	struct vx_pipe *pipe;
    891	struct vx_pipe *pipe_out_monitoring = NULL;
    892	unsigned int audio;
    893	int err;
    894
    895	if (chip->chip_status & VX_STAT_IS_STALE)
    896		return -EBUSY;
    897
    898	audio = subs->pcm->device * 2;
    899	if (snd_BUG_ON(audio >= chip->audio_ins))
    900		return -EINVAL;
    901	err = vx_alloc_pipe(chip, 1, audio, 2, &pipe);
    902	if (err < 0)
    903		return err;
    904	pipe->substream = subs;
    905	chip->capture_pipes[audio] = pipe;
    906
    907	/* check if monitoring is needed */
    908	if (chip->audio_monitor_active[audio]) {
    909		pipe_out_monitoring = chip->playback_pipes[audio];
    910		if (! pipe_out_monitoring) {
    911			/* allocate a pipe */
    912			err = vx_alloc_pipe(chip, 0, audio, 2, &pipe_out_monitoring);
    913			if (err < 0)
    914				return err;
    915			chip->playback_pipes[audio] = pipe_out_monitoring;
    916		}
    917		pipe_out_monitoring->references++;
    918		/* 
    919		   if an output pipe is available, it's audios still may need to be 
    920		   unmuted. hence we'll have to call a mixer entry point.
    921		*/
    922		vx_set_monitor_level(chip, audio, chip->audio_monitor[audio],
    923				     chip->audio_monitor_active[audio]);
    924		/* assuming stereo */
    925		vx_set_monitor_level(chip, audio+1, chip->audio_monitor[audio+1],
    926				     chip->audio_monitor_active[audio+1]); 
    927	}
    928
    929	pipe->monitoring_pipe = pipe_out_monitoring; /* default value NULL */
    930
    931	runtime->hw = vx_pcm_capture_hw;
    932	runtime->hw.period_bytes_min = chip->ibl.size;
    933	runtime->private_data = pipe;
    934
    935	/* align to 4 bytes (otherwise will be problematic when 24bit is used) */ 
    936	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 4);
    937	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4);
    938
    939	return 0;
    940}
    941
    942/*
    943 * vx_pcm_capture_close - close callback for capture
    944 */
    945static int vx_pcm_capture_close(struct snd_pcm_substream *subs)
    946{
    947	struct vx_core *chip = snd_pcm_substream_chip(subs);
    948	struct vx_pipe *pipe;
    949	struct vx_pipe *pipe_out_monitoring;
    950	
    951	if (! subs->runtime->private_data)
    952		return -EINVAL;
    953	pipe = subs->runtime->private_data;
    954	chip->capture_pipes[pipe->number] = NULL;
    955
    956	pipe_out_monitoring = pipe->monitoring_pipe;
    957
    958	/*
    959	  if an output pipe is attached to this input, 
    960	  check if it needs to be released.
    961	*/
    962	if (pipe_out_monitoring) {
    963		if (--pipe_out_monitoring->references == 0) {
    964			vx_free_pipe(chip, pipe_out_monitoring);
    965			chip->playback_pipes[pipe->number] = NULL;
    966			pipe->monitoring_pipe = NULL;
    967		}
    968	}
    969	
    970	vx_free_pipe(chip, pipe);
    971	return 0;
    972}
    973
    974
    975
    976#define DMA_READ_ALIGN	6	/* hardware alignment for read */
    977
    978/*
    979 * vx_pcm_capture_update - update the capture buffer
    980 */
    981static void vx_pcm_capture_update(struct vx_core *chip, struct snd_pcm_substream *subs,
    982				  struct vx_pipe *pipe)
    983{
    984	int size, space, count;
    985	struct snd_pcm_runtime *runtime = subs->runtime;
    986
    987	if (!pipe->running || (chip->chip_status & VX_STAT_IS_STALE))
    988		return;
    989
    990	size = runtime->buffer_size - snd_pcm_capture_avail(runtime);
    991	if (! size)
    992		return;
    993	size = frames_to_bytes(runtime, size);
    994	space = vx_query_hbuffer_size(chip, pipe);
    995	if (space < 0)
    996		goto _error;
    997	if (size > space)
    998		size = space;
    999	size = (size / 3) * 3; /* align to 3 bytes */
   1000	if (size < DMA_READ_ALIGN)
   1001		goto _error;
   1002
   1003	/* keep the last 6 bytes, they will be read after disconnection */
   1004	count = size - DMA_READ_ALIGN;
   1005	/* read bytes until the current pointer reaches to the aligned position
   1006	 * for word-transfer
   1007	 */
   1008	while (count > 0) {
   1009		if ((pipe->hw_ptr % pipe->align) == 0)
   1010			break;
   1011		if (vx_wait_for_rx_full(chip) < 0)
   1012			goto _error;
   1013		vx_pcm_read_per_bytes(chip, runtime, pipe);
   1014		count -= 3;
   1015	}
   1016	if (count > 0) {
   1017		/* ok, let's accelerate! */
   1018		int align = pipe->align * 3;
   1019		space = (count / align) * align;
   1020		if (space > 0) {
   1021			vx_pseudo_dma_read(chip, runtime, pipe, space);
   1022			count -= space;
   1023		}
   1024	}
   1025	/* read the rest of bytes */
   1026	while (count > 0) {
   1027		if (vx_wait_for_rx_full(chip) < 0)
   1028			goto _error;
   1029		vx_pcm_read_per_bytes(chip, runtime, pipe);
   1030		count -= 3;
   1031	}
   1032	/* disconnect the host, SIZE_HBUF command always switches to the stream mode */
   1033	vx_send_rih(chip, IRQ_CONNECT_STREAM_NEXT);
   1034	/* read the last pending 6 bytes */
   1035	count = DMA_READ_ALIGN;
   1036	while (count > 0) {
   1037		vx_pcm_read_per_bytes(chip, runtime, pipe);
   1038		count -= 3;
   1039	}
   1040	/* update the position */
   1041	pipe->transferred += size;
   1042	if (pipe->transferred >= pipe->period_bytes) {
   1043		pipe->transferred %= pipe->period_bytes;
   1044		snd_pcm_period_elapsed(subs);
   1045	}
   1046	return;
   1047
   1048 _error:
   1049	/* disconnect the host, SIZE_HBUF command always switches to the stream mode */
   1050	vx_send_rih(chip, IRQ_CONNECT_STREAM_NEXT);
   1051	return;
   1052}
   1053
   1054/*
   1055 * vx_pcm_capture_pointer - pointer callback for capture
   1056 */
   1057static snd_pcm_uframes_t vx_pcm_capture_pointer(struct snd_pcm_substream *subs)
   1058{
   1059	struct snd_pcm_runtime *runtime = subs->runtime;
   1060	struct vx_pipe *pipe = runtime->private_data;
   1061	return bytes_to_frames(runtime, pipe->hw_ptr);
   1062}
   1063
   1064/*
   1065 * operators for PCM capture
   1066 */
   1067static const struct snd_pcm_ops vx_pcm_capture_ops = {
   1068	.open =		vx_pcm_capture_open,
   1069	.close =	vx_pcm_capture_close,
   1070	.prepare =	vx_pcm_prepare,
   1071	.trigger =	vx_pcm_trigger,
   1072	.pointer =	vx_pcm_capture_pointer,
   1073};
   1074
   1075
   1076/*
   1077 * interrupt handler for pcm streams
   1078 */
   1079void vx_pcm_update_intr(struct vx_core *chip, unsigned int events)
   1080{
   1081	unsigned int i;
   1082	struct vx_pipe *pipe;
   1083
   1084#define EVENT_MASK	(END_OF_BUFFER_EVENTS_PENDING|ASYNC_EVENTS_PENDING)
   1085
   1086	if (events & EVENT_MASK) {
   1087		vx_init_rmh(&chip->irq_rmh, CMD_ASYNC);
   1088		if (events & ASYNC_EVENTS_PENDING)
   1089			chip->irq_rmh.Cmd[0] |= 0x00000001;	/* SEL_ASYNC_EVENTS */
   1090		if (events & END_OF_BUFFER_EVENTS_PENDING)
   1091			chip->irq_rmh.Cmd[0] |= 0x00000002;	/* SEL_END_OF_BUF_EVENTS */
   1092
   1093		if (vx_send_msg(chip, &chip->irq_rmh) < 0) {
   1094			snd_printdd(KERN_ERR "msg send error!!\n");
   1095			return;
   1096		}
   1097
   1098		i = 1;
   1099		while (i < chip->irq_rmh.LgStat) {
   1100			int p, buf, capture, eob;
   1101			p = chip->irq_rmh.Stat[i] & MASK_FIRST_FIELD;
   1102			capture = (chip->irq_rmh.Stat[i] & 0x400000) ? 1 : 0;
   1103			eob = (chip->irq_rmh.Stat[i] & 0x800000) ? 1 : 0;
   1104			i++;
   1105			if (events & ASYNC_EVENTS_PENDING)
   1106				i++;
   1107			buf = 1; /* force to transfer */
   1108			if (events & END_OF_BUFFER_EVENTS_PENDING) {
   1109				if (eob)
   1110					buf = chip->irq_rmh.Stat[i];
   1111				i++;
   1112			}
   1113			if (capture)
   1114				continue;
   1115			if (snd_BUG_ON(p < 0 || p >= chip->audio_outs))
   1116				continue;
   1117			pipe = chip->playback_pipes[p];
   1118			if (pipe && pipe->substream) {
   1119				vx_pcm_playback_update(chip, pipe->substream, pipe);
   1120				vx_pcm_playback_transfer(chip, pipe->substream, pipe, buf);
   1121			}
   1122		}
   1123	}
   1124
   1125	/* update the capture pcm pointers as frequently as possible */
   1126	for (i = 0; i < chip->audio_ins; i++) {
   1127		pipe = chip->capture_pipes[i];
   1128		if (pipe && pipe->substream)
   1129			vx_pcm_capture_update(chip, pipe->substream, pipe);
   1130	}
   1131}
   1132
   1133
   1134/*
   1135 * vx_init_audio_io - check the available audio i/o and allocate pipe arrays
   1136 */
   1137static int vx_init_audio_io(struct vx_core *chip)
   1138{
   1139	struct vx_rmh rmh;
   1140	int preferred;
   1141
   1142	vx_init_rmh(&rmh, CMD_SUPPORTED);
   1143	if (vx_send_msg(chip, &rmh) < 0) {
   1144		snd_printk(KERN_ERR "vx: cannot get the supported audio data\n");
   1145		return -ENXIO;
   1146	}
   1147
   1148	chip->audio_outs = rmh.Stat[0] & MASK_FIRST_FIELD;
   1149	chip->audio_ins = (rmh.Stat[0] >> (FIELD_SIZE*2)) & MASK_FIRST_FIELD;
   1150	chip->audio_info = rmh.Stat[1];
   1151
   1152	/* allocate pipes */
   1153	chip->playback_pipes = kcalloc(chip->audio_outs, sizeof(struct vx_pipe *), GFP_KERNEL);
   1154	if (!chip->playback_pipes)
   1155		return -ENOMEM;
   1156	chip->capture_pipes = kcalloc(chip->audio_ins, sizeof(struct vx_pipe *), GFP_KERNEL);
   1157	if (!chip->capture_pipes) {
   1158		kfree(chip->playback_pipes);
   1159		return -ENOMEM;
   1160	}
   1161
   1162	preferred = chip->ibl.size;
   1163	chip->ibl.size = 0;
   1164	vx_set_ibl(chip, &chip->ibl); /* query the info */
   1165	if (preferred > 0) {
   1166		chip->ibl.size = roundup(preferred, chip->ibl.granularity);
   1167		if (chip->ibl.size > chip->ibl.max_size)
   1168			chip->ibl.size = chip->ibl.max_size;
   1169	} else
   1170		chip->ibl.size = chip->ibl.min_size; /* set to the minimum */
   1171	vx_set_ibl(chip, &chip->ibl);
   1172
   1173	return 0;
   1174}
   1175
   1176
   1177/*
   1178 * free callback for pcm
   1179 */
   1180static void snd_vx_pcm_free(struct snd_pcm *pcm)
   1181{
   1182	struct vx_core *chip = pcm->private_data;
   1183	chip->pcm[pcm->device] = NULL;
   1184	kfree(chip->playback_pipes);
   1185	chip->playback_pipes = NULL;
   1186	kfree(chip->capture_pipes);
   1187	chip->capture_pipes = NULL;
   1188}
   1189
   1190/*
   1191 * snd_vx_pcm_new - create and initialize a pcm
   1192 */
   1193int snd_vx_pcm_new(struct vx_core *chip)
   1194{
   1195	struct snd_pcm *pcm;
   1196	unsigned int i;
   1197	int err;
   1198
   1199	err = vx_init_audio_io(chip);
   1200	if (err < 0)
   1201		return err;
   1202
   1203	for (i = 0; i < chip->hw->num_codecs; i++) {
   1204		unsigned int outs, ins;
   1205		outs = chip->audio_outs > i * 2 ? 1 : 0;
   1206		ins = chip->audio_ins > i * 2 ? 1 : 0;
   1207		if (! outs && ! ins)
   1208			break;
   1209		err = snd_pcm_new(chip->card, "VX PCM", i,
   1210				  outs, ins, &pcm);
   1211		if (err < 0)
   1212			return err;
   1213		if (outs)
   1214			snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &vx_pcm_playback_ops);
   1215		if (ins)
   1216			snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &vx_pcm_capture_ops);
   1217		snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC,
   1218					       snd_dma_continuous_data(GFP_KERNEL | GFP_DMA32),
   1219					       0, 0);
   1220
   1221		pcm->private_data = chip;
   1222		pcm->private_free = snd_vx_pcm_free;
   1223		pcm->info_flags = 0;
   1224		pcm->nonatomic = true;
   1225		strcpy(pcm->name, chip->card->shortname);
   1226		chip->pcm[i] = pcm;
   1227	}
   1228
   1229	return 0;
   1230}