include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[safe/jmp/linux-2.6] / sound / pci / ctxfi / ctatc.c
index 1a4bb35..1bff80c 100644 (file)
@@ -22,7 +22,9 @@
 #include "ctsrc.h"
 #include "ctamixer.h"
 #include "ctdaio.h"
+#include "cttimer.h"
 #include <linux/delay.h>
+#include <linux/slab.h>
 #include <sound/pcm.h>
 #include <sound/control.h>
 #include <sound/asoundef.h>
                            | (0x10 << 16) \
                            | ((IEC958_AES3_CON_FS_48000) << 24))
 
-static const struct ct_atc_chip_sub_details atc_sub_details[NUM_CTCARDS] = {
-       [CTSB0760] = {.subsys = PCI_SUBDEVICE_ID_CREATIVE_SB0760,
-                     .nm_model = "SB076x"},
-       [CTHENDRIX] = {.subsys = PCI_SUBDEVICE_ID_CREATIVE_HENDRIX,
-                     .nm_model = "Hendrix"},
-       [CTSB08801] = {.subsys = PCI_SUBDEVICE_ID_CREATIVE_SB08801,
-                     .nm_model = "SB0880"},
-       [CTSB08802] = {.subsys = PCI_SUBDEVICE_ID_CREATIVE_SB08802,
-                     .nm_model = "SB0880"},
-       [CTSB08803] = {.subsys = PCI_SUBDEVICE_ID_CREATIVE_SB08803,
-                     .nm_model = "SB0880"}
+static struct snd_pci_quirk __devinitdata subsys_20k1_list[] = {
+       SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, 0x0022, "SB055x", CTSB055X),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, 0x002f, "SB055x", CTSB055X),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, 0x0029, "SB073x", CTSB073X),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, 0x0031, "SB073x", CTSB073X),
+       SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_CREATIVE, 0xf000, 0x6000,
+                          "UAA", CTUAA),
+       { } /* terminator */
 };
 
-static struct ct_atc_chip_details atc_chip_details[] = {
-       {.vendor = PCI_VENDOR_ID_CREATIVE,
-        .device = PCI_DEVICE_ID_CREATIVE_20K1,
-        .sub_details = NULL,
-        .nm_card = "X-Fi 20k1"},
-       {.vendor = PCI_VENDOR_ID_CREATIVE,
-        .device = PCI_DEVICE_ID_CREATIVE_20K2,
-        .sub_details = atc_sub_details,
-        .nm_card = "X-Fi 20k2"},
-       {} /* terminator */
+static struct snd_pci_quirk __devinitdata subsys_20k2_list[] = {
+       SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB0760,
+                     "SB0760", CTSB0760),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB08801,
+                     "SB0880", CTSB0880),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB08802,
+                     "SB0880", CTSB0880),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB08803,
+                     "SB0880", CTSB0880),
+       SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_CREATIVE, 0xf000,
+                          PCI_SUBDEVICE_ID_CREATIVE_HENDRIX, "HENDRIX",
+                          CTHENDRIX),
+       { } /* terminator */
+};
+
+static const char *ct_subsys_name[NUM_CTCARDS] = {
+       /* 20k1 models */
+       [CTSB055X]      = "SB055x",
+       [CTSB073X]      = "SB073x",
+       [CTUAA]         = "UAA",
+       [CT20K1_UNKNOWN] = "Unknown",
+       /* 20k2 models */
+       [CTSB0760]      = "SB076x",
+       [CTHENDRIX]     = "Hendrix",
+       [CTSB0880]      = "SB0880",
+       [CT20K2_UNKNOWN] = "Unknown",
 };
 
 static struct {
@@ -72,15 +87,15 @@ static struct {
        [FRONT]         = { .create = ct_alsa_pcm_create,
                            .destroy = NULL,
                            .public_name = "Front/WaveIn"},
-       [REAR]          = { .create = ct_alsa_pcm_create,
+       [SURROUND]      = { .create = ct_alsa_pcm_create,
                            .destroy = NULL,
-                           .public_name = "Rear"},
+                           .public_name = "Surround"},
        [CLFE]          = { .create = ct_alsa_pcm_create,
                            .destroy = NULL,
                            .public_name = "Center/LFE"},
-       [SURROUND]      = { .create = ct_alsa_pcm_create,
+       [SIDE]          = { .create = ct_alsa_pcm_create,
                            .destroy = NULL,
-                           .public_name = "Surround"},
+                           .public_name = "Side"},
        [IEC958]        = { .create = ct_alsa_pcm_create,
                            .destroy = NULL,
                            .public_name = "IEC958 Non-audio"},
@@ -122,15 +137,15 @@ static int ct_map_audio_buffer(struct ct_atc *atc, struct ct_atc_pcm *apcm)
        struct snd_pcm_runtime *runtime;
        struct ct_vm *vm;
 
-       if (NULL == apcm->substream)
+       if (!apcm->substream)
                return 0;
 
        runtime = apcm->substream->runtime;
        vm = atc->vm;
 
-       apcm->vm_block = vm->map(vm, runtime->dma_area, runtime->dma_bytes);
+       apcm->vm_block = vm->map(vm, apcm->substream, runtime->dma_bytes);
 
-       if (NULL == apcm->vm_block)
+       if (!apcm->vm_block)
                return -ENOENT;
 
        return 0;
@@ -140,7 +155,7 @@ static void ct_unmap_audio_buffer(struct ct_atc *atc, struct ct_atc_pcm *apcm)
 {
        struct ct_vm *vm;
 
-       if (NULL == apcm->vm_block)
+       if (!apcm->vm_block)
                return;
 
        vm = atc->vm;
@@ -152,34 +167,22 @@ static void ct_unmap_audio_buffer(struct ct_atc *atc, struct ct_atc_pcm *apcm)
 
 static unsigned long atc_get_ptp_phys(struct ct_atc *atc, int index)
 {
-       struct ct_vm *vm;
-       void *kvirt_addr;
-       unsigned long phys_addr;
-
-       vm = atc->vm;
-       kvirt_addr = vm->get_ptp_virt(vm, index);
-       if (kvirt_addr == NULL)
-               phys_addr = (~0UL);
-       else
-               phys_addr = virt_to_phys(kvirt_addr);
-
-       return phys_addr;
+       return atc->vm->get_ptp_phys(atc->vm, index);
 }
 
 static unsigned int convert_format(snd_pcm_format_t snd_format)
 {
        switch (snd_format) {
        case SNDRV_PCM_FORMAT_U8:
-       case SNDRV_PCM_FORMAT_S8:
                return SRC_SF_U8;
        case SNDRV_PCM_FORMAT_S16_LE:
-       case SNDRV_PCM_FORMAT_U16_LE:
                return SRC_SF_S16;
        case SNDRV_PCM_FORMAT_S24_3LE:
                return SRC_SF_S24;
-       case SNDRV_PCM_FORMAT_S24_LE:
        case SNDRV_PCM_FORMAT_S32_LE:
                return SRC_SF_S32;
+       case SNDRV_PCM_FORMAT_FLOAT_LE:
+               return SRC_SF_F32;
        default:
                printk(KERN_ERR "ctxfi: not recognized snd format is %d \n",
                        snd_format);
@@ -190,8 +193,8 @@ static unsigned int convert_format(snd_pcm_format_t snd_format)
 static unsigned int
 atc_get_pitch(unsigned int input_rate, unsigned int output_rate)
 {
-       unsigned int pitch = 0;
-       int b = 0;
+       unsigned int pitch;
+       int b;
 
        /* get pitch and convert to fixed-point 8.24 format. */
        pitch = (input_rate / output_rate) << 24;
@@ -218,16 +221,16 @@ atc_get_pitch(unsigned int input_rate, unsigned int output_rate)
 
 static int select_rom(unsigned int pitch)
 {
-       if ((pitch > 0x00428f5c) && (pitch < 0x01b851ec)) {
+       if (pitch > 0x00428f5c && pitch < 0x01b851ec) {
                /* 0.26 <= pitch <= 1.72 */
                return 1;
-       } else if ((0x01d66666 == pitch) || (0x01d66667 == pitch)) {
+       } else if (pitch == 0x01d66666 || pitch == 0x01d66667) {
                /* pitch == 1.8375 */
                return 2;
-       } else if (0x02000000 == pitch) {
+       } else if (pitch == 0x02000000) {
                /* pitch == 2 */
                return 3;
-       } else if ((pitch >= 0x0) && (pitch <= 0x08000000)) {
+       } else if (pitch <= 0x08000000) {
                /* 0 <= pitch <= 8 */
                return 0;
        } else {
@@ -241,18 +244,15 @@ static int atc_pcm_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm)
        struct amixer_mgr *amixer_mgr = atc->rsc_mgrs[AMIXER];
        struct src_desc desc = {0};
        struct amixer_desc mix_dsc = {0};
-       struct src *src = NULL;
-       struct amixer *amixer = NULL;
-       int err = 0;
+       struct src *src;
+       struct amixer *amixer;
+       int err;
        int n_amixer = apcm->substream->runtime->channels, i = 0;
        int device = apcm->substream->pcm->device;
-       unsigned int pitch = 0;
-       unsigned long flags;
+       unsigned int pitch;
 
-       if (NULL != apcm->src) {
-               /* Prepared pcm playback */
-               return 0;
-       }
+       /* first release old resources */
+       atc_pcm_release_resources(atc, apcm);
 
        /* Get SRC resource */
        desc.multi = apcm->substream->runtime->channels;
@@ -273,7 +273,7 @@ static int atc_pcm_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm)
        /* Get AMIXER resource */
        n_amixer = (n_amixer < 2) ? 2 : n_amixer;
        apcm->amixers = kzalloc(sizeof(void *)*n_amixer, GFP_KERNEL);
-       if (NULL == apcm->amixers) {
+       if (!apcm->amixers) {
                err = -ENOMEM;
                goto error1;
        }
@@ -296,15 +296,17 @@ static int atc_pcm_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm)
        src = apcm->src;
        for (i = 0; i < n_amixer; i++) {
                amixer = apcm->amixers[i];
-               spin_lock_irqsave(&atc->atc_lock, flags);
+               mutex_lock(&atc->atc_mutex);
                amixer->ops->setup(amixer, &src->rsc,
                                        INIT_VOL, atc->pcm[i+device*2]);
-               spin_unlock_irqrestore(&atc->atc_lock, flags);
+               mutex_unlock(&atc->atc_mutex);
                src = src->ops->next_interleave(src);
-               if (NULL == src)
+               if (!src)
                        src = apcm->src;
        }
 
+       ct_timer_prepare(apcm->timer);
+
        return 0;
 
 error1:
@@ -319,10 +321,10 @@ atc_pcm_release_resources(struct ct_atc *atc, struct ct_atc_pcm *apcm)
        struct srcimp_mgr *srcimp_mgr = atc->rsc_mgrs[SRCIMP];
        struct amixer_mgr *amixer_mgr = atc->rsc_mgrs[AMIXER];
        struct sum_mgr *sum_mgr = atc->rsc_mgrs[SUM];
-       struct srcimp *srcimp = NULL;
-       int i = 0;
+       struct srcimp *srcimp;
+       int i;
 
-       if (NULL != apcm->srcimps) {
+       if (apcm->srcimps) {
                for (i = 0; i < apcm->n_srcimp; i++) {
                        srcimp = apcm->srcimps[i];
                        srcimp->ops->unmap(srcimp);
@@ -333,7 +335,7 @@ atc_pcm_release_resources(struct ct_atc *atc, struct ct_atc_pcm *apcm)
                apcm->srcimps = NULL;
        }
 
-       if (NULL != apcm->srccs) {
+       if (apcm->srccs) {
                for (i = 0; i < apcm->n_srcc; i++) {
                        src_mgr->put_src(src_mgr, apcm->srccs[i]);
                        apcm->srccs[i] = NULL;
@@ -342,7 +344,7 @@ atc_pcm_release_resources(struct ct_atc *atc, struct ct_atc_pcm *apcm)
                apcm->srccs = NULL;
        }
 
-       if (NULL != apcm->amixers) {
+       if (apcm->amixers) {
                for (i = 0; i < apcm->n_amixer; i++) {
                        amixer_mgr->put_amixer(amixer_mgr, apcm->amixers[i]);
                        apcm->amixers[i] = NULL;
@@ -351,17 +353,17 @@ atc_pcm_release_resources(struct ct_atc *atc, struct ct_atc_pcm *apcm)
                apcm->amixers = NULL;
        }
 
-       if (NULL != apcm->mono) {
+       if (apcm->mono) {
                sum_mgr->put_sum(sum_mgr, apcm->mono);
                apcm->mono = NULL;
        }
 
-       if (NULL != apcm->src) {
+       if (apcm->src) {
                src_mgr->put_src(src_mgr, apcm->src);
                apcm->src = NULL;
        }
 
-       if (NULL != apcm->vm_block) {
+       if (apcm->vm_block) {
                /* Undo device virtual mem map */
                ct_unmap_audio_buffer(atc, apcm);
                apcm->vm_block = NULL;
@@ -372,9 +374,13 @@ atc_pcm_release_resources(struct ct_atc *atc, struct ct_atc_pcm *apcm)
 
 static int atc_pcm_playback_start(struct ct_atc *atc, struct ct_atc_pcm *apcm)
 {
-       unsigned int max_cisz = 0;
+       unsigned int max_cisz;
        struct src *src = apcm->src;
 
+       if (apcm->started)
+               return 0;
+       apcm->started = 1;
+
        max_cisz = src->multi * src->rsc.msr;
        max_cisz = 0x80 * (max_cisz < 8 ? max_cisz : 8);
 
@@ -387,20 +393,23 @@ static int atc_pcm_playback_start(struct ct_atc *atc, struct ct_atc_pcm *apcm)
        src->ops->set_state(src, SRC_STATE_INIT);
        src->ops->commit_write(src);
 
+       ct_timer_start(apcm->timer);
        return 0;
 }
 
 static int atc_pcm_stop(struct ct_atc *atc, struct ct_atc_pcm *apcm)
 {
-       struct src *src = NULL;
-       int i = 0;
+       struct src *src;
+       int i;
+
+       ct_timer_stop(apcm->timer);
 
        src = apcm->src;
        src->ops->set_bm(src, 0);
        src->ops->set_state(src, SRC_STATE_OFF);
        src->ops->commit_write(src);
 
-       if (NULL != apcm->srccs) {
+       if (apcm->srccs) {
                for (i = 0; i < apcm->n_srcc; i++) {
                        src = apcm->srccs[i];
                        src->ops->set_bm(src, 0);
@@ -418,9 +427,11 @@ static int
 atc_pcm_playback_position(struct ct_atc *atc, struct ct_atc_pcm *apcm)
 {
        struct src *src = apcm->src;
-       u32 size = 0, max_cisz = 0;
-       int position = 0;
+       u32 size, max_cisz;
+       int position;
 
+       if (!src)
+               return 0;
        position = src->ops->get_ca(src);
 
        size = apcm->vm_block->size;
@@ -441,7 +452,7 @@ struct src_node_conf_t {
 static void setup_src_node_conf(struct ct_atc *atc, struct ct_atc_pcm *apcm,
                                struct src_node_conf_t *conf, int *n_srcc)
 {
-       unsigned int pitch = 0;
+       unsigned int pitch;
 
        /* get pitch and convert to fixed-point 8.24 format. */
        pitch = atc_get_pitch((atc->rsr * atc->msr),
@@ -486,16 +497,19 @@ atc_pcm_capture_get_resources(struct ct_atc *atc, struct ct_atc_pcm *apcm)
        struct amixer_mgr *amixer_mgr = atc->rsc_mgrs[AMIXER];
        struct sum_mgr *sum_mgr = atc->rsc_mgrs[SUM];
        struct src_desc src_dsc = {0};
-       struct src *src = NULL;
+       struct src *src;
        struct srcimp_desc srcimp_dsc = {0};
-       struct srcimp *srcimp = NULL;
+       struct srcimp *srcimp;
        struct amixer_desc mix_dsc = {0};
        struct sum_desc sum_dsc = {0};
-       unsigned int pitch = 0;
-       int multi = 0, err = 0, i = 0;
-       int n_srcimp = 0, n_amixer = 0, n_srcc = 0, n_sum = 0;
+       unsigned int pitch;
+       int multi, err, i;
+       int n_srcimp, n_amixer, n_srcc, n_sum;
        struct src_node_conf_t src_node_conf[2] = {{0} };
 
+       /* first release old resources */
+       atc_pcm_release_resources(atc, apcm);
+
        /* The numbers of converting SRCs and SRCIMPs should be determined
         * by pitch value. */
 
@@ -507,8 +521,8 @@ atc_pcm_capture_get_resources(struct ct_atc *atc, struct ct_atc_pcm *apcm)
 
        setup_src_node_conf(atc, apcm, src_node_conf, &n_srcc);
        n_sum = (1 == multi) ? 1 : 0;
-       n_amixer += n_sum * 2 + n_srcc;
-       n_srcimp += n_srcc;
+       n_amixer = n_sum * 2 + n_srcc;
+       n_srcimp = n_srcc;
        if ((multi > 1) && (0x8000000 >= pitch)) {
                /* Need extra AMIXERs and SRCIMPs for special treatment
                 * of interleaved recording of conjugate channels */
@@ -520,18 +534,18 @@ atc_pcm_capture_get_resources(struct ct_atc *atc, struct ct_atc_pcm *apcm)
 
        if (n_srcc) {
                apcm->srccs = kzalloc(sizeof(void *)*n_srcc, GFP_KERNEL);
-               if (NULL == apcm->srccs)
+               if (!apcm->srccs)
                        return -ENOMEM;
        }
        if (n_amixer) {
                apcm->amixers = kzalloc(sizeof(void *)*n_amixer, GFP_KERNEL);
-               if (NULL == apcm->amixers) {
+               if (!apcm->amixers) {
                        err = -ENOMEM;
                        goto error1;
                }
        }
        apcm->srcimps = kzalloc(sizeof(void *)*n_srcimp, GFP_KERNEL);
-       if (NULL == apcm->srcimps) {
+       if (!apcm->srcimps) {
                err = -ENOMEM;
                goto error1;
        }
@@ -622,20 +636,17 @@ error1:
 
 static int atc_pcm_capture_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm)
 {
-       struct src *src = NULL;
-       struct amixer *amixer = NULL;
-       struct srcimp *srcimp = NULL;
+       struct src *src;
+       struct amixer *amixer;
+       struct srcimp *srcimp;
        struct ct_mixer *mixer = atc->mixer;
-       struct sum *mono = NULL;
+       struct sum *mono;
        struct rsc *out_ports[8] = {NULL};
-       int err = 0, i = 0, j = 0, n_sum = 0, multi = 0;
-       unsigned int pitch = 0;
+       int err, i, j, n_sum, multi;
+       unsigned int pitch;
        int mix_base = 0, imp_base = 0;
 
-       if (NULL != apcm->src) {
-               /* Prepared pcm capture */
-               return 0;
-       }
+       atc_pcm_release_resources(atc, apcm);
 
        /* Get needed resources. */
        err = atc_pcm_capture_get_resources(atc, apcm);
@@ -696,14 +707,16 @@ static int atc_pcm_capture_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm)
                }
        }
 
+       ct_timer_prepare(apcm->timer);
+
        return 0;
 }
 
 static int atc_pcm_capture_start(struct ct_atc *atc, struct ct_atc_pcm *apcm)
 {
-       struct src *src = NULL;
+       struct src *src;
        struct src_mgr *src_mgr = atc->rsc_mgrs[SRC];
-       int i = 0, multi = 0;
+       int i, multi;
 
        if (apcm->started)
                return 0;
@@ -744,6 +757,7 @@ static int atc_pcm_capture_start(struct ct_atc *atc, struct ct_atc_pcm *apcm)
        /* Enable relevant SRCs synchronously */
        src_mgr->commit_write(src_mgr);
 
+       ct_timer_start(apcm->timer);
        return 0;
 }
 
@@ -752,6 +766,8 @@ atc_pcm_capture_position(struct ct_atc *atc, struct ct_atc_pcm *apcm)
 {
        struct src *src = apcm->src;
 
+       if (!src)
+               return 0;
        return src->ops->get_ca(src) - apcm->vm_block->addr;
 }
 
@@ -762,10 +778,13 @@ static int spdif_passthru_playback_get_resources(struct ct_atc *atc,
        struct amixer_mgr *amixer_mgr = atc->rsc_mgrs[AMIXER];
        struct src_desc desc = {0};
        struct amixer_desc mix_dsc = {0};
-       struct src *src = NULL;
-       int err = 0;
-       int n_amixer = apcm->substream->runtime->channels, i = 0;
-       unsigned int pitch = 0, rsr = atc->pll_rate;
+       struct src *src;
+       int err;
+       int n_amixer = apcm->substream->runtime->channels, i;
+       unsigned int pitch, rsr = atc->pll_rate;
+
+       /* first release old resources */
+       atc_pcm_release_resources(atc, apcm);
 
        /* Get SRC resource */
        desc.multi = apcm->substream->runtime->channels;
@@ -789,7 +808,7 @@ static int spdif_passthru_playback_get_resources(struct ct_atc *atc,
        /* Get AMIXER resource */
        n_amixer = (n_amixer < 2) ? 2 : n_amixer;
        apcm->amixers = kzalloc(sizeof(void *)*n_amixer, GFP_KERNEL);
-       if (NULL == apcm->amixers) {
+       if (!apcm->amixers) {
                err = -ENOMEM;
                goto error1;
        }
@@ -815,15 +834,23 @@ error1:
        return err;
 }
 
+static int atc_pll_init(struct ct_atc *atc, int rate)
+{
+       struct hw *hw = atc->hw;
+       int err;
+       err = hw->pll_init(hw, rate);
+       atc->pll_rate = err ? 0 : rate;
+       return err;
+}
+
 static int
 spdif_passthru_playback_setup(struct ct_atc *atc, struct ct_atc_pcm *apcm)
 {
        struct dao *dao = container_of(atc->daios[SPDIFOO], struct dao, daio);
-       unsigned long flags;
        unsigned int rate = apcm->substream->runtime->rate;
-       unsigned int status = 0;
+       unsigned int status;
        int err = 0;
-       unsigned char iec958_con_fs = 0;
+       unsigned char iec958_con_fs;
 
        switch (rate) {
        case 48000:
@@ -839,7 +866,7 @@ spdif_passthru_playback_setup(struct ct_atc *atc, struct ct_atc_pcm *apcm)
                return -ENOENT;
        }
 
-       spin_lock_irqsave(&atc->atc_lock, flags);
+       mutex_lock(&atc->atc_mutex);
        dao->ops->get_spos(dao, &status);
        if (((status >> 24) & IEC958_AES3_CON_FS) != iec958_con_fs) {
                status &= ((~IEC958_AES3_CON_FS) << 24);
@@ -847,11 +874,9 @@ spdif_passthru_playback_setup(struct ct_atc *atc, struct ct_atc_pcm *apcm)
                dao->ops->set_spos(dao, status);
                dao->ops->commit_write(dao);
        }
-       if ((rate != atc->pll_rate) && (32000 != rate)) {
-               err = ((struct hw *)atc->hw)->pll_init(atc->hw, rate);
-               atc->pll_rate = err ? 0 : rate;
-       }
-       spin_unlock_irqrestore(&atc->atc_lock, flags);
+       if ((rate != atc->pll_rate) && (32000 != rate))
+               err = atc_pll_init(atc, rate);
+       mutex_unlock(&atc->atc_mutex);
 
        return err;
 }
@@ -859,15 +884,13 @@ spdif_passthru_playback_setup(struct ct_atc *atc, struct ct_atc_pcm *apcm)
 static int
 spdif_passthru_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm)
 {
-       struct src *src = NULL;
-       struct amixer *amixer = NULL;
-       struct dao *dao = NULL;
-       int err = 0;
-       int i = 0;
-       unsigned long flags;
+       struct src *src;
+       struct amixer *amixer;
+       struct dao *dao;
+       int err;
+       int i;
 
-       if (NULL != apcm->src)
-               return 0;
+       atc_pcm_release_resources(atc, apcm);
 
        /* Configure SPDIFOO and PLL to passthrough mode;
         * determine pll_rate. */
@@ -886,17 +909,19 @@ spdif_passthru_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm)
                amixer = apcm->amixers[i];
                amixer->ops->setup(amixer, &src->rsc, INIT_VOL, NULL);
                src = src->ops->next_interleave(src);
-               if (NULL == src)
+               if (!src)
                        src = apcm->src;
        }
        /* Connect to SPDIFOO */
-       spin_lock_irqsave(&atc->atc_lock, flags);
+       mutex_lock(&atc->atc_mutex);
        dao = container_of(atc->daios[SPDIFOO], struct dao, daio);
        amixer = apcm->amixers[0];
        dao->ops->set_left_input(dao, &amixer->rsc);
        amixer = apcm->amixers[1];
        dao->ops->set_right_input(dao, &amixer->rsc);
-       spin_unlock_irqrestore(&atc->atc_lock, flags);
+       mutex_unlock(&atc->atc_mutex);
+
+       ct_timer_prepare(apcm->timer);
 
        return 0;
 }
@@ -905,7 +930,7 @@ static int atc_select_line_in(struct ct_atc *atc)
 {
        struct hw *hw = atc->hw;
        struct ct_mixer *mixer = atc->mixer;
-       struct src *src = NULL;
+       struct src *src;
 
        if (hw->is_adc_source_selected(hw, ADC_LINEIN))
                return 0;
@@ -927,7 +952,7 @@ static int atc_select_mic_in(struct ct_atc *atc)
 {
        struct hw *hw = atc->hw;
        struct ct_mixer *mixer = atc->mixer;
-       struct src *src = NULL;
+       struct src *src;
 
        if (hw->is_adc_source_selected(hw, ADC_MICIN))
                return 0;
@@ -1002,7 +1027,7 @@ static int atc_line_front_unmute(struct ct_atc *atc, unsigned char state)
 
 static int atc_line_surround_unmute(struct ct_atc *atc, unsigned char state)
 {
-       return atc_daio_unmute(atc, state, LINEO4);
+       return atc_daio_unmute(atc, state, LINEO2);
 }
 
 static int atc_line_clfe_unmute(struct ct_atc *atc, unsigned char state)
@@ -1012,7 +1037,7 @@ static int atc_line_clfe_unmute(struct ct_atc *atc, unsigned char state)
 
 static int atc_line_rear_unmute(struct ct_atc *atc, unsigned char state)
 {
-       return atc_daio_unmute(atc, state, LINEO2);
+       return atc_daio_unmute(atc, state, LINEO4);
 }
 
 static int atc_line_in_unmute(struct ct_atc *atc, unsigned char state)
@@ -1042,15 +1067,14 @@ static int atc_spdif_out_set_status(struct ct_atc *atc, unsigned int status)
 
 static int atc_spdif_out_passthru(struct ct_atc *atc, unsigned char state)
 {
-       unsigned long flags;
        struct dao_desc da_dsc = {0};
-       struct dao *dao = NULL;
-       int err = 0;
+       struct dao *dao;
+       int err;
        struct ct_mixer *mixer = atc->mixer;
        struct rsc *rscs[2] = {NULL};
        unsigned int spos = 0;
 
-       spin_lock_irqsave(&atc->atc_lock, flags);
+       mutex_lock(&atc->atc_mutex);
        dao = container_of(atc->daios[SPDIFOO], struct dao, daio);
        da_dsc.msr = state ? 1 : atc->msr;
        da_dsc.passthru = state ? 1 : 0;
@@ -1063,21 +1087,19 @@ static int atc_spdif_out_passthru(struct ct_atc *atc, unsigned char state)
                dao->ops->set_left_input(dao, rscs[0]);
                dao->ops->set_right_input(dao, rscs[1]);
                /* Restore PLL to atc->rsr if needed. */
-               if (atc->pll_rate != atc->rsr) {
-                       err = ((struct hw *)atc->hw)->pll_init(atc->hw,
-                                                              atc->rsr);
-                       atc->pll_rate = err ? 0 : atc->rsr;
-               }
+               if (atc->pll_rate != atc->rsr)
+                       err = atc_pll_init(atc, atc->rsr);
        }
        dao->ops->set_spos(dao, spos);
        dao->ops->commit_write(dao);
-       spin_unlock_irqrestore(&atc->atc_lock, flags);
+       mutex_unlock(&atc->atc_mutex);
 
        return err;
 }
 
-static int ct_atc_destroy(struct ct_atc *atc)
+static int atc_release_resources(struct ct_atc *atc)
 {
+       int i;
        struct daio_mgr *daio_mgr = NULL;
        struct dao *dao = NULL;
        struct dai *dai = NULL;
@@ -1087,17 +1109,9 @@ static int ct_atc_destroy(struct ct_atc *atc)
        struct srcimp_mgr *srcimp_mgr = NULL;
        struct srcimp *srcimp = NULL;
        struct ct_mixer *mixer = NULL;
-       int i = 0;
 
-       if (NULL == atc)
-               return 0;
-
-       /* Stop hardware and disable all interrupts */
-       if (NULL != atc->hw)
-               ((struct hw *)atc->hw)->card_stop(atc->hw);
-
-       /* Destroy internal mixer objects */
-       if (NULL != atc->mixer) {
+       /* disconnect internal mixer objects */
+       if (atc->mixer) {
                mixer = atc->mixer;
                mixer->set_input_left(mixer, MIX_LINE_IN, NULL);
                mixer->set_input_right(mixer, MIX_LINE_IN, NULL);
@@ -1105,10 +1119,9 @@ static int ct_atc_destroy(struct ct_atc *atc)
                mixer->set_input_right(mixer, MIX_MIC_IN, NULL);
                mixer->set_input_left(mixer, MIX_SPDIF_IN, NULL);
                mixer->set_input_right(mixer, MIX_SPDIF_IN, NULL);
-               ct_mixer_destroy(atc->mixer);
        }
 
-       if (NULL != atc->daios) {
+       if (atc->daios) {
                daio_mgr = (struct daio_mgr *)atc->rsc_mgrs[DAIO];
                for (i = 0; i < atc->n_daio; i++) {
                        daio = atc->daios[i];
@@ -1123,25 +1136,28 @@ static int ct_atc_destroy(struct ct_atc *atc)
                        daio_mgr->put_daio(daio_mgr, daio);
                }
                kfree(atc->daios);
+               atc->daios = NULL;
        }
 
-       if (NULL != atc->pcm) {
+       if (atc->pcm) {
                sum_mgr = atc->rsc_mgrs[SUM];
                for (i = 0; i < atc->n_pcm; i++)
                        sum_mgr->put_sum(sum_mgr, atc->pcm[i]);
 
                kfree(atc->pcm);
+               atc->pcm = NULL;
        }
 
-       if (NULL != atc->srcs) {
+       if (atc->srcs) {
                src_mgr = atc->rsc_mgrs[SRC];
                for (i = 0; i < atc->n_src; i++)
                        src_mgr->put_src(src_mgr, atc->srcs[i]);
 
                kfree(atc->srcs);
+               atc->srcs = NULL;
        }
 
-       if (NULL != atc->srcimps) {
+       if (atc->srcimps) {
                srcimp_mgr = atc->rsc_mgrs[SRCIMP];
                for (i = 0; i < atc->n_srcimp; i++) {
                        srcimp = atc->srcimps[i];
@@ -1149,20 +1165,41 @@ static int ct_atc_destroy(struct ct_atc *atc)
                        srcimp_mgr->put_srcimp(srcimp_mgr, atc->srcimps[i]);
                }
                kfree(atc->srcimps);
+               atc->srcimps = NULL;
+       }
+
+       return 0;
+}
+
+static int ct_atc_destroy(struct ct_atc *atc)
+{
+       int i = 0;
+
+       if (!atc)
+               return 0;
+
+       if (atc->timer) {
+               ct_timer_free(atc->timer);
+               atc->timer = NULL;
        }
 
+       atc_release_resources(atc);
+
+       /* Destroy internal mixer objects */
+       if (atc->mixer)
+               ct_mixer_destroy(atc->mixer);
+
        for (i = 0; i < NUM_RSCTYP; i++) {
-               if ((NULL != rsc_mgr_funcs[i].destroy) &&
-                   (NULL != atc->rsc_mgrs[i]))
+               if (rsc_mgr_funcs[i].destroy && atc->rsc_mgrs[i])
                        rsc_mgr_funcs[i].destroy(atc->rsc_mgrs[i]);
 
        }
 
-       if (NULL != atc->hw)
+       if (atc->hw)
                destroy_hw_obj((struct hw *)atc->hw);
 
        /* Destroy device virtual memory manager object */
-       if (NULL != atc->vm) {
+       if (atc->vm) {
                ct_vm_destroy(atc->vm);
                atc->vm = NULL;
        }
@@ -1178,67 +1215,62 @@ static int atc_dev_free(struct snd_device *dev)
        return ct_atc_destroy(atc);
 }
 
-static int atc_identify_card(struct ct_atc *atc)
+static int __devinit atc_identify_card(struct ct_atc *atc, unsigned int ssid)
 {
-       u16 subsys;
-       u8 revision;
-       struct pci_dev *pci = atc->pci;
-       const struct ct_atc_chip_details *d;
-       enum CTCARDS i;
-
-       subsys = pci->subsystem_device;
-       revision = pci->revision;
-       atc->chip_details = NULL;
-       atc->model = NUM_CTCARDS;
-       for (d = atc_chip_details; d->vendor; d++) {
-               if (d->vendor != pci->vendor || d->device != pci->device)
-                       continue;
-
-               if (NULL == d->sub_details) {
-                       atc->chip_details = d;
-                       break;
-               }
-               for (i = 0; i < NUM_CTCARDS; i++) {
-                       if ((d->sub_details[i].subsys == subsys) ||
-                           (((subsys & 0x6000) == 0x6000) &&
-                           ((d->sub_details[i].subsys & 0x6000) == 0x6000))) {
-                               atc->model = i;
-                               break;
-                       }
-               }
-               if (i >= NUM_CTCARDS)
-                       continue;
+       const struct snd_pci_quirk *p;
+       const struct snd_pci_quirk *list;
+       u16 vendor_id, device_id;
 
-               atc->chip_details = d;
+       switch (atc->chip_type) {
+       case ATC20K1:
+               atc->chip_name = "20K1";
+               list = subsys_20k1_list;
                break;
-               /* not take revision into consideration now */
-       }
-       if (!d->vendor)
+       case ATC20K2:
+               atc->chip_name = "20K2";
+               list = subsys_20k2_list;
+               break;
+       default:
                return -ENOENT;
-
+       }
+       if (ssid) {
+               vendor_id = ssid >> 16;
+               device_id = ssid & 0xffff;
+       } else {
+               vendor_id = atc->pci->subsystem_vendor;
+               device_id = atc->pci->subsystem_device;
+       }
+       p = snd_pci_quirk_lookup_id(vendor_id, device_id, list);
+       if (p) {
+               if (p->value < 0) {
+                       printk(KERN_ERR "ctxfi: "
+                              "Device %04x:%04x is black-listed\n",
+                              vendor_id, device_id);
+                       return -ENOENT;
+               }
+               atc->model = p->value;
+       } else {
+               if (atc->chip_type == ATC20K1)
+                       atc->model = CT20K1_UNKNOWN;
+               else
+                       atc->model = CT20K2_UNKNOWN;
+       }
+       atc->model_name = ct_subsys_name[atc->model];
+       snd_printd("ctxfi: chip %s model %s (%04x:%04x) is found\n",
+                  atc->chip_name, atc->model_name,
+                  vendor_id, device_id);
        return 0;
 }
 
-static int ct_create_alsa_devs(struct ct_atc *atc)
+int __devinit ct_atc_create_alsa_devs(struct ct_atc *atc)
 {
        enum CTALSADEVS i;
-       struct hw *hw = atc->hw;
        int err;
 
-       switch (hw->get_chip_type(hw)) {
-       case ATC20K1:
-               alsa_dev_funcs[MIXER].public_name = "20K1";
-               break;
-       case ATC20K2:
-               alsa_dev_funcs[MIXER].public_name = "20K2";
-               break;
-       default:
-               alsa_dev_funcs[MIXER].public_name = "Unknown";
-               break;
-       }
+       alsa_dev_funcs[MIXER].public_name = atc->chip_name;
 
        for (i = 0; i < NUM_CTALSADEVS; i++) {
-               if (NULL == alsa_dev_funcs[i].create)
+               if (!alsa_dev_funcs[i].create)
                        continue;
 
                err = alsa_dev_funcs[i].create(atc, i,
@@ -1253,13 +1285,13 @@ static int ct_create_alsa_devs(struct ct_atc *atc)
        return 0;
 }
 
-static int atc_create_hw_devs(struct ct_atc *atc)
+static int __devinit atc_create_hw_devs(struct ct_atc *atc)
 {
-       struct hw *hw = NULL;
+       struct hw *hw;
        struct card_conf info = {0};
-       int i = 0, err = 0;
+       int i, err;
 
-       err = create_hw_obj(atc->pci, &hw);
+       err = create_hw_obj(atc->pci, atc->chip_type, atc->model, &hw);
        if (err) {
                printk(KERN_ERR "Failed to create hw obj!!!\n");
                return err;
@@ -1275,7 +1307,7 @@ static int atc_create_hw_devs(struct ct_atc *atc)
                return err;
 
        for (i = 0; i < NUM_RSCTYP; i++) {
-               if (NULL == rsc_mgr_funcs[i].create)
+               if (!rsc_mgr_funcs[i].create)
                        continue;
 
                err = rsc_mgr_funcs[i].create(atc->hw, &atc->rsc_mgrs[i]);
@@ -1292,30 +1324,29 @@ static int atc_create_hw_devs(struct ct_atc *atc)
 static int atc_get_resources(struct ct_atc *atc)
 {
        struct daio_desc da_desc = {0};
-       struct daio_mgr *daio_mgr = NULL;
+       struct daio_mgr *daio_mgr;
        struct src_desc src_dsc = {0};
-       struct src_mgr *src_mgr = NULL;
+       struct src_mgr *src_mgr;
        struct srcimp_desc srcimp_dsc = {0};
-       struct srcimp_mgr *srcimp_mgr = NULL;
+       struct srcimp_mgr *srcimp_mgr;
        struct sum_desc sum_dsc = {0};
-       struct sum_mgr *sum_mgr = NULL;
-       int err = 0, i = 0;
-       unsigned short subsys_id;
+       struct sum_mgr *sum_mgr;
+       int err, i;
 
        atc->daios = kzalloc(sizeof(void *)*(DAIONUM), GFP_KERNEL);
-       if (NULL == atc->daios)
+       if (!atc->daios)
                return -ENOMEM;
 
        atc->srcs = kzalloc(sizeof(void *)*(2*2), GFP_KERNEL);
-       if (NULL == atc->srcs)
+       if (!atc->srcs)
                return -ENOMEM;
 
        atc->srcimps = kzalloc(sizeof(void *)*(2*2), GFP_KERNEL);
-       if (NULL == atc->srcimps)
+       if (!atc->srcimps)
                return -ENOMEM;
 
        atc->pcm = kzalloc(sizeof(void *)*(2*4), GFP_KERNEL);
-       if (NULL == atc->pcm)
+       if (!atc->pcm)
                return -ENOMEM;
 
        daio_mgr = (struct daio_mgr *)atc->rsc_mgrs[DAIO];
@@ -1331,13 +1362,10 @@ static int atc_get_resources(struct ct_atc *atc)
                }
                atc->n_daio++;
        }
-       subsys_id = atc->pci->subsystem_device;
-       if ((subsys_id == 0x0029) || (subsys_id == 0x0031)) {
-               /* SB073x cards */
+       if (atc->model == CTSB073X)
                da_desc.type = SPDIFI1;
-       } else {
+       else
                da_desc.type = SPDIFIO;
-       }
        err = daio_mgr->get_daio(daio_mgr, &da_desc,
                                (struct daio **)&atc->daios[i]);
        if (err) {
@@ -1390,12 +1418,6 @@ static int atc_get_resources(struct ct_atc *atc)
                atc->n_pcm++;
        }
 
-       err = ct_mixer_create(atc, (struct ct_mixer **)&atc->mixer);
-       if (err) {
-               printk(KERN_ERR "ctxfi: Failed to create mixer obj!!!\n");
-               return err;
-       }
-
        return 0;
 }
 
@@ -1404,8 +1426,8 @@ atc_connect_dai(struct src_mgr *src_mgr, struct dai *dai,
                struct src **srcs, struct srcimp **srcimps)
 {
        struct rsc *rscs[2] = {NULL};
-       struct src *src = NULL;
-       struct srcimp *srcimp = NULL;
+       struct src *src;
+       struct srcimp *srcimp;
        int i = 0;
 
        rscs[0] = &dai->daio.rscl;
@@ -1440,13 +1462,13 @@ atc_connect_dai(struct src_mgr *src_mgr, struct dai *dai,
 
 static void atc_connect_resources(struct ct_atc *atc)
 {
-       struct dai *dai = NULL;
-       struct dao *dao = NULL;
-       struct src *src = NULL;
-       struct sum *sum = NULL;
-       struct ct_mixer *mixer = NULL;
+       struct dai *dai;
+       struct dao *dao;
+       struct src *src;
+       struct sum *sum;
+       struct ct_mixer *mixer;
        struct rsc *rscs[2] = {NULL};
-       int i = 0, j = 0;
+       int i, j;
 
        mixer = atc->mixer;
 
@@ -1484,37 +1506,117 @@ static void atc_connect_resources(struct ct_atc *atc)
        }
 }
 
-static void atc_set_ops(struct ct_atc *atc)
+#ifdef CONFIG_PM
+static int atc_suspend(struct ct_atc *atc, pm_message_t state)
 {
-       /* Set operations */
-       atc->map_audio_buffer = ct_map_audio_buffer;
-       atc->unmap_audio_buffer = ct_unmap_audio_buffer;
-       atc->pcm_playback_prepare = atc_pcm_playback_prepare;
-       atc->pcm_release_resources = atc_pcm_release_resources;
-       atc->pcm_playback_start = atc_pcm_playback_start;
-       atc->pcm_playback_stop = atc_pcm_stop;
-       atc->pcm_playback_position = atc_pcm_playback_position;
-       atc->pcm_capture_prepare = atc_pcm_capture_prepare;
-       atc->pcm_capture_start = atc_pcm_capture_start;
-       atc->pcm_capture_stop = atc_pcm_stop;
-       atc->pcm_capture_position = atc_pcm_capture_position;
-       atc->spdif_passthru_playback_prepare = spdif_passthru_playback_prepare;
-       atc->get_ptp_phys = atc_get_ptp_phys;
-       atc->select_line_in = atc_select_line_in;
-       atc->select_mic_in = atc_select_mic_in;
-       atc->select_digit_io = atc_select_digit_io;
-       atc->line_front_unmute = atc_line_front_unmute;
-       atc->line_surround_unmute = atc_line_surround_unmute;
-       atc->line_clfe_unmute = atc_line_clfe_unmute;
-       atc->line_rear_unmute = atc_line_rear_unmute;
-       atc->line_in_unmute = atc_line_in_unmute;
-       atc->spdif_out_unmute = atc_spdif_out_unmute;
-       atc->spdif_in_unmute = atc_spdif_in_unmute;
-       atc->spdif_out_get_status = atc_spdif_out_get_status;
-       atc->spdif_out_set_status = atc_spdif_out_set_status;
-       atc->spdif_out_passthru = atc_spdif_out_passthru;
-       atc->have_digit_io_switch = atc_have_digit_io_switch;
+       int i;
+       struct hw *hw = atc->hw;
+
+       snd_power_change_state(atc->card, SNDRV_CTL_POWER_D3hot);
+
+       for (i = FRONT; i < NUM_PCMS; i++) {
+               if (!atc->pcms[i])
+                       continue;
+
+               snd_pcm_suspend_all(atc->pcms[i]);
+       }
+
+       atc_release_resources(atc);
+
+       hw->suspend(hw, state);
+
+       return 0;
+}
+
+static int atc_hw_resume(struct ct_atc *atc)
+{
+       struct hw *hw = atc->hw;
+       struct card_conf info = {0};
+
+       /* Re-initialize card hardware. */
+       info.rsr = atc->rsr;
+       info.msr = atc->msr;
+       info.vm_pgt_phys = atc_get_ptp_phys(atc, 0);
+       return hw->resume(hw, &info);
+}
+
+static int atc_resources_resume(struct ct_atc *atc)
+{
+       struct ct_mixer *mixer;
+       int err = 0;
+
+       /* Get resources */
+       err = atc_get_resources(atc);
+       if (err < 0) {
+               atc_release_resources(atc);
+               return err;
+       }
+
+       /* Build topology */
+       atc_connect_resources(atc);
+
+       mixer = atc->mixer;
+       mixer->resume(mixer);
+
+       return 0;
+}
+
+static int atc_resume(struct ct_atc *atc)
+{
+       int err = 0;
+
+       /* Do hardware resume. */
+       err = atc_hw_resume(atc);
+       if (err < 0) {
+               printk(KERN_ERR "ctxfi: pci_enable_device failed, "
+                      "disabling device\n");
+               snd_card_disconnect(atc->card);
+               return err;
+       }
+
+       err = atc_resources_resume(atc);
+       if (err < 0)
+               return err;
+
+       snd_power_change_state(atc->card, SNDRV_CTL_POWER_D0);
+
+       return 0;
 }
+#endif
+
+static struct ct_atc atc_preset __devinitdata = {
+       .map_audio_buffer = ct_map_audio_buffer,
+       .unmap_audio_buffer = ct_unmap_audio_buffer,
+       .pcm_playback_prepare = atc_pcm_playback_prepare,
+       .pcm_release_resources = atc_pcm_release_resources,
+       .pcm_playback_start = atc_pcm_playback_start,
+       .pcm_playback_stop = atc_pcm_stop,
+       .pcm_playback_position = atc_pcm_playback_position,
+       .pcm_capture_prepare = atc_pcm_capture_prepare,
+       .pcm_capture_start = atc_pcm_capture_start,
+       .pcm_capture_stop = atc_pcm_stop,
+       .pcm_capture_position = atc_pcm_capture_position,
+       .spdif_passthru_playback_prepare = spdif_passthru_playback_prepare,
+       .get_ptp_phys = atc_get_ptp_phys,
+       .select_line_in = atc_select_line_in,
+       .select_mic_in = atc_select_mic_in,
+       .select_digit_io = atc_select_digit_io,
+       .line_front_unmute = atc_line_front_unmute,
+       .line_surround_unmute = atc_line_surround_unmute,
+       .line_clfe_unmute = atc_line_clfe_unmute,
+       .line_rear_unmute = atc_line_rear_unmute,
+       .line_in_unmute = atc_line_in_unmute,
+       .spdif_out_unmute = atc_spdif_out_unmute,
+       .spdif_in_unmute = atc_spdif_in_unmute,
+       .spdif_out_get_status = atc_spdif_out_get_status,
+       .spdif_out_set_status = atc_spdif_out_set_status,
+       .spdif_out_passthru = atc_spdif_out_passthru,
+       .have_digit_io_switch = atc_have_digit_io_switch,
+#ifdef CONFIG_PM
+       .suspend = atc_suspend,
+       .resume = atc_resume,
+#endif
+};
 
 /**
  *  ct_atc_create - create and initialize a hardware manager
@@ -1528,40 +1630,43 @@ static void atc_set_ops(struct ct_atc *atc)
  *  Returns 0 if suceeds, or negative error code if fails.
  */
 
-int ct_atc_create(struct snd_card *card, struct pci_dev *pci,
-                 unsigned int rsr, unsigned int msr, struct ct_atc **ratc)
+int __devinit ct_atc_create(struct snd_card *card, struct pci_dev *pci,
+                           unsigned int rsr, unsigned int msr,
+                           int chip_type, unsigned int ssid,
+                           struct ct_atc **ratc)
 {
-       struct ct_atc *atc = NULL;
+       struct ct_atc *atc;
        static struct snd_device_ops ops = {
                .dev_free = atc_dev_free,
        };
-       int err = 0;
+       int err;
 
        *ratc = NULL;
 
        atc = kzalloc(sizeof(*atc), GFP_KERNEL);
-       if (NULL == atc)
+       if (!atc)
                return -ENOMEM;
 
+       /* Set operations */
+       *atc = atc_preset;
+
        atc->card = card;
        atc->pci = pci;
        atc->rsr = rsr;
        atc->msr = msr;
+       atc->chip_type = chip_type;
 
-       /* Set operations */
-       atc_set_ops(atc);
-
-       spin_lock_init(&atc->atc_lock);
+       mutex_init(&atc->atc_mutex);
 
        /* Find card model */
-       err = atc_identify_card(atc);
+       err = atc_identify_card(atc, ssid);
        if (err < 0) {
                printk(KERN_ERR "ctatc: Card not recognised\n");
                goto error1;
        }
 
        /* Set up device virtual memory management object */
-       err = ct_vm_create(&atc->vm);
+       err = ct_vm_create(&atc->vm, pci);
        if (err < 0)
                goto error1;
 
@@ -1570,6 +1675,12 @@ int ct_atc_create(struct snd_card *card, struct pci_dev *pci,
        if (err < 0)
                goto error1;
 
+       err = ct_mixer_create(atc, (struct ct_mixer **)&atc->mixer);
+       if (err) {
+               printk(KERN_ERR "ctxfi: Failed to create mixer obj!!!\n");
+               goto error1;
+       }
+
        /* Get resources */
        err = atc_get_resources(atc);
        if (err < 0)
@@ -1578,7 +1689,9 @@ int ct_atc_create(struct snd_card *card, struct pci_dev *pci,
        /* Build topology */
        atc_connect_resources(atc);
 
-       atc->create_alsa_devs = ct_create_alsa_devs;
+       atc->timer = ct_timer_new(atc);
+       if (!atc->timer)
+               goto error1;
 
        err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, atc, &ops);
        if (err < 0)
@@ -1594,4 +1707,3 @@ error1:
        printk(KERN_ERR "ctxfi: Something wrong!!!\n");
        return err;
 }
-