brintos

brintos / linux-shallow public Read only

0
0
Text · 31.6 KiB · cbc77ca Raw
1235 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Driver for Digigram VX soundcards4 *5 * PCM part6 *7 * Copyright (c) 2002,2003 by Takashi Iwai <tiwai@suse.de>8 *9 * STRATEGY10 *  for playback, we send series of "chunks", which size is equal with the11 *  IBL size, typically 126 samples.  at each end of chunk, the end-of-buffer12 *  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() will17 *  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 each21 *  interrupt (capture stream has no EOB notification).  if the pending22 *  data is accumulated to the period size, snd_pcm_period_elapsed() is23 *  called and the pointer is updated.24 *25 *  the current point of read buffer is kept in pipe->hw_ptr.  note that26 *  this is in bytes.27 *28 * TODO29 *  - 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 set70 * @dsp_time: the pointer for RMH status time array71 */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 specified81 * @rmh: the rmh record to modify82 * @pipe: the pipe to be checked83 *84 * if the pipe is programmed with the differed time, set the DSP time85 * 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 command120 * @pipe: the affected pipe121 * @data: format bitmask122 */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 pipe145 * @pipe: the affected pipe146 * @runtime: pcm runtime instance to be referred147 *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 size178 */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	dev_dbg(chip->card->dev,194		"%s: size = %d, max = %d, min = %d, gran = %d\n",195		__func__, info->size, info->max_size, info->min_size,196		info->granularity);197	return 0;198}199 200 201/*202 * vx_get_pipe_state - get the state of a pipe203 * @pipe: the pipe to be checked204 * @state: the pointer for the returned state205 *206 * checks the state of a given pipe, and stores the state (1 = running,207 * 0 = paused) on the given pointer.208 *209 * called from trigger callback only210 */211static int vx_get_pipe_state(struct vx_core *chip, struct vx_pipe *pipe, int *state)212{213	int err;214	struct vx_rmh rmh;215 216	vx_init_rmh(&rmh, CMD_PIPE_STATE);217	vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);218	err = vx_send_msg(chip, &rmh);219	if (! err)220		*state = (rmh.Stat[0] & (1 << pipe->number)) ? 1 : 0;221	return err;222}223 224 225/*226 * vx_query_hbuffer_size - query available h-buffer size in bytes227 * @pipe: the pipe to be checked228 *229 * return the available size on h-buffer in bytes,230 * or a negative error code.231 *232 * NOTE: calling this function always switches to the stream mode.233 *       you'll need to disconnect the host to get back to the234 *       normal mode.235 */236static int vx_query_hbuffer_size(struct vx_core *chip, struct vx_pipe *pipe)237{238	int result;239	struct vx_rmh rmh;240 241	vx_init_rmh(&rmh, CMD_SIZE_HBUFFER);242	vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);243	if (pipe->is_capture)244		rmh.Cmd[0] |= 0x00000001;245	result = vx_send_msg(chip, &rmh);246	if (! result)247		result = rmh.Stat[0] & 0xffff;248	return result;249}250 251 252/*253 * vx_pipe_can_start - query whether a pipe is ready for start254 * @pipe: the pipe to be checked255 *256 * return 1 if ready, 0 if not ready, and negative value on error.257 *258 * called from trigger callback only259 */260static int vx_pipe_can_start(struct vx_core *chip, struct vx_pipe *pipe)261{262	int err;263	struct vx_rmh rmh;264        265	vx_init_rmh(&rmh, CMD_CAN_START_PIPE);266	vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);267	rmh.Cmd[0] |= 1;268 269	err = vx_send_msg(chip, &rmh);270	if (! err) {271		if (rmh.Stat[0])272			err = 1;273	}274	return err;275}276 277/*278 * vx_conf_pipe - tell the pipe to stand by and wait for IRQA.279 * @pipe: the pipe to be configured280 */281static int vx_conf_pipe(struct vx_core *chip, struct vx_pipe *pipe)282{283	struct vx_rmh rmh;284 285	vx_init_rmh(&rmh, CMD_CONF_PIPE);286	if (pipe->is_capture)287		rmh.Cmd[0] |= COMMAND_RECORD_MASK;288	rmh.Cmd[1] = 1 << pipe->number;289	return vx_send_msg(chip, &rmh);290}291 292/*293 * vx_send_irqa - trigger IRQA294 */295static int vx_send_irqa(struct vx_core *chip)296{297	struct vx_rmh rmh;298 299	vx_init_rmh(&rmh, CMD_SEND_IRQA);300	return vx_send_msg(chip, &rmh);301}302 303 304#define MAX_WAIT_FOR_DSP        250305/*306 * vx boards do not support inter-card sync, besides307 * only 126 samples require to be prepared before a pipe can start308 */309#define CAN_START_DELAY         2	/* wait 2ms only before asking if the pipe is ready*/310#define WAIT_STATE_DELAY        2	/* wait 2ms after irqA was requested and check if the pipe state toggled*/311 312/*313 * vx_toggle_pipe - start / pause a pipe314 * @pipe: the pipe to be triggered315 * @state: start = 1, pause = 0316 *317 * called from trigger callback only318 *319 */320static int vx_toggle_pipe(struct vx_core *chip, struct vx_pipe *pipe, int state)321{322	int err, i, cur_state;323 324	/* Check the pipe is not already in the requested state */325	if (vx_get_pipe_state(chip, pipe, &cur_state) < 0)326		return -EBADFD;327	if (state == cur_state)328		return 0;329 330	/* If a start is requested, ask the DSP to get prepared331	 * and wait for a positive acknowledge (when there are332	 * enough sound buffer for this pipe)333	 */334	if (state) {335		for (i = 0 ; i < MAX_WAIT_FOR_DSP; i++) {336			err = vx_pipe_can_start(chip, pipe);337			if (err > 0)338				break;339			/* Wait for a few, before asking again340			 * to avoid flooding the DSP with our requests341			 */342			mdelay(1);343		}344	}345    346	err = vx_conf_pipe(chip, pipe);347	if (err < 0)348		return err;349 350	err = vx_send_irqa(chip);351	if (err < 0)352		return err;353    354	/* If it completes successfully, wait for the pipes355	 * reaching the expected state before returning356	 * Check one pipe only (since they are synchronous)357	 */358	for (i = 0; i < MAX_WAIT_FOR_DSP; i++) {359		err = vx_get_pipe_state(chip, pipe, &cur_state);360		if (err < 0 || cur_state == state)361			break;362		err = -EIO;363		mdelay(1);364	}365	return err < 0 ? -EIO : 0;366}367 368    369/*370 * vx_stop_pipe - stop a pipe371 * @pipe: the pipe to be stopped372 *373 * called from trigger callback only374 */375static int vx_stop_pipe(struct vx_core *chip, struct vx_pipe *pipe)376{377	struct vx_rmh rmh;378	vx_init_rmh(&rmh, CMD_STOP_PIPE);379	vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);380	return vx_send_msg(chip, &rmh);381}382 383 384/*385 * vx_alloc_pipe - allocate a pipe and initialize the pipe instance386 * @capture: 0 = playback, 1 = capture operation387 * @audioid: the audio id to be assigned388 * @num_audio: number of audio channels389 * @pipep: the returned pipe instance390 *391 * return 0 on success, or a negative error code.392 */393static int vx_alloc_pipe(struct vx_core *chip, int capture,394			 int audioid, int num_audio,395			 struct vx_pipe **pipep)396{397	int err;398	struct vx_pipe *pipe;399	struct vx_rmh rmh;400	int data_mode;401 402	*pipep = NULL;403	vx_init_rmh(&rmh, CMD_RES_PIPE);404	vx_set_pipe_cmd_params(&rmh, capture, audioid, num_audio);405#if 0	// NYI406	if (underrun_skip_sound)407		rmh.Cmd[0] |= BIT_SKIP_SOUND;408#endif	// NYI409	data_mode = (chip->uer_bits & IEC958_AES0_NONAUDIO) != 0;410	if (! capture && data_mode)411		rmh.Cmd[0] |= BIT_DATA_MODE;412	err = vx_send_msg(chip, &rmh);413	if (err < 0)414		return err;415 416	/* initialize the pipe record */417	pipe = kzalloc(sizeof(*pipe), GFP_KERNEL);418	if (! pipe) {419		/* release the pipe */420		vx_init_rmh(&rmh, CMD_FREE_PIPE);421		vx_set_pipe_cmd_params(&rmh, capture, audioid, 0);422		vx_send_msg(chip, &rmh);423		return -ENOMEM;424	}425 426	/* the pipe index should be identical with the audio index */427	pipe->number = audioid;428	pipe->is_capture = capture;429	pipe->channels = num_audio;430	pipe->differed_type = 0;431	pipe->pcx_time = 0;432	pipe->data_mode = data_mode;433	*pipep = pipe;434 435	return 0;436}437 438 439/*440 * vx_free_pipe - release a pipe441 * @pipe: pipe to be released442 */443static int vx_free_pipe(struct vx_core *chip, struct vx_pipe *pipe)444{445	struct vx_rmh rmh;446 447	vx_init_rmh(&rmh, CMD_FREE_PIPE);448	vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);449	vx_send_msg(chip, &rmh);450 451	kfree(pipe);452	return 0;453}454 455 456/*457 * vx_start_stream - start the stream458 *459 * called from trigger callback only460 */461static int vx_start_stream(struct vx_core *chip, struct vx_pipe *pipe)462{463	struct vx_rmh rmh;464 465	vx_init_rmh(&rmh, CMD_START_ONE_STREAM);466	vx_set_stream_cmd_params(&rmh, pipe->is_capture, pipe->number);467	vx_set_differed_time(chip, &rmh, pipe);468	return vx_send_msg(chip, &rmh);469}470 471 472/*473 * vx_stop_stream - stop the stream474 *475 * called from trigger callback only476 */477static int vx_stop_stream(struct vx_core *chip, struct vx_pipe *pipe)478{479	struct vx_rmh rmh;480 481	vx_init_rmh(&rmh, CMD_STOP_STREAM);482	vx_set_stream_cmd_params(&rmh, pipe->is_capture, pipe->number);483	return vx_send_msg(chip, &rmh);484}485 486 487/*488 * playback hw information489 */490 491static const struct snd_pcm_hardware vx_pcm_playback_hw = {492	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |493				 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP_VALID /*|*/494				 /*SNDRV_PCM_INFO_RESUME*/),495	.formats =		(/*SNDRV_PCM_FMTBIT_U8 |*/496				 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_3LE),497	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,498	.rate_min =		5000,499	.rate_max =		48000,500	.channels_min =		1,501	.channels_max =		2,502	.buffer_bytes_max =	(128*1024),503	.period_bytes_min =	126,504	.period_bytes_max =	(128*1024),505	.periods_min =		2,506	.periods_max =		VX_MAX_PERIODS,507	.fifo_size =		126,508};509 510 511/*512 * vx_pcm_playback_open - open callback for playback513 */514static int vx_pcm_playback_open(struct snd_pcm_substream *subs)515{516	struct snd_pcm_runtime *runtime = subs->runtime;517	struct vx_core *chip = snd_pcm_substream_chip(subs);518	struct vx_pipe *pipe = NULL;519	unsigned int audio;520	int err;521 522	if (chip->chip_status & VX_STAT_IS_STALE)523		return -EBUSY;524 525	audio = subs->pcm->device * 2;526	if (snd_BUG_ON(audio >= chip->audio_outs))527		return -EINVAL;528	529	/* playback pipe may have been already allocated for monitoring */530	pipe = chip->playback_pipes[audio];531	if (! pipe) {532		/* not allocated yet */533		err = vx_alloc_pipe(chip, 0, audio, 2, &pipe); /* stereo playback */534		if (err < 0)535			return err;536	}537	/* open for playback */538	pipe->references++;539 540	pipe->substream = subs;541	chip->playback_pipes[audio] = pipe;542 543	runtime->hw = vx_pcm_playback_hw;544	runtime->hw.period_bytes_min = chip->ibl.size;545	runtime->private_data = pipe;546 547	/* align to 4 bytes (otherwise will be problematic when 24bit is used) */ 548	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 4);549	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4);550 551	return 0;552}553 554/*555 * vx_pcm_playback_close - close callback for playback556 */557static int vx_pcm_playback_close(struct snd_pcm_substream *subs)558{559	struct vx_core *chip = snd_pcm_substream_chip(subs);560	struct vx_pipe *pipe;561 562	if (! subs->runtime->private_data)563		return -EINVAL;564 565	pipe = subs->runtime->private_data;566 567	if (--pipe->references == 0) {568		chip->playback_pipes[pipe->number] = NULL;569		vx_free_pipe(chip, pipe);570	}571 572	return 0;573 574}575 576 577/*578 * vx_notify_end_of_buffer - send "end-of-buffer" notifier at the given pipe579 * @pipe: the pipe to notify580 *581 * NB: call with a certain lock.582 */583static int vx_notify_end_of_buffer(struct vx_core *chip, struct vx_pipe *pipe)584{585	int err;586	struct vx_rmh rmh;  /* use a temporary rmh here */587 588	/* Toggle Dsp Host Interface into Message mode */589	vx_send_rih_nolock(chip, IRQ_PAUSE_START_CONNECT);590	vx_init_rmh(&rmh, CMD_NOTIFY_END_OF_BUFFER);591	vx_set_stream_cmd_params(&rmh, 0, pipe->number);592	err = vx_send_msg_nolock(chip, &rmh);593	if (err < 0)594		return err;595	/* Toggle Dsp Host Interface back to sound transfer mode */596	vx_send_rih_nolock(chip, IRQ_PAUSE_START_CONNECT);597	return 0;598}599 600/*601 * vx_pcm_playback_transfer_chunk - transfer a single chunk602 * @subs: substream603 * @pipe: the pipe to transfer604 * @size: chunk size in bytes605 *606 * transfer a single buffer chunk.  EOB notificaton is added after that.607 * called from the interrupt handler, too.608 *609 * return 0 if ok.610 */611static int vx_pcm_playback_transfer_chunk(struct vx_core *chip,612					  struct snd_pcm_runtime *runtime,613					  struct vx_pipe *pipe, int size)614{615	int space, err = 0;616 617	space = vx_query_hbuffer_size(chip, pipe);618	if (space < 0) {619		/* disconnect the host, SIZE_HBUF command always switches to the stream mode */620		vx_send_rih(chip, IRQ_CONNECT_STREAM_NEXT);621		dev_dbg(chip->card->dev, "error hbuffer\n");622		return space;623	}624	if (space < size) {625		vx_send_rih(chip, IRQ_CONNECT_STREAM_NEXT);626		dev_dbg(chip->card->dev, "no enough hbuffer space %d\n", space);627		return -EIO; /* XRUN */628	}629		630	/* we don't need irqsave here, because this function631	 * is called from either trigger callback or irq handler632	 */633	mutex_lock(&chip->lock);634	vx_pseudo_dma_write(chip, runtime, pipe, size);635	err = vx_notify_end_of_buffer(chip, pipe);636	/* disconnect the host, SIZE_HBUF command always switches to the stream mode */637	vx_send_rih_nolock(chip, IRQ_CONNECT_STREAM_NEXT);638	mutex_unlock(&chip->lock);639	return err;640}641 642/*643 * update the position of the given pipe.644 * pipe->position is updated and wrapped within the buffer size.645 * pipe->transferred is updated, too, but the size is not wrapped,646 * so that the caller can check the total transferred size later647 * (to call snd_pcm_period_elapsed).648 */649static int vx_update_pipe_position(struct vx_core *chip,650				   struct snd_pcm_runtime *runtime,651				   struct vx_pipe *pipe)652{653	struct vx_rmh rmh;654	int err, update;655	u64 count;656 657	vx_init_rmh(&rmh, CMD_STREAM_SAMPLE_COUNT);658	vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);659	err = vx_send_msg(chip, &rmh);660	if (err < 0)661		return err;662 663	count = ((u64)(rmh.Stat[0] & 0xfffff) << 24) | (u64)rmh.Stat[1];664	update = (int)(count - pipe->cur_count);665	pipe->cur_count = count;666	pipe->position += update;667	if (pipe->position >= (int)runtime->buffer_size)668		pipe->position %= runtime->buffer_size;669	pipe->transferred += update;670	return 0;671}672 673/*674 * transfer the pending playback buffer data to DSP675 * called from interrupt handler676 */677static void vx_pcm_playback_transfer(struct vx_core *chip,678				     struct snd_pcm_substream *subs,679				     struct vx_pipe *pipe, int nchunks)680{681	int i, err;682	struct snd_pcm_runtime *runtime = subs->runtime;683 684	if (! pipe->prepared || (chip->chip_status & VX_STAT_IS_STALE))685		return;686	for (i = 0; i < nchunks; i++) {687		err = vx_pcm_playback_transfer_chunk(chip, runtime, pipe,688						     chip->ibl.size);689		if (err < 0)690			return;691	}692}693 694/*695 * update the playback position and call snd_pcm_period_elapsed() if necessary696 * called from interrupt handler697 */698static void vx_pcm_playback_update(struct vx_core *chip,699				   struct snd_pcm_substream *subs,700				   struct vx_pipe *pipe)701{702	int err;703	struct snd_pcm_runtime *runtime = subs->runtime;704 705	if (pipe->running && ! (chip->chip_status & VX_STAT_IS_STALE)) {706		err = vx_update_pipe_position(chip, runtime, pipe);707		if (err < 0)708			return;709		if (pipe->transferred >= (int)runtime->period_size) {710			pipe->transferred %= runtime->period_size;711			snd_pcm_period_elapsed(subs);712		}713	}714}715 716/*717 * vx_pcm_playback_trigger - trigger callback for playback718 */719static int vx_pcm_trigger(struct snd_pcm_substream *subs, int cmd)720{721	struct vx_core *chip = snd_pcm_substream_chip(subs);722	struct vx_pipe *pipe = subs->runtime->private_data;723	int err;724 725	if (chip->chip_status & VX_STAT_IS_STALE)726		return -EBUSY;727		728	switch (cmd) {729	case SNDRV_PCM_TRIGGER_START:730	case SNDRV_PCM_TRIGGER_RESUME:731		if (! pipe->is_capture)732			vx_pcm_playback_transfer(chip, subs, pipe, 2);733		err = vx_start_stream(chip, pipe);734		if (err < 0) {735			pr_debug("vx: cannot start stream\n");736			return err;737		}738		err = vx_toggle_pipe(chip, pipe, 1);739		if (err < 0) {740			pr_debug("vx: cannot start pipe\n");741			vx_stop_stream(chip, pipe);742			return err;743		}744		chip->pcm_running++;745		pipe->running = 1;746		break;747	case SNDRV_PCM_TRIGGER_STOP:748	case SNDRV_PCM_TRIGGER_SUSPEND:749		vx_toggle_pipe(chip, pipe, 0);750		vx_stop_pipe(chip, pipe);751		vx_stop_stream(chip, pipe);752		chip->pcm_running--;753		pipe->running = 0;754		break;755	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:756		err = vx_toggle_pipe(chip, pipe, 0);757		if (err < 0)758			return err;759		break;760	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:761		err = vx_toggle_pipe(chip, pipe, 1);762		if (err < 0)763			return err;764		break;765	default:766		return -EINVAL;767	}768	return 0;769}770 771/*772 * vx_pcm_playback_pointer - pointer callback for playback773 */774static snd_pcm_uframes_t vx_pcm_playback_pointer(struct snd_pcm_substream *subs)775{776	struct snd_pcm_runtime *runtime = subs->runtime;777	struct vx_pipe *pipe = runtime->private_data;778	return pipe->position;779}780 781/*782 * vx_pcm_prepare - prepare callback for playback and capture783 */784static int vx_pcm_prepare(struct snd_pcm_substream *subs)785{786	struct vx_core *chip = snd_pcm_substream_chip(subs);787	struct snd_pcm_runtime *runtime = subs->runtime;788	struct vx_pipe *pipe = runtime->private_data;789	int err, data_mode;790	// int max_size, nchunks;791 792	if (chip->chip_status & VX_STAT_IS_STALE)793		return -EBUSY;794 795	data_mode = (chip->uer_bits & IEC958_AES0_NONAUDIO) != 0;796	if (data_mode != pipe->data_mode && ! pipe->is_capture) {797		/* IEC958 status (raw-mode) was changed */798		/* we reopen the pipe */799		struct vx_rmh rmh;800		dev_dbg(chip->card->dev,801			"reopen the pipe with data_mode = %d\n", data_mode);802		vx_init_rmh(&rmh, CMD_FREE_PIPE);803		vx_set_pipe_cmd_params(&rmh, 0, pipe->number, 0);804		err = vx_send_msg(chip, &rmh);805		if (err < 0)806			return err;807		vx_init_rmh(&rmh, CMD_RES_PIPE);808		vx_set_pipe_cmd_params(&rmh, 0, pipe->number, pipe->channels);809		if (data_mode)810			rmh.Cmd[0] |= BIT_DATA_MODE;811		err = vx_send_msg(chip, &rmh);812		if (err < 0)813			return err;814		pipe->data_mode = data_mode;815	}816 817	if (chip->pcm_running && chip->freq != runtime->rate) {818		dev_err(chip->card->dev,819			"vx: cannot set different clock %d from the current %d\n",820			runtime->rate, chip->freq);821		return -EINVAL;822	}823	vx_set_clock(chip, runtime->rate);824 825	err = vx_set_format(chip, pipe, runtime);826	if (err < 0)827		return err;828 829	if (vx_is_pcmcia(chip)) {830		pipe->align = 2; /* 16bit word */831	} else {832		pipe->align = 4; /* 32bit word */833	}834 835	pipe->buffer_bytes = frames_to_bytes(runtime, runtime->buffer_size);836	pipe->period_bytes = frames_to_bytes(runtime, runtime->period_size);837	pipe->hw_ptr = 0;838 839	/* set the timestamp */840	vx_update_pipe_position(chip, runtime, pipe);841	/* clear again */842	pipe->transferred = 0;843	pipe->position = 0;844 845	pipe->prepared = 1;846 847	return 0;848}849 850 851/*852 * operators for PCM playback853 */854static const struct snd_pcm_ops vx_pcm_playback_ops = {855	.open =		vx_pcm_playback_open,856	.close =	vx_pcm_playback_close,857	.prepare =	vx_pcm_prepare,858	.trigger =	vx_pcm_trigger,859	.pointer =	vx_pcm_playback_pointer,860};861 862 863/*864 * playback hw information865 */866 867static const struct snd_pcm_hardware vx_pcm_capture_hw = {868	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |869				 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP_VALID /*|*/870				 /*SNDRV_PCM_INFO_RESUME*/),871	.formats =		(/*SNDRV_PCM_FMTBIT_U8 |*/872				 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_3LE),873	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,874	.rate_min =		5000,875	.rate_max =		48000,876	.channels_min =		1,877	.channels_max =		2,878	.buffer_bytes_max =	(128*1024),879	.period_bytes_min =	126,880	.period_bytes_max =	(128*1024),881	.periods_min =		2,882	.periods_max =		VX_MAX_PERIODS,883	.fifo_size =		126,884};885 886 887/*888 * vx_pcm_capture_open - open callback for capture889 */890static int vx_pcm_capture_open(struct snd_pcm_substream *subs)891{892	struct snd_pcm_runtime *runtime = subs->runtime;893	struct vx_core *chip = snd_pcm_substream_chip(subs);894	struct vx_pipe *pipe;895	struct vx_pipe *pipe_out_monitoring = NULL;896	unsigned int audio;897	int err;898 899	if (chip->chip_status & VX_STAT_IS_STALE)900		return -EBUSY;901 902	audio = subs->pcm->device * 2;903	if (snd_BUG_ON(audio >= chip->audio_ins))904		return -EINVAL;905	err = vx_alloc_pipe(chip, 1, audio, 2, &pipe);906	if (err < 0)907		return err;908	pipe->substream = subs;909	chip->capture_pipes[audio] = pipe;910 911	/* check if monitoring is needed */912	if (chip->audio_monitor_active[audio]) {913		pipe_out_monitoring = chip->playback_pipes[audio];914		if (! pipe_out_monitoring) {915			/* allocate a pipe */916			err = vx_alloc_pipe(chip, 0, audio, 2, &pipe_out_monitoring);917			if (err < 0)918				return err;919			chip->playback_pipes[audio] = pipe_out_monitoring;920		}921		pipe_out_monitoring->references++;922		/* 923		   if an output pipe is available, it's audios still may need to be 924		   unmuted. hence we'll have to call a mixer entry point.925		*/926		vx_set_monitor_level(chip, audio, chip->audio_monitor[audio],927				     chip->audio_monitor_active[audio]);928		/* assuming stereo */929		vx_set_monitor_level(chip, audio+1, chip->audio_monitor[audio+1],930				     chip->audio_monitor_active[audio+1]); 931	}932 933	pipe->monitoring_pipe = pipe_out_monitoring; /* default value NULL */934 935	runtime->hw = vx_pcm_capture_hw;936	runtime->hw.period_bytes_min = chip->ibl.size;937	runtime->private_data = pipe;938 939	/* align to 4 bytes (otherwise will be problematic when 24bit is used) */ 940	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 4);941	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4);942 943	return 0;944}945 946/*947 * vx_pcm_capture_close - close callback for capture948 */949static int vx_pcm_capture_close(struct snd_pcm_substream *subs)950{951	struct vx_core *chip = snd_pcm_substream_chip(subs);952	struct vx_pipe *pipe;953	struct vx_pipe *pipe_out_monitoring;954	955	if (! subs->runtime->private_data)956		return -EINVAL;957	pipe = subs->runtime->private_data;958	chip->capture_pipes[pipe->number] = NULL;959 960	pipe_out_monitoring = pipe->monitoring_pipe;961 962	/*963	  if an output pipe is attached to this input, 964	  check if it needs to be released.965	*/966	if (pipe_out_monitoring) {967		if (--pipe_out_monitoring->references == 0) {968			vx_free_pipe(chip, pipe_out_monitoring);969			chip->playback_pipes[pipe->number] = NULL;970			pipe->monitoring_pipe = NULL;971		}972	}973	974	vx_free_pipe(chip, pipe);975	return 0;976}977 978 979 980#define DMA_READ_ALIGN	6	/* hardware alignment for read */981 982/*983 * vx_pcm_capture_update - update the capture buffer984 */985static void vx_pcm_capture_update(struct vx_core *chip, struct snd_pcm_substream *subs,986				  struct vx_pipe *pipe)987{988	int size, space, count;989	struct snd_pcm_runtime *runtime = subs->runtime;990 991	if (!pipe->running || (chip->chip_status & VX_STAT_IS_STALE))992		return;993 994	size = runtime->buffer_size - snd_pcm_capture_avail(runtime);995	if (! size)996		return;997	size = frames_to_bytes(runtime, size);998	space = vx_query_hbuffer_size(chip, pipe);999	if (space < 0)1000		goto _error;1001	if (size > space)1002		size = space;1003	size = (size / 3) * 3; /* align to 3 bytes */1004	if (size < DMA_READ_ALIGN)1005		goto _error;1006 1007	/* keep the last 6 bytes, they will be read after disconnection */1008	count = size - DMA_READ_ALIGN;1009	/* read bytes until the current pointer reaches to the aligned position1010	 * for word-transfer1011	 */1012	while (count > 0) {1013		if ((pipe->hw_ptr % pipe->align) == 0)1014			break;1015		if (vx_wait_for_rx_full(chip) < 0)1016			goto _error;1017		vx_pcm_read_per_bytes(chip, runtime, pipe);1018		count -= 3;1019	}1020	if (count > 0) {1021		/* ok, let's accelerate! */1022		int align = pipe->align * 3;1023		space = (count / align) * align;1024		if (space > 0) {1025			vx_pseudo_dma_read(chip, runtime, pipe, space);1026			count -= space;1027		}1028	}1029	/* read the rest of bytes */1030	while (count > 0) {1031		if (vx_wait_for_rx_full(chip) < 0)1032			goto _error;1033		vx_pcm_read_per_bytes(chip, runtime, pipe);1034		count -= 3;1035	}1036	/* disconnect the host, SIZE_HBUF command always switches to the stream mode */1037	vx_send_rih(chip, IRQ_CONNECT_STREAM_NEXT);1038	/* read the last pending 6 bytes */1039	count = DMA_READ_ALIGN;1040	while (count > 0) {1041		vx_pcm_read_per_bytes(chip, runtime, pipe);1042		count -= 3;1043	}1044	/* update the position */1045	pipe->transferred += size;1046	if (pipe->transferred >= pipe->period_bytes) {1047		pipe->transferred %= pipe->period_bytes;1048		snd_pcm_period_elapsed(subs);1049	}1050	return;1051 1052 _error:1053	/* disconnect the host, SIZE_HBUF command always switches to the stream mode */1054	vx_send_rih(chip, IRQ_CONNECT_STREAM_NEXT);1055	return;1056}1057 1058/*1059 * vx_pcm_capture_pointer - pointer callback for capture1060 */1061static snd_pcm_uframes_t vx_pcm_capture_pointer(struct snd_pcm_substream *subs)1062{1063	struct snd_pcm_runtime *runtime = subs->runtime;1064	struct vx_pipe *pipe = runtime->private_data;1065	return bytes_to_frames(runtime, pipe->hw_ptr);1066}1067 1068/*1069 * operators for PCM capture1070 */1071static const struct snd_pcm_ops vx_pcm_capture_ops = {1072	.open =		vx_pcm_capture_open,1073	.close =	vx_pcm_capture_close,1074	.prepare =	vx_pcm_prepare,1075	.trigger =	vx_pcm_trigger,1076	.pointer =	vx_pcm_capture_pointer,1077};1078 1079 1080/*1081 * interrupt handler for pcm streams1082 */1083void vx_pcm_update_intr(struct vx_core *chip, unsigned int events)1084{1085	unsigned int i;1086	struct vx_pipe *pipe;1087 1088#define EVENT_MASK	(END_OF_BUFFER_EVENTS_PENDING|ASYNC_EVENTS_PENDING)1089 1090	if (events & EVENT_MASK) {1091		vx_init_rmh(&chip->irq_rmh, CMD_ASYNC);1092		if (events & ASYNC_EVENTS_PENDING)1093			chip->irq_rmh.Cmd[0] |= 0x00000001;	/* SEL_ASYNC_EVENTS */1094		if (events & END_OF_BUFFER_EVENTS_PENDING)1095			chip->irq_rmh.Cmd[0] |= 0x00000002;	/* SEL_END_OF_BUF_EVENTS */1096 1097		if (vx_send_msg(chip, &chip->irq_rmh) < 0) {1098			dev_dbg(chip->card->dev, "msg send error!!\n");1099			return;1100		}1101 1102		i = 1;1103		while (i < chip->irq_rmh.LgStat) {1104			int p, buf, capture, eob;1105			p = chip->irq_rmh.Stat[i] & MASK_FIRST_FIELD;1106			capture = (chip->irq_rmh.Stat[i] & 0x400000) ? 1 : 0;1107			eob = (chip->irq_rmh.Stat[i] & 0x800000) ? 1 : 0;1108			i++;1109			if (events & ASYNC_EVENTS_PENDING)1110				i++;1111			buf = 1; /* force to transfer */1112			if (events & END_OF_BUFFER_EVENTS_PENDING) {1113				if (eob)1114					buf = chip->irq_rmh.Stat[i];1115				i++;1116			}1117			if (capture)1118				continue;1119			if (snd_BUG_ON(p < 0 || p >= chip->audio_outs))1120				continue;1121			pipe = chip->playback_pipes[p];1122			if (pipe && pipe->substream) {1123				vx_pcm_playback_update(chip, pipe->substream, pipe);1124				vx_pcm_playback_transfer(chip, pipe->substream, pipe, buf);1125			}1126		}1127	}1128 1129	/* update the capture pcm pointers as frequently as possible */1130	for (i = 0; i < chip->audio_ins; i++) {1131		pipe = chip->capture_pipes[i];1132		if (pipe && pipe->substream)1133			vx_pcm_capture_update(chip, pipe->substream, pipe);1134	}1135}1136 1137 1138/*1139 * vx_init_audio_io - check the available audio i/o and allocate pipe arrays1140 */1141static int vx_init_audio_io(struct vx_core *chip)1142{1143	struct vx_rmh rmh;1144	int preferred;1145 1146	vx_init_rmh(&rmh, CMD_SUPPORTED);1147	if (vx_send_msg(chip, &rmh) < 0) {1148		dev_err(chip->card->dev,1149			"vx: cannot get the supported audio data\n");1150		return -ENXIO;1151	}1152 1153	chip->audio_outs = rmh.Stat[0] & MASK_FIRST_FIELD;1154	chip->audio_ins = (rmh.Stat[0] >> (FIELD_SIZE*2)) & MASK_FIRST_FIELD;1155	chip->audio_info = rmh.Stat[1];1156 1157	/* allocate pipes */1158	chip->playback_pipes = kcalloc(chip->audio_outs, sizeof(struct vx_pipe *), GFP_KERNEL);1159	if (!chip->playback_pipes)1160		return -ENOMEM;1161	chip->capture_pipes = kcalloc(chip->audio_ins, sizeof(struct vx_pipe *), GFP_KERNEL);1162	if (!chip->capture_pipes) {1163		kfree(chip->playback_pipes);1164		return -ENOMEM;1165	}1166 1167	preferred = chip->ibl.size;1168	chip->ibl.size = 0;1169	vx_set_ibl(chip, &chip->ibl); /* query the info */1170	if (preferred > 0) {1171		chip->ibl.size = roundup(preferred, chip->ibl.granularity);1172		if (chip->ibl.size > chip->ibl.max_size)1173			chip->ibl.size = chip->ibl.max_size;1174	} else1175		chip->ibl.size = chip->ibl.min_size; /* set to the minimum */1176	vx_set_ibl(chip, &chip->ibl);1177 1178	return 0;1179}1180 1181 1182/*1183 * free callback for pcm1184 */1185static void snd_vx_pcm_free(struct snd_pcm *pcm)1186{1187	struct vx_core *chip = pcm->private_data;1188	chip->pcm[pcm->device] = NULL;1189	kfree(chip->playback_pipes);1190	chip->playback_pipes = NULL;1191	kfree(chip->capture_pipes);1192	chip->capture_pipes = NULL;1193}1194 1195/*1196 * snd_vx_pcm_new - create and initialize a pcm1197 */1198int snd_vx_pcm_new(struct vx_core *chip)1199{1200	struct snd_pcm *pcm;1201	unsigned int i;1202	int err;1203 1204	err = vx_init_audio_io(chip);1205	if (err < 0)1206		return err;1207 1208	for (i = 0; i < chip->hw->num_codecs; i++) {1209		unsigned int outs, ins;1210		outs = chip->audio_outs > i * 2 ? 1 : 0;1211		ins = chip->audio_ins > i * 2 ? 1 : 0;1212		if (! outs && ! ins)1213			break;1214		err = snd_pcm_new(chip->card, "VX PCM", i,1215				  outs, ins, &pcm);1216		if (err < 0)1217			return err;1218		if (outs)1219			snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &vx_pcm_playback_ops);1220		if (ins)1221			snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &vx_pcm_capture_ops);1222		snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC,1223					       NULL, 0, 0);1224 1225		pcm->private_data = chip;1226		pcm->private_free = snd_vx_pcm_free;1227		pcm->info_flags = 0;1228		pcm->nonatomic = true;1229		strcpy(pcm->name, chip->card->shortname);1230		chip->pcm[i] = pcm;1231	}1232 1233	return 0;1234}1235