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