brintos

brintos / linux-shallow public Read only

0
0
Text · 41.9 KiB · 2a3e9d8 Raw
1746 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.4 *5 * @File    ctatc.c6 *7 * @Brief8 * This file contains the implementation of the device resource management9 * object.10 *11 * @Author Liu Chun12 * @Date Mar 28 200813 */14 15#include "ctatc.h"16#include "ctpcm.h"17#include "ctmixer.h"18#include "ctsrc.h"19#include "ctamixer.h"20#include "ctdaio.h"21#include "cttimer.h"22#include <linux/delay.h>23#include <linux/slab.h>24#include <sound/pcm.h>25#include <sound/control.h>26#include <sound/asoundef.h>27 28#define MONO_SUM_SCALE	0x19a8	/* 2^(-0.5) in 14-bit floating format */29#define MAX_MULTI_CHN	830 31#define IEC958_DEFAULT_CON ((IEC958_AES0_NONAUDIO \32			    | IEC958_AES0_CON_NOT_COPYRIGHT) \33			    | ((IEC958_AES1_CON_MIXER \34			    | IEC958_AES1_CON_ORIGINAL) << 8) \35			    | (0x10 << 16) \36			    | ((IEC958_AES3_CON_FS_48000) << 24))37 38static const struct snd_pci_quirk subsys_20k1_list[] = {39	SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, 0x0021, "SB046x", CTSB046X),40	SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, 0x0022, "SB055x", CTSB055X),41	SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, 0x002f, "SB055x", CTSB055X),42	SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, 0x0029, "SB073x", CTSB073X),43	SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, 0x0031, "SB073x", CTSB073X),44	SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_CREATIVE, 0xf000, 0x6000,45			   "UAA", CTUAA),46	{ } /* terminator */47};48 49static const struct snd_pci_quirk subsys_20k2_list[] = {50	SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB0760,51		      "SB0760", CTSB0760),52	SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB1270,53		      "SB1270", CTSB1270),54	SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB08801,55		      "SB0880", CTSB0880),56	SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB08802,57		      "SB0880", CTSB0880),58	SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB08803,59		      "SB0880", CTSB0880),60	SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_CREATIVE, 0xf000,61			   PCI_SUBDEVICE_ID_CREATIVE_HENDRIX, "HENDRIX",62			   CTHENDRIX),63	{ } /* terminator */64};65 66static const char *ct_subsys_name[NUM_CTCARDS] = {67	/* 20k1 models */68	[CTSB046X]	= "SB046x",69	[CTSB055X]	= "SB055x",70	[CTSB073X]	= "SB073x",71	[CTUAA]		= "UAA",72	[CT20K1_UNKNOWN] = "Unknown",73	/* 20k2 models */74	[CTSB0760]	= "SB076x",75	[CTHENDRIX]	= "Hendrix",76	[CTSB0880]	= "SB0880",77	[CTSB1270]      = "SB1270",78	[CT20K2_UNKNOWN] = "Unknown",79};80 81static struct {82	int (*create)(struct ct_atc *atc,83			enum CTALSADEVS device, const char *device_name);84	int (*destroy)(void *alsa_dev);85	const char *public_name;86} alsa_dev_funcs[NUM_CTALSADEVS] = {87	[FRONT]		= { .create = ct_alsa_pcm_create,88			    .destroy = NULL,89			    .public_name = "Front/WaveIn"},90	[SURROUND]	= { .create = ct_alsa_pcm_create,91			    .destroy = NULL,92			    .public_name = "Surround"},93	[CLFE]		= { .create = ct_alsa_pcm_create,94			    .destroy = NULL,95			    .public_name = "Center/LFE"},96	[SIDE]		= { .create = ct_alsa_pcm_create,97			    .destroy = NULL,98			    .public_name = "Side"},99	[IEC958]	= { .create = ct_alsa_pcm_create,100			    .destroy = NULL,101			    .public_name = "IEC958 Non-audio"},102 103	[MIXER]		= { .create = ct_alsa_mix_create,104			    .destroy = NULL,105			    .public_name = "Mixer"}106};107 108static struct {109	int (*create)(struct hw *hw, void **rmgr);110	int (*destroy)(void *mgr);111} rsc_mgr_funcs[NUM_RSCTYP] = {112	[SRC] 		= { .create 	= src_mgr_create,113			    .destroy 	= src_mgr_destroy	},114	[SRCIMP] 	= { .create 	= srcimp_mgr_create,115			    .destroy 	= srcimp_mgr_destroy	},116	[AMIXER]	= { .create	= amixer_mgr_create,117			    .destroy	= amixer_mgr_destroy	},118	[SUM]		= { .create	= sum_mgr_create,119			    .destroy	= sum_mgr_destroy	},120	[DAIO]		= { .create	= daio_mgr_create,121			    .destroy	= daio_mgr_destroy	}122};123 124static int125atc_pcm_release_resources(struct ct_atc *atc, struct ct_atc_pcm *apcm);126 127/* *128 * Only mono and interleaved modes are supported now.129 * Always allocates a contiguous channel block.130 * */131 132static int ct_map_audio_buffer(struct ct_atc *atc, struct ct_atc_pcm *apcm)133{134	struct snd_pcm_runtime *runtime;135	struct ct_vm *vm;136 137	if (!apcm->substream)138		return 0;139 140	runtime = apcm->substream->runtime;141	vm = atc->vm;142 143	apcm->vm_block = vm->map(vm, apcm->substream, runtime->dma_bytes);144 145	if (!apcm->vm_block)146		return -ENOENT;147 148	return 0;149}150 151static void ct_unmap_audio_buffer(struct ct_atc *atc, struct ct_atc_pcm *apcm)152{153	struct ct_vm *vm;154 155	if (!apcm->vm_block)156		return;157 158	vm = atc->vm;159 160	vm->unmap(vm, apcm->vm_block);161 162	apcm->vm_block = NULL;163}164 165static unsigned long atc_get_ptp_phys(struct ct_atc *atc, int index)166{167	return atc->vm->get_ptp_phys(atc->vm, index);168}169 170static unsigned int convert_format(snd_pcm_format_t snd_format,171				   struct snd_card *card)172{173	switch (snd_format) {174	case SNDRV_PCM_FORMAT_U8:175		return SRC_SF_U8;176	case SNDRV_PCM_FORMAT_S16_LE:177		return SRC_SF_S16;178	case SNDRV_PCM_FORMAT_S24_3LE:179		return SRC_SF_S24;180	case SNDRV_PCM_FORMAT_S32_LE:181		return SRC_SF_S32;182	case SNDRV_PCM_FORMAT_FLOAT_LE:183		return SRC_SF_F32;184	default:185		dev_err(card->dev, "not recognized snd format is %d\n",186			snd_format);187		return SRC_SF_S16;188	}189}190 191static unsigned int192atc_get_pitch(unsigned int input_rate, unsigned int output_rate)193{194	unsigned int pitch;195	int b;196 197	/* get pitch and convert to fixed-point 8.24 format. */198	pitch = (input_rate / output_rate) << 24;199	input_rate %= output_rate;200	input_rate /= 100;201	output_rate /= 100;202	for (b = 31; ((b >= 0) && !(input_rate >> b)); )203		b--;204 205	if (b >= 0) {206		input_rate <<= (31 - b);207		input_rate /= output_rate;208		b = 24 - (31 - b);209		if (b >= 0)210			input_rate <<= b;211		else212			input_rate >>= -b;213 214		pitch |= input_rate;215	}216 217	return pitch;218}219 220static int select_rom(unsigned int pitch)221{222	if (pitch > 0x00428f5c && pitch < 0x01b851ec) {223		/* 0.26 <= pitch <= 1.72 */224		return 1;225	} else if (pitch == 0x01d66666 || pitch == 0x01d66667) {226		/* pitch == 1.8375 */227		return 2;228	} else if (pitch == 0x02000000) {229		/* pitch == 2 */230		return 3;231	} else if (pitch <= 0x08000000) {232		/* 0 <= pitch <= 8 */233		return 0;234	} else {235		return -ENOENT;236	}237}238 239static int atc_pcm_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm)240{241	struct src_mgr *src_mgr = atc->rsc_mgrs[SRC];242	struct amixer_mgr *amixer_mgr = atc->rsc_mgrs[AMIXER];243	struct src_desc desc = {0};244	struct amixer_desc mix_dsc = {0};245	struct src *src;246	struct amixer *amixer;247	int err;248	int n_amixer = apcm->substream->runtime->channels, i = 0;249	int device = apcm->substream->pcm->device;250	unsigned int pitch;251 252	/* first release old resources */253	atc_pcm_release_resources(atc, apcm);254 255	/* Get SRC resource */256	desc.multi = apcm->substream->runtime->channels;257	desc.msr = atc->msr;258	desc.mode = MEMRD;259	err = src_mgr->get_src(src_mgr, &desc, (struct src **)&apcm->src);260	if (err)261		goto error1;262 263	pitch = atc_get_pitch(apcm->substream->runtime->rate,264						(atc->rsr * atc->msr));265	src = apcm->src;266	src->ops->set_pitch(src, pitch);267	src->ops->set_rom(src, select_rom(pitch));268	src->ops->set_sf(src, convert_format(apcm->substream->runtime->format,269					     atc->card));270	src->ops->set_pm(src, (src->ops->next_interleave(src) != NULL));271 272	/* Get AMIXER resource */273	n_amixer = (n_amixer < 2) ? 2 : n_amixer;274	apcm->amixers = kcalloc(n_amixer, sizeof(void *), GFP_KERNEL);275	if (!apcm->amixers) {276		err = -ENOMEM;277		goto error1;278	}279	mix_dsc.msr = atc->msr;280	for (i = 0, apcm->n_amixer = 0; i < n_amixer; i++) {281		err = amixer_mgr->get_amixer(amixer_mgr, &mix_dsc,282					(struct amixer **)&apcm->amixers[i]);283		if (err)284			goto error1;285 286		apcm->n_amixer++;287	}288 289	/* Set up device virtual mem map */290	err = ct_map_audio_buffer(atc, apcm);291	if (err < 0)292		goto error1;293 294	/* Connect resources */295	src = apcm->src;296	for (i = 0; i < n_amixer; i++) {297		amixer = apcm->amixers[i];298		mutex_lock(&atc->atc_mutex);299		amixer->ops->setup(amixer, &src->rsc,300					INIT_VOL, atc->pcm[i+device*2]);301		mutex_unlock(&atc->atc_mutex);302		src = src->ops->next_interleave(src);303		if (!src)304			src = apcm->src;305	}306 307	ct_timer_prepare(apcm->timer);308 309	return 0;310 311error1:312	atc_pcm_release_resources(atc, apcm);313	return err;314}315 316static int317atc_pcm_release_resources(struct ct_atc *atc, struct ct_atc_pcm *apcm)318{319	struct src_mgr *src_mgr = atc->rsc_mgrs[SRC];320	struct srcimp_mgr *srcimp_mgr = atc->rsc_mgrs[SRCIMP];321	struct amixer_mgr *amixer_mgr = atc->rsc_mgrs[AMIXER];322	struct sum_mgr *sum_mgr = atc->rsc_mgrs[SUM];323	struct srcimp *srcimp;324	int i;325 326	if (apcm->srcimps) {327		for (i = 0; i < apcm->n_srcimp; i++) {328			srcimp = apcm->srcimps[i];329			srcimp->ops->unmap(srcimp);330			srcimp_mgr->put_srcimp(srcimp_mgr, srcimp);331			apcm->srcimps[i] = NULL;332		}333		kfree(apcm->srcimps);334		apcm->srcimps = NULL;335	}336 337	if (apcm->srccs) {338		for (i = 0; i < apcm->n_srcc; i++) {339			src_mgr->put_src(src_mgr, apcm->srccs[i]);340			apcm->srccs[i] = NULL;341		}342		kfree(apcm->srccs);343		apcm->srccs = NULL;344	}345 346	if (apcm->amixers) {347		for (i = 0; i < apcm->n_amixer; i++) {348			amixer_mgr->put_amixer(amixer_mgr, apcm->amixers[i]);349			apcm->amixers[i] = NULL;350		}351		kfree(apcm->amixers);352		apcm->amixers = NULL;353	}354 355	if (apcm->mono) {356		sum_mgr->put_sum(sum_mgr, apcm->mono);357		apcm->mono = NULL;358	}359 360	if (apcm->src) {361		src_mgr->put_src(src_mgr, apcm->src);362		apcm->src = NULL;363	}364 365	if (apcm->vm_block) {366		/* Undo device virtual mem map */367		ct_unmap_audio_buffer(atc, apcm);368		apcm->vm_block = NULL;369	}370 371	return 0;372}373 374static int atc_pcm_playback_start(struct ct_atc *atc, struct ct_atc_pcm *apcm)375{376	unsigned int max_cisz;377	struct src *src = apcm->src;378 379	if (apcm->started)380		return 0;381	apcm->started = 1;382 383	max_cisz = src->multi * src->rsc.msr;384	max_cisz = 0x80 * (max_cisz < 8 ? max_cisz : 8);385 386	src->ops->set_sa(src, apcm->vm_block->addr);387	src->ops->set_la(src, apcm->vm_block->addr + apcm->vm_block->size);388	src->ops->set_ca(src, apcm->vm_block->addr + max_cisz);389	src->ops->set_cisz(src, max_cisz);390 391	src->ops->set_bm(src, 1);392	src->ops->set_state(src, SRC_STATE_INIT);393	src->ops->commit_write(src);394 395	ct_timer_start(apcm->timer);396	return 0;397}398 399static int atc_pcm_stop(struct ct_atc *atc, struct ct_atc_pcm *apcm)400{401	struct src *src;402	int i;403 404	ct_timer_stop(apcm->timer);405 406	src = apcm->src;407	src->ops->set_bm(src, 0);408	src->ops->set_state(src, SRC_STATE_OFF);409	src->ops->commit_write(src);410 411	if (apcm->srccs) {412		for (i = 0; i < apcm->n_srcc; i++) {413			src = apcm->srccs[i];414			src->ops->set_bm(src, 0);415			src->ops->set_state(src, SRC_STATE_OFF);416			src->ops->commit_write(src);417		}418	}419 420	apcm->started = 0;421 422	return 0;423}424 425static int426atc_pcm_playback_position(struct ct_atc *atc, struct ct_atc_pcm *apcm)427{428	struct src *src = apcm->src;429	u32 size, max_cisz;430	int position;431 432	if (!src)433		return 0;434	position = src->ops->get_ca(src);435 436	if (position < apcm->vm_block->addr) {437		dev_dbg(atc->card->dev,438			"bad ca - ca=0x%08x, vba=0x%08x, vbs=0x%08x\n",439			position, apcm->vm_block->addr, apcm->vm_block->size);440		position = apcm->vm_block->addr;441	}442 443	size = apcm->vm_block->size;444	max_cisz = src->multi * src->rsc.msr;445	max_cisz = 128 * (max_cisz < 8 ? max_cisz : 8);446 447	return (position + size - max_cisz - apcm->vm_block->addr) % size;448}449 450struct src_node_conf_t {451	unsigned int pitch;452	unsigned int msr:8;453	unsigned int mix_msr:8;454	unsigned int imp_msr:8;455	unsigned int vo:1;456};457 458static void setup_src_node_conf(struct ct_atc *atc, struct ct_atc_pcm *apcm,459				struct src_node_conf_t *conf, int *n_srcc)460{461	unsigned int pitch;462 463	/* get pitch and convert to fixed-point 8.24 format. */464	pitch = atc_get_pitch((atc->rsr * atc->msr),465				apcm->substream->runtime->rate);466	*n_srcc = 0;467 468	if (1 == atc->msr) { /* FIXME: do we really need SRC here if pitch==1 */469		*n_srcc = apcm->substream->runtime->channels;470		conf[0].pitch = pitch;471		conf[0].mix_msr = conf[0].imp_msr = conf[0].msr = 1;472		conf[0].vo = 1;473	} else if (2 <= atc->msr) {474		if (0x8000000 < pitch) {475			/* Need two-stage SRCs, SRCIMPs and476			 * AMIXERs for converting format */477			conf[0].pitch = (atc->msr << 24);478			conf[0].msr = conf[0].mix_msr = 1;479			conf[0].imp_msr = atc->msr;480			conf[0].vo = 0;481			conf[1].pitch = atc_get_pitch(atc->rsr,482					apcm->substream->runtime->rate);483			conf[1].msr = conf[1].mix_msr = conf[1].imp_msr = 1;484			conf[1].vo = 1;485			*n_srcc = apcm->substream->runtime->channels * 2;486		} else if (0x1000000 < pitch) {487			/* Need one-stage SRCs, SRCIMPs and488			 * AMIXERs for converting format */489			conf[0].pitch = pitch;490			conf[0].msr = conf[0].mix_msr491				    = conf[0].imp_msr = atc->msr;492			conf[0].vo = 1;493			*n_srcc = apcm->substream->runtime->channels;494		}495	}496}497 498static int499atc_pcm_capture_get_resources(struct ct_atc *atc, struct ct_atc_pcm *apcm)500{501	struct src_mgr *src_mgr = atc->rsc_mgrs[SRC];502	struct srcimp_mgr *srcimp_mgr = atc->rsc_mgrs[SRCIMP];503	struct amixer_mgr *amixer_mgr = atc->rsc_mgrs[AMIXER];504	struct sum_mgr *sum_mgr = atc->rsc_mgrs[SUM];505	struct src_desc src_dsc = {0};506	struct src *src;507	struct srcimp_desc srcimp_dsc = {0};508	struct srcimp *srcimp;509	struct amixer_desc mix_dsc = {0};510	struct sum_desc sum_dsc = {0};511	unsigned int pitch;512	int multi, err, i;513	int n_srcimp, n_amixer, n_srcc, n_sum;514	struct src_node_conf_t src_node_conf[2] = {{0} };515 516	/* first release old resources */517	atc_pcm_release_resources(atc, apcm);518 519	/* The numbers of converting SRCs and SRCIMPs should be determined520	 * by pitch value. */521 522	multi = apcm->substream->runtime->channels;523 524	/* get pitch and convert to fixed-point 8.24 format. */525	pitch = atc_get_pitch((atc->rsr * atc->msr),526				apcm->substream->runtime->rate);527 528	setup_src_node_conf(atc, apcm, src_node_conf, &n_srcc);529	n_sum = (1 == multi) ? 1 : 0;530	n_amixer = n_sum * 2 + n_srcc;531	n_srcimp = n_srcc;532	if ((multi > 1) && (0x8000000 >= pitch)) {533		/* Need extra AMIXERs and SRCIMPs for special treatment534		 * of interleaved recording of conjugate channels */535		n_amixer += multi * atc->msr;536		n_srcimp += multi * atc->msr;537	} else {538		n_srcimp += multi;539	}540 541	if (n_srcc) {542		apcm->srccs = kcalloc(n_srcc, sizeof(void *), GFP_KERNEL);543		if (!apcm->srccs)544			return -ENOMEM;545	}546	if (n_amixer) {547		apcm->amixers = kcalloc(n_amixer, sizeof(void *), GFP_KERNEL);548		if (!apcm->amixers) {549			err = -ENOMEM;550			goto error1;551		}552	}553	apcm->srcimps = kcalloc(n_srcimp, sizeof(void *), GFP_KERNEL);554	if (!apcm->srcimps) {555		err = -ENOMEM;556		goto error1;557	}558 559	/* Allocate SRCs for sample rate conversion if needed */560	src_dsc.multi = 1;561	src_dsc.mode = ARCRW;562	for (i = 0, apcm->n_srcc = 0; i < n_srcc; i++) {563		src_dsc.msr = src_node_conf[i/multi].msr;564		err = src_mgr->get_src(src_mgr, &src_dsc,565					(struct src **)&apcm->srccs[i]);566		if (err)567			goto error1;568 569		src = apcm->srccs[i];570		pitch = src_node_conf[i/multi].pitch;571		src->ops->set_pitch(src, pitch);572		src->ops->set_rom(src, select_rom(pitch));573		src->ops->set_vo(src, src_node_conf[i/multi].vo);574 575		apcm->n_srcc++;576	}577 578	/* Allocate AMIXERs for routing SRCs of conversion if needed */579	for (i = 0, apcm->n_amixer = 0; i < n_amixer; i++) {580		if (i < (n_sum*2))581			mix_dsc.msr = atc->msr;582		else if (i < (n_sum*2+n_srcc))583			mix_dsc.msr = src_node_conf[(i-n_sum*2)/multi].mix_msr;584		else585			mix_dsc.msr = 1;586 587		err = amixer_mgr->get_amixer(amixer_mgr, &mix_dsc,588					(struct amixer **)&apcm->amixers[i]);589		if (err)590			goto error1;591 592		apcm->n_amixer++;593	}594 595	/* Allocate a SUM resource to mix all input channels together */596	sum_dsc.msr = atc->msr;597	err = sum_mgr->get_sum(sum_mgr, &sum_dsc, (struct sum **)&apcm->mono);598	if (err)599		goto error1;600 601	pitch = atc_get_pitch((atc->rsr * atc->msr),602				apcm->substream->runtime->rate);603	/* Allocate SRCIMP resources */604	for (i = 0, apcm->n_srcimp = 0; i < n_srcimp; i++) {605		if (i < (n_srcc))606			srcimp_dsc.msr = src_node_conf[i/multi].imp_msr;607		else if (1 == multi)608			srcimp_dsc.msr = (pitch <= 0x8000000) ? atc->msr : 1;609		else610			srcimp_dsc.msr = 1;611 612		err = srcimp_mgr->get_srcimp(srcimp_mgr, &srcimp_dsc, &srcimp);613		if (err)614			goto error1;615 616		apcm->srcimps[i] = srcimp;617		apcm->n_srcimp++;618	}619 620	/* Allocate a SRC for writing data to host memory */621	src_dsc.multi = apcm->substream->runtime->channels;622	src_dsc.msr = 1;623	src_dsc.mode = MEMWR;624	err = src_mgr->get_src(src_mgr, &src_dsc, (struct src **)&apcm->src);625	if (err)626		goto error1;627 628	src = apcm->src;629	src->ops->set_pitch(src, pitch);630 631	/* Set up device virtual mem map */632	err = ct_map_audio_buffer(atc, apcm);633	if (err < 0)634		goto error1;635 636	return 0;637 638error1:639	atc_pcm_release_resources(atc, apcm);640	return err;641}642 643static int atc_pcm_capture_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm)644{645	struct src *src;646	struct amixer *amixer;647	struct srcimp *srcimp;648	struct ct_mixer *mixer = atc->mixer;649	struct sum *mono;650	struct rsc *out_ports[8] = {NULL};651	int err, i, j, n_sum, multi;652	unsigned int pitch;653	int mix_base = 0, imp_base = 0;654 655	atc_pcm_release_resources(atc, apcm);656 657	/* Get needed resources. */658	err = atc_pcm_capture_get_resources(atc, apcm);659	if (err)660		return err;661 662	/* Connect resources */663	mixer->get_output_ports(mixer, MIX_PCMO_FRONT,664				&out_ports[0], &out_ports[1]);665 666	multi = apcm->substream->runtime->channels;667	if (1 == multi) {668		mono = apcm->mono;669		for (i = 0; i < 2; i++) {670			amixer = apcm->amixers[i];671			amixer->ops->setup(amixer, out_ports[i],672						MONO_SUM_SCALE, mono);673		}674		out_ports[0] = &mono->rsc;675		n_sum = 1;676		mix_base = n_sum * 2;677	}678 679	for (i = 0; i < apcm->n_srcc; i++) {680		src = apcm->srccs[i];681		srcimp = apcm->srcimps[imp_base+i];682		amixer = apcm->amixers[mix_base+i];683		srcimp->ops->map(srcimp, src, out_ports[i%multi]);684		amixer->ops->setup(amixer, &src->rsc, INIT_VOL, NULL);685		out_ports[i%multi] = &amixer->rsc;686	}687 688	pitch = atc_get_pitch((atc->rsr * atc->msr),689				apcm->substream->runtime->rate);690 691	if ((multi > 1) && (pitch <= 0x8000000)) {692		/* Special connection for interleaved693		 * recording with conjugate channels */694		for (i = 0; i < multi; i++) {695			out_ports[i]->ops->master(out_ports[i]);696			for (j = 0; j < atc->msr; j++) {697				amixer = apcm->amixers[apcm->n_srcc+j*multi+i];698				amixer->ops->set_input(amixer, out_ports[i]);699				amixer->ops->set_scale(amixer, INIT_VOL);700				amixer->ops->set_sum(amixer, NULL);701				amixer->ops->commit_raw_write(amixer);702				out_ports[i]->ops->next_conj(out_ports[i]);703 704				srcimp = apcm->srcimps[apcm->n_srcc+j*multi+i];705				srcimp->ops->map(srcimp, apcm->src,706							&amixer->rsc);707			}708		}709	} else {710		for (i = 0; i < multi; i++) {711			srcimp = apcm->srcimps[apcm->n_srcc+i];712			srcimp->ops->map(srcimp, apcm->src, out_ports[i]);713		}714	}715 716	ct_timer_prepare(apcm->timer);717 718	return 0;719}720 721static int atc_pcm_capture_start(struct ct_atc *atc, struct ct_atc_pcm *apcm)722{723	struct src *src;724	struct src_mgr *src_mgr = atc->rsc_mgrs[SRC];725	int i, multi;726 727	if (apcm->started)728		return 0;729 730	apcm->started = 1;731	multi = apcm->substream->runtime->channels;732	/* Set up converting SRCs */733	for (i = 0; i < apcm->n_srcc; i++) {734		src = apcm->srccs[i];735		src->ops->set_pm(src, ((i%multi) != (multi-1)));736		src_mgr->src_disable(src_mgr, src);737	}738 739	/*  Set up recording SRC */740	src = apcm->src;741	src->ops->set_sf(src, convert_format(apcm->substream->runtime->format,742					     atc->card));743	src->ops->set_sa(src, apcm->vm_block->addr);744	src->ops->set_la(src, apcm->vm_block->addr + apcm->vm_block->size);745	src->ops->set_ca(src, apcm->vm_block->addr);746	src_mgr->src_disable(src_mgr, src);747 748	/* Disable relevant SRCs firstly */749	src_mgr->commit_write(src_mgr);750 751	/* Enable SRCs respectively */752	for (i = 0; i < apcm->n_srcc; i++) {753		src = apcm->srccs[i];754		src->ops->set_state(src, SRC_STATE_RUN);755		src->ops->commit_write(src);756		src_mgr->src_enable_s(src_mgr, src);757	}758	src = apcm->src;759	src->ops->set_bm(src, 1);760	src->ops->set_state(src, SRC_STATE_RUN);761	src->ops->commit_write(src);762	src_mgr->src_enable_s(src_mgr, src);763 764	/* Enable relevant SRCs synchronously */765	src_mgr->commit_write(src_mgr);766 767	ct_timer_start(apcm->timer);768	return 0;769}770 771static int772atc_pcm_capture_position(struct ct_atc *atc, struct ct_atc_pcm *apcm)773{774	struct src *src = apcm->src;775 776	if (!src)777		return 0;778	return src->ops->get_ca(src) - apcm->vm_block->addr;779}780 781static int spdif_passthru_playback_get_resources(struct ct_atc *atc,782						 struct ct_atc_pcm *apcm)783{784	struct src_mgr *src_mgr = atc->rsc_mgrs[SRC];785	struct amixer_mgr *amixer_mgr = atc->rsc_mgrs[AMIXER];786	struct src_desc desc = {0};787	struct amixer_desc mix_dsc = {0};788	struct src *src;789	int err;790	int n_amixer = apcm->substream->runtime->channels, i;791	unsigned int pitch, rsr = atc->pll_rate;792 793	/* first release old resources */794	atc_pcm_release_resources(atc, apcm);795 796	/* Get SRC resource */797	desc.multi = apcm->substream->runtime->channels;798	desc.msr = 1;799	while (apcm->substream->runtime->rate > (rsr * desc.msr))800		desc.msr <<= 1;801 802	desc.mode = MEMRD;803	err = src_mgr->get_src(src_mgr, &desc, (struct src **)&apcm->src);804	if (err)805		goto error1;806 807	pitch = atc_get_pitch(apcm->substream->runtime->rate, (rsr * desc.msr));808	src = apcm->src;809	src->ops->set_pitch(src, pitch);810	src->ops->set_rom(src, select_rom(pitch));811	src->ops->set_sf(src, convert_format(apcm->substream->runtime->format,812					     atc->card));813	src->ops->set_pm(src, (src->ops->next_interleave(src) != NULL));814	src->ops->set_bp(src, 1);815 816	/* Get AMIXER resource */817	n_amixer = (n_amixer < 2) ? 2 : n_amixer;818	apcm->amixers = kcalloc(n_amixer, sizeof(void *), GFP_KERNEL);819	if (!apcm->amixers) {820		err = -ENOMEM;821		goto error1;822	}823	mix_dsc.msr = desc.msr;824	for (i = 0, apcm->n_amixer = 0; i < n_amixer; i++) {825		err = amixer_mgr->get_amixer(amixer_mgr, &mix_dsc,826					(struct amixer **)&apcm->amixers[i]);827		if (err)828			goto error1;829 830		apcm->n_amixer++;831	}832 833	/* Set up device virtual mem map */834	err = ct_map_audio_buffer(atc, apcm);835	if (err < 0)836		goto error1;837 838	return 0;839 840error1:841	atc_pcm_release_resources(atc, apcm);842	return err;843}844 845static int atc_pll_init(struct ct_atc *atc, int rate)846{847	struct hw *hw = atc->hw;848	int err;849	err = hw->pll_init(hw, rate);850	atc->pll_rate = err ? 0 : rate;851	return err;852}853 854static int855spdif_passthru_playback_setup(struct ct_atc *atc, struct ct_atc_pcm *apcm)856{857	struct dao *dao = container_of(atc->daios[SPDIFOO], struct dao, daio);858	unsigned int rate = apcm->substream->runtime->rate;859	unsigned int status;860	int err = 0;861	unsigned char iec958_con_fs;862 863	switch (rate) {864	case 48000:865		iec958_con_fs = IEC958_AES3_CON_FS_48000;866		break;867	case 44100:868		iec958_con_fs = IEC958_AES3_CON_FS_44100;869		break;870	case 32000:871		iec958_con_fs = IEC958_AES3_CON_FS_32000;872		break;873	default:874		return -ENOENT;875	}876 877	mutex_lock(&atc->atc_mutex);878	dao->ops->get_spos(dao, &status);879	if (((status >> 24) & IEC958_AES3_CON_FS) != iec958_con_fs) {880		status &= ~(IEC958_AES3_CON_FS << 24);881		status |= (iec958_con_fs << 24);882		dao->ops->set_spos(dao, status);883		dao->ops->commit_write(dao);884	}885	if ((rate != atc->pll_rate) && (32000 != rate))886		err = atc_pll_init(atc, rate);887	mutex_unlock(&atc->atc_mutex);888 889	return err;890}891 892static int893spdif_passthru_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm)894{895	struct src *src;896	struct amixer *amixer;897	struct dao *dao;898	int err;899	int i;900 901	atc_pcm_release_resources(atc, apcm);902 903	/* Configure SPDIFOO and PLL to passthrough mode;904	 * determine pll_rate. */905	err = spdif_passthru_playback_setup(atc, apcm);906	if (err)907		return err;908 909	/* Get needed resources. */910	err = spdif_passthru_playback_get_resources(atc, apcm);911	if (err)912		return err;913 914	/* Connect resources */915	src = apcm->src;916	for (i = 0; i < apcm->n_amixer; i++) {917		amixer = apcm->amixers[i];918		amixer->ops->setup(amixer, &src->rsc, INIT_VOL, NULL);919		src = src->ops->next_interleave(src);920		if (!src)921			src = apcm->src;922	}923	/* Connect to SPDIFOO */924	mutex_lock(&atc->atc_mutex);925	dao = container_of(atc->daios[SPDIFOO], struct dao, daio);926	amixer = apcm->amixers[0];927	dao->ops->set_left_input(dao, &amixer->rsc);928	amixer = apcm->amixers[1];929	dao->ops->set_right_input(dao, &amixer->rsc);930	mutex_unlock(&atc->atc_mutex);931 932	ct_timer_prepare(apcm->timer);933 934	return 0;935}936 937static int atc_select_line_in(struct ct_atc *atc)938{939	struct hw *hw = atc->hw;940	struct ct_mixer *mixer = atc->mixer;941	struct src *src;942 943	if (hw->is_adc_source_selected(hw, ADC_LINEIN))944		return 0;945 946	mixer->set_input_left(mixer, MIX_MIC_IN, NULL);947	mixer->set_input_right(mixer, MIX_MIC_IN, NULL);948 949	hw->select_adc_source(hw, ADC_LINEIN);950 951	src = atc->srcs[2];952	mixer->set_input_left(mixer, MIX_LINE_IN, &src->rsc);953	src = atc->srcs[3];954	mixer->set_input_right(mixer, MIX_LINE_IN, &src->rsc);955 956	return 0;957}958 959static int atc_select_mic_in(struct ct_atc *atc)960{961	struct hw *hw = atc->hw;962	struct ct_mixer *mixer = atc->mixer;963	struct src *src;964 965	if (hw->is_adc_source_selected(hw, ADC_MICIN))966		return 0;967 968	mixer->set_input_left(mixer, MIX_LINE_IN, NULL);969	mixer->set_input_right(mixer, MIX_LINE_IN, NULL);970 971	hw->select_adc_source(hw, ADC_MICIN);972 973	src = atc->srcs[2];974	mixer->set_input_left(mixer, MIX_MIC_IN, &src->rsc);975	src = atc->srcs[3];976	mixer->set_input_right(mixer, MIX_MIC_IN, &src->rsc);977 978	return 0;979}980 981static struct capabilities atc_capabilities(struct ct_atc *atc)982{983	struct hw *hw = atc->hw;984 985	return hw->capabilities(hw);986}987 988static int atc_output_switch_get(struct ct_atc *atc)989{990	struct hw *hw = atc->hw;991 992	return hw->output_switch_get(hw);993}994 995static int atc_output_switch_put(struct ct_atc *atc, int position)996{997	struct hw *hw = atc->hw;998 999	return hw->output_switch_put(hw, position);1000}1001 1002static int atc_mic_source_switch_get(struct ct_atc *atc)1003{1004	struct hw *hw = atc->hw;1005 1006	return hw->mic_source_switch_get(hw);1007}1008 1009static int atc_mic_source_switch_put(struct ct_atc *atc, int position)1010{1011	struct hw *hw = atc->hw;1012 1013	return hw->mic_source_switch_put(hw, position);1014}1015 1016static int atc_select_digit_io(struct ct_atc *atc)1017{1018	struct hw *hw = atc->hw;1019 1020	if (hw->is_adc_source_selected(hw, ADC_NONE))1021		return 0;1022 1023	hw->select_adc_source(hw, ADC_NONE);1024 1025	return 0;1026}1027 1028static int atc_daio_unmute(struct ct_atc *atc, unsigned char state, int type)1029{1030	struct daio_mgr *daio_mgr = atc->rsc_mgrs[DAIO];1031 1032	if (state)1033		daio_mgr->daio_enable(daio_mgr, atc->daios[type]);1034	else1035		daio_mgr->daio_disable(daio_mgr, atc->daios[type]);1036 1037	daio_mgr->commit_write(daio_mgr);1038 1039	return 0;1040}1041 1042static int1043atc_dao_get_status(struct ct_atc *atc, unsigned int *status, int type)1044{1045	struct dao *dao = container_of(atc->daios[type], struct dao, daio);1046	return dao->ops->get_spos(dao, status);1047}1048 1049static int1050atc_dao_set_status(struct ct_atc *atc, unsigned int status, int type)1051{1052	struct dao *dao = container_of(atc->daios[type], struct dao, daio);1053 1054	dao->ops->set_spos(dao, status);1055	dao->ops->commit_write(dao);1056	return 0;1057}1058 1059static int atc_line_front_unmute(struct ct_atc *atc, unsigned char state)1060{1061	return atc_daio_unmute(atc, state, LINEO1);1062}1063 1064static int atc_line_surround_unmute(struct ct_atc *atc, unsigned char state)1065{1066	return atc_daio_unmute(atc, state, LINEO2);1067}1068 1069static int atc_line_clfe_unmute(struct ct_atc *atc, unsigned char state)1070{1071	return atc_daio_unmute(atc, state, LINEO3);1072}1073 1074static int atc_line_rear_unmute(struct ct_atc *atc, unsigned char state)1075{1076	return atc_daio_unmute(atc, state, LINEO4);1077}1078 1079static int atc_line_in_unmute(struct ct_atc *atc, unsigned char state)1080{1081	return atc_daio_unmute(atc, state, LINEIM);1082}1083 1084static int atc_mic_unmute(struct ct_atc *atc, unsigned char state)1085{1086	return atc_daio_unmute(atc, state, MIC);1087}1088 1089static int atc_spdif_out_unmute(struct ct_atc *atc, unsigned char state)1090{1091	return atc_daio_unmute(atc, state, SPDIFOO);1092}1093 1094static int atc_spdif_in_unmute(struct ct_atc *atc, unsigned char state)1095{1096	return atc_daio_unmute(atc, state, SPDIFIO);1097}1098 1099static int atc_spdif_out_get_status(struct ct_atc *atc, unsigned int *status)1100{1101	return atc_dao_get_status(atc, status, SPDIFOO);1102}1103 1104static int atc_spdif_out_set_status(struct ct_atc *atc, unsigned int status)1105{1106	return atc_dao_set_status(atc, status, SPDIFOO);1107}1108 1109static int atc_spdif_out_passthru(struct ct_atc *atc, unsigned char state)1110{1111	struct dao_desc da_dsc = {0};1112	struct dao *dao;1113	int err;1114	struct ct_mixer *mixer = atc->mixer;1115	struct rsc *rscs[2] = {NULL};1116	unsigned int spos = 0;1117 1118	mutex_lock(&atc->atc_mutex);1119	dao = container_of(atc->daios[SPDIFOO], struct dao, daio);1120	da_dsc.msr = state ? 1 : atc->msr;1121	da_dsc.passthru = state ? 1 : 0;1122	err = dao->ops->reinit(dao, &da_dsc);1123	if (state) {1124		spos = IEC958_DEFAULT_CON;1125	} else {1126		mixer->get_output_ports(mixer, MIX_SPDIF_OUT,1127					&rscs[0], &rscs[1]);1128		dao->ops->set_left_input(dao, rscs[0]);1129		dao->ops->set_right_input(dao, rscs[1]);1130		/* Restore PLL to atc->rsr if needed. */1131		if (atc->pll_rate != atc->rsr)1132			err = atc_pll_init(atc, atc->rsr);1133	}1134	dao->ops->set_spos(dao, spos);1135	dao->ops->commit_write(dao);1136	mutex_unlock(&atc->atc_mutex);1137 1138	return err;1139}1140 1141static int atc_release_resources(struct ct_atc *atc)1142{1143	int i;1144	struct daio_mgr *daio_mgr = NULL;1145	struct dao *dao = NULL;1146	struct daio *daio = NULL;1147	struct sum_mgr *sum_mgr = NULL;1148	struct src_mgr *src_mgr = NULL;1149	struct srcimp_mgr *srcimp_mgr = NULL;1150	struct srcimp *srcimp = NULL;1151	struct ct_mixer *mixer = NULL;1152 1153	/* disconnect internal mixer objects */1154	if (atc->mixer) {1155		mixer = atc->mixer;1156		mixer->set_input_left(mixer, MIX_LINE_IN, NULL);1157		mixer->set_input_right(mixer, MIX_LINE_IN, NULL);1158		mixer->set_input_left(mixer, MIX_MIC_IN, NULL);1159		mixer->set_input_right(mixer, MIX_MIC_IN, NULL);1160		mixer->set_input_left(mixer, MIX_SPDIF_IN, NULL);1161		mixer->set_input_right(mixer, MIX_SPDIF_IN, NULL);1162	}1163 1164	if (atc->daios) {1165		daio_mgr = (struct daio_mgr *)atc->rsc_mgrs[DAIO];1166		for (i = 0; i < atc->n_daio; i++) {1167			daio = atc->daios[i];1168			if (daio->type < LINEIM) {1169				dao = container_of(daio, struct dao, daio);1170				dao->ops->clear_left_input(dao);1171				dao->ops->clear_right_input(dao);1172			}1173			daio_mgr->put_daio(daio_mgr, daio);1174		}1175		kfree(atc->daios);1176		atc->daios = NULL;1177	}1178 1179	if (atc->pcm) {1180		sum_mgr = atc->rsc_mgrs[SUM];1181		for (i = 0; i < atc->n_pcm; i++)1182			sum_mgr->put_sum(sum_mgr, atc->pcm[i]);1183 1184		kfree(atc->pcm);1185		atc->pcm = NULL;1186	}1187 1188	if (atc->srcs) {1189		src_mgr = atc->rsc_mgrs[SRC];1190		for (i = 0; i < atc->n_src; i++)1191			src_mgr->put_src(src_mgr, atc->srcs[i]);1192 1193		kfree(atc->srcs);1194		atc->srcs = NULL;1195	}1196 1197	if (atc->srcimps) {1198		srcimp_mgr = atc->rsc_mgrs[SRCIMP];1199		for (i = 0; i < atc->n_srcimp; i++) {1200			srcimp = atc->srcimps[i];1201			srcimp->ops->unmap(srcimp);1202			srcimp_mgr->put_srcimp(srcimp_mgr, atc->srcimps[i]);1203		}1204		kfree(atc->srcimps);1205		atc->srcimps = NULL;1206	}1207 1208	return 0;1209}1210 1211static int ct_atc_destroy(struct ct_atc *atc)1212{1213	int i = 0;1214 1215	if (!atc)1216		return 0;1217 1218	if (atc->timer) {1219		ct_timer_free(atc->timer);1220		atc->timer = NULL;1221	}1222 1223	atc_release_resources(atc);1224 1225	/* Destroy internal mixer objects */1226	if (atc->mixer)1227		ct_mixer_destroy(atc->mixer);1228 1229	for (i = 0; i < NUM_RSCTYP; i++) {1230		if (rsc_mgr_funcs[i].destroy && atc->rsc_mgrs[i])1231			rsc_mgr_funcs[i].destroy(atc->rsc_mgrs[i]);1232 1233	}1234 1235	if (atc->hw)1236		destroy_hw_obj(atc->hw);1237 1238	/* Destroy device virtual memory manager object */1239	if (atc->vm) {1240		ct_vm_destroy(atc->vm);1241		atc->vm = NULL;1242	}1243 1244	kfree(atc);1245 1246	return 0;1247}1248 1249static int atc_dev_free(struct snd_device *dev)1250{1251	struct ct_atc *atc = dev->device_data;1252	return ct_atc_destroy(atc);1253}1254 1255static int atc_identify_card(struct ct_atc *atc, unsigned int ssid)1256{1257	const struct snd_pci_quirk *p;1258	const struct snd_pci_quirk *list;1259	u16 vendor_id, device_id;1260 1261	switch (atc->chip_type) {1262	case ATC20K1:1263		atc->chip_name = "20K1";1264		list = subsys_20k1_list;1265		break;1266	case ATC20K2:1267		atc->chip_name = "20K2";1268		list = subsys_20k2_list;1269		break;1270	default:1271		return -ENOENT;1272	}1273	if (ssid) {1274		vendor_id = ssid >> 16;1275		device_id = ssid & 0xffff;1276	} else {1277		vendor_id = atc->pci->subsystem_vendor;1278		device_id = atc->pci->subsystem_device;1279	}1280	p = snd_pci_quirk_lookup_id(vendor_id, device_id, list);1281	if (p) {1282		if (p->value < 0) {1283			dev_err(atc->card->dev,1284				"Device %04x:%04x is on the denylist\n",1285				vendor_id, device_id);1286			return -ENOENT;1287		}1288		atc->model = p->value;1289	} else {1290		if (atc->chip_type == ATC20K1)1291			atc->model = CT20K1_UNKNOWN;1292		else1293			atc->model = CT20K2_UNKNOWN;1294	}1295	atc->model_name = ct_subsys_name[atc->model];1296	dev_info(atc->card->dev, "chip %s model %s (%04x:%04x) is found\n",1297		   atc->chip_name, atc->model_name,1298		   vendor_id, device_id);1299	return 0;1300}1301 1302int ct_atc_create_alsa_devs(struct ct_atc *atc)1303{1304	enum CTALSADEVS i;1305	int err;1306 1307	alsa_dev_funcs[MIXER].public_name = atc->chip_name;1308 1309	for (i = 0; i < NUM_CTALSADEVS; i++) {1310		if (!alsa_dev_funcs[i].create)1311			continue;1312 1313		err = alsa_dev_funcs[i].create(atc, i,1314				alsa_dev_funcs[i].public_name);1315		if (err) {1316			dev_err(atc->card->dev,1317				"Creating alsa device %d failed!\n", i);1318			return err;1319		}1320	}1321 1322	return 0;1323}1324 1325static int atc_create_hw_devs(struct ct_atc *atc)1326{1327	struct hw *hw;1328	struct card_conf info = {0};1329	int i, err;1330 1331	err = create_hw_obj(atc->pci, atc->chip_type, atc->model, &hw);1332	if (err) {1333		dev_err(atc->card->dev, "Failed to create hw obj!!!\n");1334		return err;1335	}1336	hw->card = atc->card;1337	atc->hw = hw;1338 1339	/* Initialize card hardware. */1340	info.rsr = atc->rsr;1341	info.msr = atc->msr;1342	info.vm_pgt_phys = atc_get_ptp_phys(atc, 0);1343	err = hw->card_init(hw, &info);1344	if (err < 0)1345		return err;1346 1347	for (i = 0; i < NUM_RSCTYP; i++) {1348		if (!rsc_mgr_funcs[i].create)1349			continue;1350 1351		err = rsc_mgr_funcs[i].create(atc->hw, &atc->rsc_mgrs[i]);1352		if (err) {1353			dev_err(atc->card->dev,1354				"Failed to create rsc_mgr %d!!!\n", i);1355			return err;1356		}1357	}1358 1359	return 0;1360}1361 1362static int atc_get_resources(struct ct_atc *atc)1363{1364	struct daio_desc da_desc = {0};1365	struct daio_mgr *daio_mgr;1366	struct src_desc src_dsc = {0};1367	struct src_mgr *src_mgr;1368	struct srcimp_desc srcimp_dsc = {0};1369	struct srcimp_mgr *srcimp_mgr;1370	struct sum_desc sum_dsc = {0};1371	struct sum_mgr *sum_mgr;1372	int err, i, num_srcs, num_daios;1373 1374	num_daios = ((atc->model == CTSB1270) ? 8 : 7);1375	num_srcs = ((atc->model == CTSB1270) ? 6 : 4);1376 1377	atc->daios = kcalloc(num_daios, sizeof(void *), GFP_KERNEL);1378	if (!atc->daios)1379		return -ENOMEM;1380 1381	atc->srcs = kcalloc(num_srcs, sizeof(void *), GFP_KERNEL);1382	if (!atc->srcs)1383		return -ENOMEM;1384 1385	atc->srcimps = kcalloc(num_srcs, sizeof(void *), GFP_KERNEL);1386	if (!atc->srcimps)1387		return -ENOMEM;1388 1389	atc->pcm = kcalloc(2 * 4, sizeof(void *), GFP_KERNEL);1390	if (!atc->pcm)1391		return -ENOMEM;1392 1393	daio_mgr = (struct daio_mgr *)atc->rsc_mgrs[DAIO];1394	da_desc.msr = atc->msr;1395	for (i = 0, atc->n_daio = 0; i < num_daios; i++) {1396		da_desc.type = (atc->model != CTSB073X) ? i :1397			     ((i == SPDIFIO) ? SPDIFI1 : i);1398		err = daio_mgr->get_daio(daio_mgr, &da_desc,1399					(struct daio **)&atc->daios[i]);1400		if (err) {1401			dev_err(atc->card->dev,1402				"Failed to get DAIO resource %d!!!\n",1403				i);1404			return err;1405		}1406		atc->n_daio++;1407	}1408 1409	src_mgr = atc->rsc_mgrs[SRC];1410	src_dsc.multi = 1;1411	src_dsc.msr = atc->msr;1412	src_dsc.mode = ARCRW;1413	for (i = 0, atc->n_src = 0; i < num_srcs; i++) {1414		err = src_mgr->get_src(src_mgr, &src_dsc,1415					(struct src **)&atc->srcs[i]);1416		if (err)1417			return err;1418 1419		atc->n_src++;1420	}1421 1422	srcimp_mgr = atc->rsc_mgrs[SRCIMP];1423	srcimp_dsc.msr = 8;1424	for (i = 0, atc->n_srcimp = 0; i < num_srcs; i++) {1425		err = srcimp_mgr->get_srcimp(srcimp_mgr, &srcimp_dsc,1426					(struct srcimp **)&atc->srcimps[i]);1427		if (err)1428			return err;1429 1430		atc->n_srcimp++;1431	}1432 1433	sum_mgr = atc->rsc_mgrs[SUM];1434	sum_dsc.msr = atc->msr;1435	for (i = 0, atc->n_pcm = 0; i < (2*4); i++) {1436		err = sum_mgr->get_sum(sum_mgr, &sum_dsc,1437					(struct sum **)&atc->pcm[i]);1438		if (err)1439			return err;1440 1441		atc->n_pcm++;1442	}1443 1444	return 0;1445}1446 1447static void1448atc_connect_dai(struct src_mgr *src_mgr, struct dai *dai,1449		struct src **srcs, struct srcimp **srcimps)1450{1451	struct rsc *rscs[2] = {NULL};1452	struct src *src;1453	struct srcimp *srcimp;1454	int i = 0;1455 1456	rscs[0] = &dai->daio.rscl;1457	rscs[1] = &dai->daio.rscr;1458	for (i = 0; i < 2; i++) {1459		src = srcs[i];1460		srcimp = srcimps[i];1461		srcimp->ops->map(srcimp, src, rscs[i]);1462		src_mgr->src_disable(src_mgr, src);1463	}1464 1465	src_mgr->commit_write(src_mgr); /* Actually disable SRCs */1466 1467	src = srcs[0];1468	src->ops->set_pm(src, 1);1469	for (i = 0; i < 2; i++) {1470		src = srcs[i];1471		src->ops->set_state(src, SRC_STATE_RUN);1472		src->ops->commit_write(src);1473		src_mgr->src_enable_s(src_mgr, src);1474	}1475 1476	dai->ops->set_srt_srcl(dai, &(srcs[0]->rsc));1477	dai->ops->set_srt_srcr(dai, &(srcs[1]->rsc));1478 1479	dai->ops->set_enb_src(dai, 1);1480	dai->ops->set_enb_srt(dai, 1);1481	dai->ops->commit_write(dai);1482 1483	src_mgr->commit_write(src_mgr); /* Synchronously enable SRCs */1484}1485 1486static void atc_connect_resources(struct ct_atc *atc)1487{1488	struct dai *dai;1489	struct dao *dao;1490	struct src *src;1491	struct sum *sum;1492	struct ct_mixer *mixer;1493	struct rsc *rscs[2] = {NULL};1494	int i, j;1495 1496	mixer = atc->mixer;1497 1498	for (i = MIX_WAVE_FRONT, j = LINEO1; i <= MIX_SPDIF_OUT; i++, j++) {1499		mixer->get_output_ports(mixer, i, &rscs[0], &rscs[1]);1500		dao = container_of(atc->daios[j], struct dao, daio);1501		dao->ops->set_left_input(dao, rscs[0]);1502		dao->ops->set_right_input(dao, rscs[1]);1503	}1504 1505	dai = container_of(atc->daios[LINEIM], struct dai, daio);1506	atc_connect_dai(atc->rsc_mgrs[SRC], dai,1507			(struct src **)&atc->srcs[2],1508			(struct srcimp **)&atc->srcimps[2]);1509	src = atc->srcs[2];1510	mixer->set_input_left(mixer, MIX_LINE_IN, &src->rsc);1511	src = atc->srcs[3];1512	mixer->set_input_right(mixer, MIX_LINE_IN, &src->rsc);1513 1514	if (atc->model == CTSB1270) {1515		/* Titanium HD has a dedicated ADC for the Mic. */1516		dai = container_of(atc->daios[MIC], struct dai, daio);1517		atc_connect_dai(atc->rsc_mgrs[SRC], dai,1518			(struct src **)&atc->srcs[4],1519			(struct srcimp **)&atc->srcimps[4]);1520		src = atc->srcs[4];1521		mixer->set_input_left(mixer, MIX_MIC_IN, &src->rsc);1522		src = atc->srcs[5];1523		mixer->set_input_right(mixer, MIX_MIC_IN, &src->rsc);1524	}1525 1526	dai = container_of(atc->daios[SPDIFIO], struct dai, daio);1527	atc_connect_dai(atc->rsc_mgrs[SRC], dai,1528			(struct src **)&atc->srcs[0],1529			(struct srcimp **)&atc->srcimps[0]);1530 1531	src = atc->srcs[0];1532	mixer->set_input_left(mixer, MIX_SPDIF_IN, &src->rsc);1533	src = atc->srcs[1];1534	mixer->set_input_right(mixer, MIX_SPDIF_IN, &src->rsc);1535 1536	for (i = MIX_PCMI_FRONT, j = 0; i <= MIX_PCMI_SURROUND; i++, j += 2) {1537		sum = atc->pcm[j];1538		mixer->set_input_left(mixer, i, &sum->rsc);1539		sum = atc->pcm[j+1];1540		mixer->set_input_right(mixer, i, &sum->rsc);1541	}1542}1543 1544#ifdef CONFIG_PM_SLEEP1545static int atc_suspend(struct ct_atc *atc)1546{1547	struct hw *hw = atc->hw;1548 1549	snd_power_change_state(atc->card, SNDRV_CTL_POWER_D3hot);1550 1551	atc_release_resources(atc);1552 1553	hw->suspend(hw);1554 1555	return 0;1556}1557 1558static int atc_hw_resume(struct ct_atc *atc)1559{1560	struct hw *hw = atc->hw;1561	struct card_conf info = {0};1562 1563	/* Re-initialize card hardware. */1564	info.rsr = atc->rsr;1565	info.msr = atc->msr;1566	info.vm_pgt_phys = atc_get_ptp_phys(atc, 0);1567	return hw->resume(hw, &info);1568}1569 1570static int atc_resources_resume(struct ct_atc *atc)1571{1572	struct ct_mixer *mixer;1573	int err = 0;1574 1575	/* Get resources */1576	err = atc_get_resources(atc);1577	if (err < 0) {1578		atc_release_resources(atc);1579		return err;1580	}1581 1582	/* Build topology */1583	atc_connect_resources(atc);1584 1585	mixer = atc->mixer;1586	mixer->resume(mixer);1587 1588	return 0;1589}1590 1591static int atc_resume(struct ct_atc *atc)1592{1593	int err = 0;1594 1595	/* Do hardware resume. */1596	err = atc_hw_resume(atc);1597	if (err < 0) {1598		dev_err(atc->card->dev,1599			"pci_enable_device failed, disabling device\n");1600		snd_card_disconnect(atc->card);1601		return err;1602	}1603 1604	err = atc_resources_resume(atc);1605	if (err < 0)1606		return err;1607 1608	snd_power_change_state(atc->card, SNDRV_CTL_POWER_D0);1609 1610	return 0;1611}1612#endif1613 1614static const struct ct_atc atc_preset = {1615	.map_audio_buffer = ct_map_audio_buffer,1616	.unmap_audio_buffer = ct_unmap_audio_buffer,1617	.pcm_playback_prepare = atc_pcm_playback_prepare,1618	.pcm_release_resources = atc_pcm_release_resources,1619	.pcm_playback_start = atc_pcm_playback_start,1620	.pcm_playback_stop = atc_pcm_stop,1621	.pcm_playback_position = atc_pcm_playback_position,1622	.pcm_capture_prepare = atc_pcm_capture_prepare,1623	.pcm_capture_start = atc_pcm_capture_start,1624	.pcm_capture_stop = atc_pcm_stop,1625	.pcm_capture_position = atc_pcm_capture_position,1626	.spdif_passthru_playback_prepare = spdif_passthru_playback_prepare,1627	.get_ptp_phys = atc_get_ptp_phys,1628	.select_line_in = atc_select_line_in,1629	.select_mic_in = atc_select_mic_in,1630	.select_digit_io = atc_select_digit_io,1631	.line_front_unmute = atc_line_front_unmute,1632	.line_surround_unmute = atc_line_surround_unmute,1633	.line_clfe_unmute = atc_line_clfe_unmute,1634	.line_rear_unmute = atc_line_rear_unmute,1635	.line_in_unmute = atc_line_in_unmute,1636	.mic_unmute = atc_mic_unmute,1637	.spdif_out_unmute = atc_spdif_out_unmute,1638	.spdif_in_unmute = atc_spdif_in_unmute,1639	.spdif_out_get_status = atc_spdif_out_get_status,1640	.spdif_out_set_status = atc_spdif_out_set_status,1641	.spdif_out_passthru = atc_spdif_out_passthru,1642	.capabilities = atc_capabilities,1643	.output_switch_get = atc_output_switch_get,1644	.output_switch_put = atc_output_switch_put,1645	.mic_source_switch_get = atc_mic_source_switch_get,1646	.mic_source_switch_put = atc_mic_source_switch_put,1647#ifdef CONFIG_PM_SLEEP1648	.suspend = atc_suspend,1649	.resume = atc_resume,1650#endif1651};1652 1653/**1654 *  ct_atc_create - create and initialize a hardware manager1655 *  @card: corresponding alsa card object1656 *  @pci: corresponding kernel pci device object1657 *  @rsr: reference sampling rate1658 *  @msr: master sampling rate1659 *  @chip_type: CHIPTYP enum values1660 *  @ssid: vendor ID (upper 16 bits) and device ID (lower 16 bits)1661 *  @ratc: return created object address in it1662 *1663 *  Creates and initializes a hardware manager.1664 *1665 *  Creates kmallocated ct_atc structure. Initializes hardware.1666 *  Returns 0 if succeeds, or negative error code if fails.1667 */1668 1669int ct_atc_create(struct snd_card *card, struct pci_dev *pci,1670		  unsigned int rsr, unsigned int msr,1671		  int chip_type, unsigned int ssid,1672		  struct ct_atc **ratc)1673{1674	struct ct_atc *atc;1675	static const struct snd_device_ops ops = {1676		.dev_free = atc_dev_free,1677	};1678	int err;1679 1680	*ratc = NULL;1681 1682	atc = kzalloc(sizeof(*atc), GFP_KERNEL);1683	if (!atc)1684		return -ENOMEM;1685 1686	/* Set operations */1687	*atc = atc_preset;1688 1689	atc->card = card;1690	atc->pci = pci;1691	atc->rsr = rsr;1692	atc->msr = msr;1693	atc->chip_type = chip_type;1694 1695	mutex_init(&atc->atc_mutex);1696 1697	/* Find card model */1698	err = atc_identify_card(atc, ssid);1699	if (err < 0) {1700		dev_err(card->dev, "ctatc: Card not recognised\n");1701		goto error1;1702	}1703 1704	/* Set up device virtual memory management object */1705	err = ct_vm_create(&atc->vm, pci);1706	if (err < 0)1707		goto error1;1708 1709	/* Create all atc hw devices */1710	err = atc_create_hw_devs(atc);1711	if (err < 0)1712		goto error1;1713 1714	err = ct_mixer_create(atc, (struct ct_mixer **)&atc->mixer);1715	if (err) {1716		dev_err(card->dev, "Failed to create mixer obj!!!\n");1717		goto error1;1718	}1719 1720	/* Get resources */1721	err = atc_get_resources(atc);1722	if (err < 0)1723		goto error1;1724 1725	/* Build topology */1726	atc_connect_resources(atc);1727 1728	atc->timer = ct_timer_new(atc);1729	if (!atc->timer) {1730		err = -ENOMEM;1731		goto error1;1732	}1733 1734	err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, atc, &ops);1735	if (err < 0)1736		goto error1;1737 1738	*ratc = atc;1739	return 0;1740 1741error1:1742	ct_atc_destroy(atc);1743	dev_err(card->dev, "Something wrong!!!\n");1744	return err;1745}1746