brintos

brintos / linux-shallow public Read only

0
0
Text · 19.1 KiB · 546f712 Raw
683 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 */4 5/*6 * Vortex PCM ALSA driver.7 *8 * Supports ADB and WT DMA. Unfortunately, WT channels do not run yet.9 * It remains stuck,and DMA transfers do not happen. 10 */11#include <sound/asoundef.h>12#include <linux/time.h>13#include <sound/core.h>14#include <sound/pcm.h>15#include <sound/pcm_params.h>16#include "au88x0.h"17 18#define VORTEX_PCM_TYPE(x) (x->name[40])19 20/* hardware definition */21static const struct snd_pcm_hardware snd_vortex_playback_hw_adb = {22	.info =23	    (SNDRV_PCM_INFO_MMAP | /* SNDRV_PCM_INFO_RESUME | */24	     SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_INTERLEAVED |25	     SNDRV_PCM_INFO_MMAP_VALID),26	.formats =27	    SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U8 |28	    SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW,29	.rates = SNDRV_PCM_RATE_CONTINUOUS,30	.rate_min = 5000,31	.rate_max = 48000,32	.channels_min = 1,33	.channels_max = 2,34	.buffer_bytes_max = 0x10000,35	.period_bytes_min = 0x20,36	.period_bytes_max = 0x1000,37	.periods_min = 2,38	.periods_max = 1024,39};40 41#ifndef CHIP_AU882042static const struct snd_pcm_hardware snd_vortex_playback_hw_a3d = {43	.info =44	    (SNDRV_PCM_INFO_MMAP | /* SNDRV_PCM_INFO_RESUME | */45	     SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_INTERLEAVED |46	     SNDRV_PCM_INFO_MMAP_VALID),47	.formats =48	    SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U8 |49	    SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW,50	.rates = SNDRV_PCM_RATE_CONTINUOUS,51	.rate_min = 5000,52	.rate_max = 48000,53	.channels_min = 1,54	.channels_max = 1,55	.buffer_bytes_max = 0x10000,56	.period_bytes_min = 0x100,57	.period_bytes_max = 0x1000,58	.periods_min = 2,59	.periods_max = 64,60};61#endif62static const struct snd_pcm_hardware snd_vortex_playback_hw_spdif = {63	.info =64	    (SNDRV_PCM_INFO_MMAP | /* SNDRV_PCM_INFO_RESUME | */65	     SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_INTERLEAVED |66	     SNDRV_PCM_INFO_MMAP_VALID),67	.formats =68	    SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U8 |69	    SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE | SNDRV_PCM_FMTBIT_MU_LAW |70	    SNDRV_PCM_FMTBIT_A_LAW,71	.rates =72	    SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,73	.rate_min = 32000,74	.rate_max = 48000,75	.channels_min = 1,76	.channels_max = 2,77	.buffer_bytes_max = 0x10000,78	.period_bytes_min = 0x100,79	.period_bytes_max = 0x1000,80	.periods_min = 2,81	.periods_max = 64,82};83 84#ifndef CHIP_AU881085static const struct snd_pcm_hardware snd_vortex_playback_hw_wt = {86	.info = (SNDRV_PCM_INFO_MMAP |87		 SNDRV_PCM_INFO_INTERLEAVED |88		 SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID),89	.formats = SNDRV_PCM_FMTBIT_S16_LE,90	.rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_CONTINUOUS,	// SNDRV_PCM_RATE_48000,91	.rate_min = 8000,92	.rate_max = 48000,93	.channels_min = 1,94	.channels_max = 2,95	.buffer_bytes_max = 0x10000,96	.period_bytes_min = 0x0400,97	.period_bytes_max = 0x1000,98	.periods_min = 2,99	.periods_max = 64,100};101#endif102#ifdef CHIP_AU8830103static const unsigned int au8830_channels[3] = {104	1, 2, 4,105};106 107static const struct snd_pcm_hw_constraint_list hw_constraints_au8830_channels = {108	.count = ARRAY_SIZE(au8830_channels),109	.list = au8830_channels,110	.mask = 0,111};112#endif113 114static void vortex_notify_pcm_vol_change(struct snd_card *card,115			struct snd_kcontrol *kctl, int activate)116{117	if (activate)118		kctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;119	else120		kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;121	snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE |122				SNDRV_CTL_EVENT_MASK_INFO, &(kctl->id));123}124 125/* open callback */126static int snd_vortex_pcm_open(struct snd_pcm_substream *substream)127{128	vortex_t *vortex = snd_pcm_substream_chip(substream);129	struct snd_pcm_runtime *runtime = substream->runtime;130	int err;131	132	/* Force equal size periods */133	err = snd_pcm_hw_constraint_integer(runtime,134					    SNDRV_PCM_HW_PARAM_PERIODS);135	if (err < 0)136		return err;137	/* Avoid PAGE_SIZE boundary to fall inside of a period. */138	err = snd_pcm_hw_constraint_pow2(runtime, 0,139					 SNDRV_PCM_HW_PARAM_PERIOD_BYTES);140	if (err < 0)141		return err;142 143	snd_pcm_hw_constraint_step(runtime, 0,144					SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 64);145 146	if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) {147#ifndef CHIP_AU8820148		if (VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_A3D) {149			runtime->hw = snd_vortex_playback_hw_a3d;150		}151#endif152		if (VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_SPDIF) {153			runtime->hw = snd_vortex_playback_hw_spdif;154			switch (vortex->spdif_sr) {155			case 32000:156				runtime->hw.rates = SNDRV_PCM_RATE_32000;157				break;158			case 44100:159				runtime->hw.rates = SNDRV_PCM_RATE_44100;160				break;161			case 48000:162				runtime->hw.rates = SNDRV_PCM_RATE_48000;163				break;164			}165		}166		if (VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_ADB167		    || VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_I2S)168			runtime->hw = snd_vortex_playback_hw_adb;169#ifdef CHIP_AU8830170		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&171			VORTEX_IS_QUAD(vortex) &&172			VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_ADB) {173			runtime->hw.channels_max = 4;174			snd_pcm_hw_constraint_list(runtime, 0,175				SNDRV_PCM_HW_PARAM_CHANNELS,176				&hw_constraints_au8830_channels);177		}178#endif179		substream->runtime->private_data = NULL;180	}181#ifndef CHIP_AU8810182	else {183		runtime->hw = snd_vortex_playback_hw_wt;184		substream->runtime->private_data = NULL;185	}186#endif187	return 0;188}189 190/* close callback */191static int snd_vortex_pcm_close(struct snd_pcm_substream *substream)192{193	//vortex_t *chip = snd_pcm_substream_chip(substream);194	stream_t *stream = (stream_t *) substream->runtime->private_data;195 196	// the hardware-specific codes will be here197	if (stream != NULL) {198		stream->substream = NULL;199		stream->nr_ch = 0;200	}201	substream->runtime->private_data = NULL;202	return 0;203}204 205/* hw_params callback */206static int207snd_vortex_pcm_hw_params(struct snd_pcm_substream *substream,208			 struct snd_pcm_hw_params *hw_params)209{210	vortex_t *chip = snd_pcm_substream_chip(substream);211	stream_t *stream = (stream_t *) (substream->runtime->private_data);212 213	/*214	   pr_info( "Vortex: periods %d, period_bytes %d, channels = %d\n", params_periods(hw_params),215	   params_period_bytes(hw_params), params_channels(hw_params));216	 */217	spin_lock_irq(&chip->lock);218	// Make audio routes and config buffer DMA.219	if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) {220		int dma, type = VORTEX_PCM_TYPE(substream->pcm);221		/* Dealloc any routes. */222		if (stream != NULL)223			vortex_adb_allocroute(chip, stream->dma,224					      stream->nr_ch, stream->dir,225					      stream->type,226					      substream->number);227		/* Alloc routes. */228		dma =229		    vortex_adb_allocroute(chip, -1,230					  params_channels(hw_params),231					  substream->stream, type,232					  substream->number);233		if (dma < 0) {234			spin_unlock_irq(&chip->lock);235			return dma;236		}237		stream = substream->runtime->private_data = &chip->dma_adb[dma];238		stream->substream = substream;239		/* Setup Buffers. */240		vortex_adbdma_setbuffers(chip, dma,241					 params_period_bytes(hw_params),242					 params_periods(hw_params));243		if (VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_ADB) {244			chip->pcm_vol[substream->number].active = 1;245			vortex_notify_pcm_vol_change(chip->card,246				chip->pcm_vol[substream->number].kctl, 1);247		}248	}249#ifndef CHIP_AU8810250	else {251		/* if (stream != NULL)252		   vortex_wt_allocroute(chip, substream->number, 0); */253		vortex_wt_allocroute(chip, substream->number,254				     params_channels(hw_params));255		stream = substream->runtime->private_data =256		    &chip->dma_wt[substream->number];257		stream->dma = substream->number;258		stream->substream = substream;259		vortex_wtdma_setbuffers(chip, substream->number,260					params_period_bytes(hw_params),261					params_periods(hw_params));262	}263#endif264	spin_unlock_irq(&chip->lock);265	return 0;266}267 268/* hw_free callback */269static int snd_vortex_pcm_hw_free(struct snd_pcm_substream *substream)270{271	vortex_t *chip = snd_pcm_substream_chip(substream);272	stream_t *stream = (stream_t *) (substream->runtime->private_data);273 274	spin_lock_irq(&chip->lock);275	// Delete audio routes.276	if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) {277		if (stream != NULL) {278			if (VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_ADB) {279				chip->pcm_vol[substream->number].active = 0;280				vortex_notify_pcm_vol_change(chip->card,281					chip->pcm_vol[substream->number].kctl,282					0);283			}284			vortex_adb_allocroute(chip, stream->dma,285					      stream->nr_ch, stream->dir,286					      stream->type,287					      substream->number);288		}289	}290#ifndef CHIP_AU8810291	else {292		if (stream != NULL)293			vortex_wt_allocroute(chip, stream->dma, 0);294	}295#endif296	substream->runtime->private_data = NULL;297	spin_unlock_irq(&chip->lock);298 299	return 0;300}301 302/* prepare callback */303static int snd_vortex_pcm_prepare(struct snd_pcm_substream *substream)304{305	vortex_t *chip = snd_pcm_substream_chip(substream);306	struct snd_pcm_runtime *runtime = substream->runtime;307	stream_t *stream = (stream_t *) substream->runtime->private_data;308	int dma = stream->dma, fmt, dir;309 310	// set up the hardware with the current configuration.311	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)312		dir = 1;313	else314		dir = 0;315	fmt = vortex_alsafmt_aspfmt(runtime->format, chip);316	spin_lock_irq(&chip->lock);317	if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) {318		vortex_adbdma_setmode(chip, dma, 1, dir, fmt,319				runtime->channels == 1 ? 0 : 1, 0);320		vortex_adbdma_setstartbuffer(chip, dma, 0);321		if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_SPDIF)322			vortex_adb_setsrc(chip, dma, runtime->rate, dir);323	}324#ifndef CHIP_AU8810325	else {326		vortex_wtdma_setmode(chip, dma, 1, fmt, 0, 0);327		// FIXME: Set rate (i guess using vortex_wt_writereg() somehow).328		vortex_wtdma_setstartbuffer(chip, dma, 0);329	}330#endif331	spin_unlock_irq(&chip->lock);332	return 0;333}334 335/* trigger callback */336static int snd_vortex_pcm_trigger(struct snd_pcm_substream *substream, int cmd)337{338	vortex_t *chip = snd_pcm_substream_chip(substream);339	stream_t *stream = (stream_t *) substream->runtime->private_data;340	int dma = stream->dma;341 342	spin_lock(&chip->lock);343	switch (cmd) {344	case SNDRV_PCM_TRIGGER_START:345		// do something to start the PCM engine346		//printk(KERN_INFO "vortex: start %d\n", dma);347		stream->fifo_enabled = 1;348		if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) {349			vortex_adbdma_resetup(chip, dma);350			vortex_adbdma_startfifo(chip, dma);351		}352#ifndef CHIP_AU8810353		else {354			dev_info(chip->card->dev, "wt start %d\n", dma);355			vortex_wtdma_startfifo(chip, dma);356		}357#endif358		break;359	case SNDRV_PCM_TRIGGER_STOP:360		// do something to stop the PCM engine361		//printk(KERN_INFO "vortex: stop %d\n", dma);362		stream->fifo_enabled = 0;363		if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT)364			vortex_adbdma_stopfifo(chip, dma);365#ifndef CHIP_AU8810366		else {367			dev_info(chip->card->dev, "wt stop %d\n", dma);368			vortex_wtdma_stopfifo(chip, dma);369		}370#endif371		break;372	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:373		//printk(KERN_INFO "vortex: pause %d\n", dma);374		if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT)375			vortex_adbdma_pausefifo(chip, dma);376#ifndef CHIP_AU8810377		else378			vortex_wtdma_pausefifo(chip, dma);379#endif380		break;381	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:382		//printk(KERN_INFO "vortex: resume %d\n", dma);383		if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT)384			vortex_adbdma_resumefifo(chip, dma);385#ifndef CHIP_AU8810386		else387			vortex_wtdma_resumefifo(chip, dma);388#endif389		break;390	default:391		spin_unlock(&chip->lock);392		return -EINVAL;393	}394	spin_unlock(&chip->lock);395	return 0;396}397 398/* pointer callback */399static snd_pcm_uframes_t snd_vortex_pcm_pointer(struct snd_pcm_substream *substream)400{401	vortex_t *chip = snd_pcm_substream_chip(substream);402	stream_t *stream = (stream_t *) substream->runtime->private_data;403	int dma = stream->dma;404	snd_pcm_uframes_t current_ptr = 0;405 406	spin_lock(&chip->lock);407	if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT)408		current_ptr = vortex_adbdma_getlinearpos(chip, dma);409#ifndef CHIP_AU8810410	else411		current_ptr = vortex_wtdma_getlinearpos(chip, dma);412#endif413	//printk(KERN_INFO "vortex: pointer = 0x%x\n", current_ptr);414	spin_unlock(&chip->lock);415	current_ptr = bytes_to_frames(substream->runtime, current_ptr);416	if (current_ptr >= substream->runtime->buffer_size)417		current_ptr = 0;418	return current_ptr;419}420 421/* operators */422static const struct snd_pcm_ops snd_vortex_playback_ops = {423	.open = snd_vortex_pcm_open,424	.close = snd_vortex_pcm_close,425	.hw_params = snd_vortex_pcm_hw_params,426	.hw_free = snd_vortex_pcm_hw_free,427	.prepare = snd_vortex_pcm_prepare,428	.trigger = snd_vortex_pcm_trigger,429	.pointer = snd_vortex_pcm_pointer,430};431 432/*433*  definitions of capture are omitted here...434*/435 436static const char * const vortex_pcm_prettyname[VORTEX_PCM_LAST] = {437	CARD_NAME " ADB",438	CARD_NAME " SPDIF",439	CARD_NAME " A3D",440	CARD_NAME " WT",441	CARD_NAME " I2S",442};443static const char * const vortex_pcm_name[VORTEX_PCM_LAST] = {444	"adb",445	"spdif",446	"a3d",447	"wt",448	"i2s",449};450 451/* SPDIF kcontrol */452 453static int snd_vortex_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)454{455	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;456	uinfo->count = 1;457	return 0;458}459 460static int snd_vortex_spdif_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)461{462	ucontrol->value.iec958.status[0] = 0xff;463	ucontrol->value.iec958.status[1] = 0xff;464	ucontrol->value.iec958.status[2] = 0xff;465	ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS;466	return 0;467}468 469static int snd_vortex_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)470{471	vortex_t *vortex = snd_kcontrol_chip(kcontrol);472	ucontrol->value.iec958.status[0] = 0x00;473	ucontrol->value.iec958.status[1] = IEC958_AES1_CON_ORIGINAL|IEC958_AES1_CON_DIGDIGCONV_ID;474	ucontrol->value.iec958.status[2] = 0x00;475	switch (vortex->spdif_sr) {476	case 32000: ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS_32000; break;477	case 44100: ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS_44100; break;478	case 48000: ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS_48000; break;479	}480	return 0;481}482 483static int snd_vortex_spdif_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)484{485	vortex_t *vortex = snd_kcontrol_chip(kcontrol);486	int spdif_sr = 48000;487	switch (ucontrol->value.iec958.status[3] & IEC958_AES3_CON_FS) {488	case IEC958_AES3_CON_FS_32000: spdif_sr = 32000; break;489	case IEC958_AES3_CON_FS_44100: spdif_sr = 44100; break;490	case IEC958_AES3_CON_FS_48000: spdif_sr = 48000; break;491	}492	if (spdif_sr == vortex->spdif_sr)493		return 0;494	vortex->spdif_sr = spdif_sr;495	vortex_spdif_init(vortex, vortex->spdif_sr, 1);496	return 1;497}498 499/* spdif controls */500static const struct snd_kcontrol_new snd_vortex_mixer_spdif[] = {501	{502		.iface =	SNDRV_CTL_ELEM_IFACE_PCM,503		.name =		SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),504		.info =		snd_vortex_spdif_info,505		.get =		snd_vortex_spdif_get,506		.put =		snd_vortex_spdif_put,507	},508	{509		.access =	SNDRV_CTL_ELEM_ACCESS_READ,510		.iface =	SNDRV_CTL_ELEM_IFACE_PCM,511		.name =		SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),512		.info =		snd_vortex_spdif_info,513		.get =		snd_vortex_spdif_mask_get514	},515};516 517/* subdevice PCM Volume control */518 519static int snd_vortex_pcm_vol_info(struct snd_kcontrol *kcontrol,520				struct snd_ctl_elem_info *uinfo)521{522	vortex_t *vortex = snd_kcontrol_chip(kcontrol);523	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;524	uinfo->count = (VORTEX_IS_QUAD(vortex) ? 4 : 2);525	uinfo->value.integer.min = -128;526	uinfo->value.integer.max = 32;527	return 0;528}529 530static int snd_vortex_pcm_vol_get(struct snd_kcontrol *kcontrol,531				struct snd_ctl_elem_value *ucontrol)532{533	int i;534	vortex_t *vortex = snd_kcontrol_chip(kcontrol);535	int subdev = kcontrol->id.subdevice;536	struct pcm_vol *p = &vortex->pcm_vol[subdev];537	int max_chn = (VORTEX_IS_QUAD(vortex) ? 4 : 2);538	for (i = 0; i < max_chn; i++)539		ucontrol->value.integer.value[i] = p->vol[i];540	return 0;541}542 543static int snd_vortex_pcm_vol_put(struct snd_kcontrol *kcontrol,544				struct snd_ctl_elem_value *ucontrol)545{546	int i;547	int changed = 0;548	int mixin;549	unsigned char vol;550	vortex_t *vortex = snd_kcontrol_chip(kcontrol);551	int subdev = kcontrol->id.subdevice;552	struct pcm_vol *p = &vortex->pcm_vol[subdev];553	int max_chn = (VORTEX_IS_QUAD(vortex) ? 4 : 2);554	for (i = 0; i < max_chn; i++) {555		if (p->vol[i] != ucontrol->value.integer.value[i]) {556			p->vol[i] = ucontrol->value.integer.value[i];557			if (p->active) {558				switch (vortex->dma_adb[p->dma].nr_ch) {559				case 1:560					mixin = p->mixin[0];561					break;562				case 2:563				default:564					mixin = p->mixin[(i < 2) ? i : (i - 2)];565					break;566				case 4:567					mixin = p->mixin[i];568					break;569				}570				vol = p->vol[i];571				vortex_mix_setinputvolumebyte(vortex,572					vortex->mixplayb[i], mixin, vol);573			}574			changed = 1;575		}576	}577	return changed;578}579 580static const DECLARE_TLV_DB_MINMAX(vortex_pcm_vol_db_scale, -9600, 2400);581 582static const struct snd_kcontrol_new snd_vortex_pcm_vol = {583	.iface = SNDRV_CTL_ELEM_IFACE_PCM,584	.name = "PCM Playback Volume",585	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |586		SNDRV_CTL_ELEM_ACCESS_TLV_READ |587		SNDRV_CTL_ELEM_ACCESS_INACTIVE,588	.info = snd_vortex_pcm_vol_info,589	.get = snd_vortex_pcm_vol_get,590	.put = snd_vortex_pcm_vol_put,591	.tlv = { .p = vortex_pcm_vol_db_scale },592};593 594/* create a pcm device */595static int snd_vortex_new_pcm(vortex_t *chip, int idx, int nr)596{597	struct snd_pcm *pcm;598	struct snd_kcontrol *kctl;599	int i;600	int err, nr_capt;601 602	if (!chip || idx < 0 || idx >= VORTEX_PCM_LAST)603		return -ENODEV;604 605	/* idx indicates which kind of PCM device. ADB, SPDIF, I2S and A3D share the 606	 * same dma engine. WT uses it own separate dma engine which can't capture. */607	if (idx == VORTEX_PCM_ADB)608		nr_capt = nr;609	else610		nr_capt = 0;611	err = snd_pcm_new(chip->card, vortex_pcm_prettyname[idx], idx, nr,612			  nr_capt, &pcm);613	if (err < 0)614		return err;615	snprintf(pcm->name, sizeof(pcm->name),616		"%s %s", CARD_NAME_SHORT, vortex_pcm_name[idx]);617	chip->pcm[idx] = pcm;618	// This is an evil hack, but it saves a lot of duplicated code.619	VORTEX_PCM_TYPE(pcm) = idx;620	pcm->private_data = chip;621	/* set operators */622	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,623			&snd_vortex_playback_ops);624	if (idx == VORTEX_PCM_ADB)625		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,626				&snd_vortex_playback_ops);627	628	/* pre-allocation of Scatter-Gather buffers */629	630	snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_SG,631				       &chip->pci_dev->dev, 0x10000, 0x10000);632 633	switch (VORTEX_PCM_TYPE(pcm)) {634	case VORTEX_PCM_ADB:635		err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,636					     snd_pcm_std_chmaps,637					     VORTEX_IS_QUAD(chip) ? 4 : 2,638					     0, NULL);639		if (err < 0)640			return err;641		err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_CAPTURE,642					     snd_pcm_std_chmaps, 2, 0, NULL);643		if (err < 0)644			return err;645		break;646#ifdef CHIP_AU8830647	case VORTEX_PCM_A3D:648		err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,649					     snd_pcm_std_chmaps, 1, 0, NULL);650		if (err < 0)651			return err;652		break;653#endif654	}655 656	if (VORTEX_PCM_TYPE(pcm) == VORTEX_PCM_SPDIF) {657		for (i = 0; i < ARRAY_SIZE(snd_vortex_mixer_spdif); i++) {658			kctl = snd_ctl_new1(&snd_vortex_mixer_spdif[i], chip);659			if (!kctl)660				return -ENOMEM;661			err = snd_ctl_add(chip->card, kctl);662			if (err < 0)663				return err;664		}665	}666	if (VORTEX_PCM_TYPE(pcm) == VORTEX_PCM_ADB) {667		for (i = 0; i < NR_PCM; i++) {668			chip->pcm_vol[i].active = 0;669			chip->pcm_vol[i].dma = -1;670			kctl = snd_ctl_new1(&snd_vortex_pcm_vol, chip);671			if (!kctl)672				return -ENOMEM;673			chip->pcm_vol[i].kctl = kctl;674			kctl->id.device = 0;675			kctl->id.subdevice = i;676			err = snd_ctl_add(chip->card, kctl);677			if (err < 0)678				return err;679		}680	}681	return 0;682}683