vserver 1.9.3
[linux-2.6.git] / sound / pci / cs46xx / cs46xx_lib.c
index e9810d2..9b18681 100644 (file)
@@ -79,6 +79,8 @@ static unsigned short snd_cs46xx_codec_read(cs46xx_t *chip,
                     (codec_index == CS46XX_SECONDARY_CODEC_INDEX),
                     return -EINVAL);
 
+       chip->active_ctrl(chip, 1);
+
        if (codec_index == CS46XX_SECONDARY_CODEC_INDEX)
                offset = CS46XX_SECONDARY_CODEC_OFFSET;
 
@@ -184,27 +186,22 @@ static unsigned short snd_cs46xx_codec_read(cs46xx_t *chip,
        //snd_cs46xx_peekBA0(chip, BA0_ACCAD);
        result = snd_cs46xx_peekBA0(chip, BA0_ACSDA + offset);
  end:
+       chip->active_ctrl(chip, -1);
        return result;
 }
 
 static unsigned short snd_cs46xx_ac97_read(ac97_t * ac97,
                                            unsigned short reg)
 {
-       cs46xx_t *chip = snd_magic_cast(cs46xx_t, ac97->private_data, return -ENXIO);
+       cs46xx_t *chip = ac97->private_data;
        unsigned short val;
-       int codec_index = -1;
-
-       /* UGGLY: nr_ac97_codecs == 0 primery codec detection is in progress */
-       if (ac97 == chip->ac97[CS46XX_PRIMARY_CODEC_INDEX] || chip->nr_ac97_codecs == 0)
-               codec_index = CS46XX_PRIMARY_CODEC_INDEX;
-       /* UGGLY: nr_ac97_codecs == 1 secondary codec detection is in progress */
-       else if (ac97 == chip->ac97[CS46XX_SECONDARY_CODEC_INDEX] || chip->nr_ac97_codecs == 1)
-               codec_index = CS46XX_SECONDARY_CODEC_INDEX;
-       else
-               snd_assert(0, return 0xffff);
-       chip->active_ctrl(chip, 1);
+       int codec_index = ac97->num;
+
+       snd_assert(codec_index == CS46XX_PRIMARY_CODEC_INDEX ||
+                  codec_index == CS46XX_SECONDARY_CODEC_INDEX,
+                  return 0xffff);
+
        val = snd_cs46xx_codec_read(chip, reg, codec_index);
-       chip->active_ctrl(chip, -1);
 
        /* HACK: voyetra uses EAPD bit in the reverse way.
         * we flip the bit to show the mixer status correctly
@@ -227,6 +224,8 @@ static void snd_cs46xx_codec_write(cs46xx_t *chip,
                    (codec_index == CS46XX_SECONDARY_CODEC_INDEX),
                    return);
 
+       chip->active_ctrl(chip, 1);
+
        /*
         *  1. Write ACCAD = Command Address Register = 46Ch for AC97 register address
         *  2. Write ACCDA = Command Data Register = 470h    for data to write to AC97
@@ -271,27 +270,24 @@ static void snd_cs46xx_codec_write(cs46xx_t *chip,
                 *  ACCTL = 460h, DCV should be reset by now and 460h = 07h
                 */
                if (!(snd_cs46xx_peekBA0(chip, BA0_ACCTL) & ACCTL_DCV)) {
-                       return;
+                       goto end;
                }
        }
        snd_printk("AC'97 write problem, codec_index = %d, reg = 0x%x, val = 0x%x\n", codec_index, reg, val);
+ end:
+       chip->active_ctrl(chip, -1);
 }
 
 static void snd_cs46xx_ac97_write(ac97_t *ac97,
                                   unsigned short reg,
                                   unsigned short val)
 {
-       cs46xx_t *chip = snd_magic_cast(cs46xx_t, ac97->private_data, return);
-       int codec_index = -1;
+       cs46xx_t *chip = ac97->private_data;
+       int codec_index = ac97->num;
 
-       /* UGGLY: nr_ac97_codecs == 0 primery codec detection is in progress */
-       if (ac97 == chip->ac97[CS46XX_PRIMARY_CODEC_INDEX] || chip->nr_ac97_codecs == 0)
-               codec_index = CS46XX_PRIMARY_CODEC_INDEX;
-       /* UGGLY: nr_ac97_codecs == 1 secondary codec detection is in progress */
-       else  if (ac97 == chip->ac97[CS46XX_SECONDARY_CODEC_INDEX] || chip->nr_ac97_codecs == 1)
-               codec_index = CS46XX_SECONDARY_CODEC_INDEX;
-       else
-               snd_assert(0,return);
+       snd_assert(codec_index == CS46XX_PRIMARY_CODEC_INDEX ||
+                  codec_index == CS46XX_SECONDARY_CODEC_INDEX,
+                  return);
 
        /* HACK: voyetra uses EAPD bit in the reverse way.
         * we flip the bit to show the mixer status correctly
@@ -299,9 +295,7 @@ static void snd_cs46xx_ac97_write(ac97_t *ac97,
        if (reg == AC97_POWERDOWN && chip->amplifier_ctrl == amp_voyetra)
                val ^= 0x8000;
 
-       chip->active_ctrl(chip, 1);
        snd_cs46xx_codec_write(chip, reg, val, codec_index);
-       chip->active_ctrl(chip, -1);
 }
 
 
@@ -688,84 +682,35 @@ static void snd_cs46xx_set_capture_sample_rate(cs46xx_t *chip, unsigned int rate
  *  PCM part
  */
 
+static void snd_cs46xx_pb_trans_copy(snd_pcm_substream_t *substream,
+                                    snd_pcm_indirect_t *rec, size_t bytes)
+{
+       snd_pcm_runtime_t *runtime = substream->runtime;
+       cs46xx_pcm_t * cpcm = runtime->private_data;
+       memcpy(cpcm->hw_buf.area + rec->hw_data, runtime->dma_area + rec->sw_data, bytes);
+}
+
 static int snd_cs46xx_playback_transfer(snd_pcm_substream_t *substream)
 {
-       /* cs46xx_t *chip = snd_pcm_substream_chip(substream); */
        snd_pcm_runtime_t *runtime = substream->runtime;
-       cs46xx_pcm_t * cpcm = snd_magic_cast(cs46xx_pcm_t, runtime->private_data, return -ENXIO);
-       snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr;
-       snd_pcm_sframes_t diff = appl_ptr - cpcm->appl_ptr;
-       int buffer_size = runtime->period_size * CS46XX_FRAGS << cpcm->shift;
-
-       if (diff) {
-               if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2))
-                       diff += runtime->boundary;
-               cpcm->sw_ready += diff * (1 << cpcm->shift);
-               cpcm->appl_ptr = appl_ptr;
-       }
-       while (cpcm->hw_ready < buffer_size && 
-              cpcm->sw_ready > 0) {
-               size_t hw_to_end = buffer_size - cpcm->hw_data;
-               size_t sw_to_end = cpcm->sw_bufsize - cpcm->sw_data;
-               size_t bytes = buffer_size - cpcm->hw_ready;
-               if (cpcm->sw_ready < (int)bytes)
-                       bytes = cpcm->sw_ready;
-               if (hw_to_end < bytes)
-                       bytes = hw_to_end;
-               if (sw_to_end < bytes)
-                       bytes = sw_to_end;
-               memcpy(cpcm->hw_buf.area + cpcm->hw_data,
-                      runtime->dma_area + cpcm->sw_data,
-                      bytes);
-               cpcm->hw_data += bytes;
-               if ((int)cpcm->hw_data == buffer_size)
-                       cpcm->hw_data = 0;
-               cpcm->sw_data += bytes;
-               if (cpcm->sw_data == cpcm->sw_bufsize)
-                       cpcm->sw_data = 0;
-               cpcm->hw_ready += bytes;
-               cpcm->sw_ready -= bytes;
-       }
+       cs46xx_pcm_t * cpcm = runtime->private_data;
+       snd_pcm_indirect_playback_transfer(substream, &cpcm->pcm_rec, snd_cs46xx_pb_trans_copy);
        return 0;
 }
 
-static int snd_cs46xx_capture_transfer(snd_pcm_substream_t *substream)
+static void snd_cs46xx_cp_trans_copy(snd_pcm_substream_t *substream,
+                                    snd_pcm_indirect_t *rec, size_t bytes)
 {
        cs46xx_t *chip = snd_pcm_substream_chip(substream);
        snd_pcm_runtime_t *runtime = substream->runtime;
-       snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr;
-       snd_pcm_sframes_t diff = appl_ptr - chip->capt.appl_ptr;
-       int buffer_size = runtime->period_size * CS46XX_FRAGS << chip->capt.shift;
-
-       if (diff) {
-               if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2))
-                       diff += runtime->boundary;
-               chip->capt.sw_ready -= diff * (1 << chip->capt.shift);
-               chip->capt.appl_ptr = appl_ptr;
-       }
-       while (chip->capt.hw_ready > 0 && 
-              chip->capt.sw_ready < (int)chip->capt.sw_bufsize) {
-               size_t hw_to_end = buffer_size - chip->capt.hw_data;
-               size_t sw_to_end = chip->capt.sw_bufsize - chip->capt.sw_data;
-               size_t bytes = chip->capt.sw_bufsize - chip->capt.sw_ready;
-               if (chip->capt.hw_ready < (int)bytes)
-                       bytes = chip->capt.hw_ready;
-               if (hw_to_end < bytes)
-                       bytes = hw_to_end;
-               if (sw_to_end < bytes)
-                       bytes = sw_to_end;
-               memcpy(runtime->dma_area + chip->capt.sw_data,
-                      chip->capt.hw_buf.area + chip->capt.hw_data,
-                      bytes);
-               chip->capt.hw_data += bytes;
-               if ((int)chip->capt.hw_data == buffer_size)
-                       chip->capt.hw_data = 0;
-               chip->capt.sw_data += bytes;
-               if (chip->capt.sw_data == chip->capt.sw_bufsize)
-                       chip->capt.sw_data = 0;
-               chip->capt.hw_ready -= bytes;
-               chip->capt.sw_ready += bytes;
-       }
+       memcpy(runtime->dma_area + rec->sw_data,
+              chip->capt.hw_buf.area + rec->hw_data, bytes);
+}
+
+static int snd_cs46xx_capture_transfer(snd_pcm_substream_t *substream)
+{
+       cs46xx_t *chip = snd_pcm_substream_chip(substream);
+       snd_pcm_indirect_capture_transfer(substream, &chip->capt.pcm_rec, snd_cs46xx_cp_trans_copy);
        return 0;
 }
 
@@ -773,7 +718,7 @@ static snd_pcm_uframes_t snd_cs46xx_playback_direct_pointer(snd_pcm_substream_t
 {
        cs46xx_t *chip = snd_pcm_substream_chip(substream);
        size_t ptr;
-       cs46xx_pcm_t *cpcm = snd_magic_cast(cs46xx_pcm_t, substream->runtime->private_data, return -ENXIO);
+       cs46xx_pcm_t *cpcm = substream->runtime->private_data;
        snd_assert (cpcm->pcm_channel,return -ENXIO);
 
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
@@ -789,9 +734,7 @@ static snd_pcm_uframes_t snd_cs46xx_playback_indirect_pointer(snd_pcm_substream_
 {
        cs46xx_t *chip = snd_pcm_substream_chip(substream);
        size_t ptr;
-       cs46xx_pcm_t *cpcm = snd_magic_cast(cs46xx_pcm_t, substream->runtime->private_data, return -ENXIO);
-       ssize_t bytes;
-       int buffer_size = substream->runtime->period_size * CS46XX_FRAGS << cpcm->shift;
+       cs46xx_pcm_t *cpcm = substream->runtime->private_data;
 
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
        snd_assert (cpcm->pcm_channel,return -ENXIO);
@@ -800,18 +743,7 @@ static snd_pcm_uframes_t snd_cs46xx_playback_indirect_pointer(snd_pcm_substream_
        ptr = snd_cs46xx_peek(chip, BA1_PBA);
 #endif
        ptr -= cpcm->hw_buf.addr;
-
-       bytes = ptr - cpcm->hw_io;
-
-       if (bytes < 0)
-               bytes += buffer_size;
-       cpcm->hw_io = ptr;
-       cpcm->hw_ready -= bytes;
-       cpcm->sw_io += bytes;
-       if (cpcm->sw_io >= cpcm->sw_bufsize)
-               cpcm->sw_io -= cpcm->sw_bufsize;
-       snd_cs46xx_playback_transfer(substream);
-       return cpcm->sw_io >> cpcm->shift;
+       return snd_pcm_indirect_playback_pointer(substream, &cpcm->pcm_rec, ptr);
 }
 
 static snd_pcm_uframes_t snd_cs46xx_capture_direct_pointer(snd_pcm_substream_t * substream)
@@ -825,18 +757,7 @@ static snd_pcm_uframes_t snd_cs46xx_capture_indirect_pointer(snd_pcm_substream_t
 {
        cs46xx_t *chip = snd_pcm_substream_chip(substream);
        size_t ptr = snd_cs46xx_peek(chip, BA1_CBA) - chip->capt.hw_buf.addr;
-       ssize_t bytes = ptr - chip->capt.hw_io;
-       int buffer_size = substream->runtime->period_size * CS46XX_FRAGS << chip->capt.shift;
-
-       if (bytes < 0)
-               bytes += buffer_size;
-       chip->capt.hw_io = ptr;
-       chip->capt.hw_ready += bytes;
-       chip->capt.sw_io += bytes;
-       if (chip->capt.sw_io >= chip->capt.sw_bufsize)
-               chip->capt.sw_io -= chip->capt.sw_bufsize;
-       snd_cs46xx_capture_transfer(substream);
-       return chip->capt.sw_io >> chip->capt.shift;
+       return snd_pcm_indirect_capture_pointer(substream, &chip->capt.pcm_rec, ptr);
 }
 
 static int snd_cs46xx_playback_trigger(snd_pcm_substream_t * substream,
@@ -847,13 +768,7 @@ static int snd_cs46xx_playback_trigger(snd_pcm_substream_t * substream,
        int result = 0;
 
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
-       cs46xx_pcm_t *cpcm = snd_magic_cast(cs46xx_pcm_t, substream->runtime->private_data, return -ENXIO);
-#else
-       spin_lock(&chip->reg_lock);
-#endif
-
-#ifdef CONFIG_SND_CS46XX_NEW_DSP
-
+       cs46xx_pcm_t *cpcm = substream->runtime->private_data;
        if (! cpcm->pcm_channel) {
                return -ENXIO;
        }
@@ -872,6 +787,7 @@ static int snd_cs46xx_playback_trigger(snd_pcm_substream_t * substream,
                if (substream->runtime->periods != CS46XX_FRAGS)
                        snd_cs46xx_playback_transfer(substream);
 #else
+               spin_lock(&chip->reg_lock);
                if (substream->runtime->periods != CS46XX_FRAGS)
                        snd_cs46xx_playback_transfer(substream);
                { unsigned int tmp;
@@ -879,6 +795,7 @@ static int snd_cs46xx_playback_trigger(snd_pcm_substream_t * substream,
                tmp &= 0x0000ffff;
                snd_cs46xx_poke(chip, BA1_PCTL, chip->play_ctl | tmp);
                }
+               spin_unlock(&chip->reg_lock);
 #endif
                break;
        case SNDRV_PCM_TRIGGER_STOP:
@@ -891,11 +808,13 @@ static int snd_cs46xx_playback_trigger(snd_pcm_substream_t * substream,
                if (!cpcm->pcm_channel->unlinked)
                        cs46xx_dsp_pcm_unlink(chip,cpcm->pcm_channel);
 #else
+               spin_lock(&chip->reg_lock);
                { unsigned int tmp;
                tmp = snd_cs46xx_peek(chip, BA1_PCTL);
                tmp &= 0x0000ffff;
                snd_cs46xx_poke(chip, BA1_PCTL, tmp);
                }
+               spin_unlock(&chip->reg_lock);
 #endif
                break;
        default:
@@ -903,10 +822,6 @@ static int snd_cs46xx_playback_trigger(snd_pcm_substream_t * substream,
                break;
        }
 
-#ifndef CONFIG_SND_CS46XX_NEW_DSP
-       spin_unlock(&chip->reg_lock);
-#endif
-
        return result;
 }
 
@@ -987,7 +902,7 @@ static int snd_cs46xx_playback_hw_params(snd_pcm_substream_t * substream,
        int sample_rate = params_rate(hw_params);
        int period_size = params_period_bytes(hw_params);
 #endif
-       cpcm = snd_magic_cast(cs46xx_pcm_t, runtime->private_data, return -ENXIO);
+       cpcm = runtime->private_data;
 
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
        snd_assert (sample_rate != 0, return -ENXIO);
@@ -1084,7 +999,7 @@ static int snd_cs46xx_playback_hw_free(snd_pcm_substream_t * substream)
        snd_pcm_runtime_t *runtime = substream->runtime;
        cs46xx_pcm_t *cpcm;
 
-       cpcm = snd_magic_cast(cs46xx_pcm_t, runtime->private_data, return -ENXIO);
+       cpcm = runtime->private_data;
 
        /* if play_back open fails, then this function
           is called and cpcm can actually be NULL here */
@@ -1108,7 +1023,7 @@ static int snd_cs46xx_playback_prepare(snd_pcm_substream_t * substream)
        snd_pcm_runtime_t *runtime = substream->runtime;
        cs46xx_pcm_t *cpcm;
 
-       cpcm = snd_magic_cast(cs46xx_pcm_t, runtime->private_data, return -ENXIO);
+       cpcm = runtime->private_data;
 
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
     snd_assert (cpcm->pcm_channel != NULL, return -ENXIO);
@@ -1143,10 +1058,9 @@ static int snd_cs46xx_playback_prepare(snd_pcm_substream_t * substream)
                        pfie |= 0x00004000;
        }
        
-       cpcm->sw_bufsize = snd_pcm_lib_buffer_bytes(substream);
-       cpcm->sw_data = cpcm->sw_io = cpcm->sw_ready = 0;
-       cpcm->hw_data = cpcm->hw_io = cpcm->hw_ready = 0;
-       cpcm->appl_ptr = 0;
+       memset(&cpcm->pcm_rec, 0, sizeof(cpcm->pcm_rec));
+       cpcm->pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
+       cpcm->pcm_rec.hw_buffer_size = runtime->period_size * CS46XX_FRAGS << cpcm->shift;
 
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
 
@@ -1223,10 +1137,9 @@ static int snd_cs46xx_capture_prepare(snd_pcm_substream_t * substream)
 
        snd_cs46xx_poke(chip, BA1_CBA, chip->capt.hw_buf.addr);
        chip->capt.shift = 2;
-       chip->capt.sw_bufsize = snd_pcm_lib_buffer_bytes(substream);
-       chip->capt.sw_data = chip->capt.sw_io = chip->capt.sw_ready = 0;
-       chip->capt.hw_data = chip->capt.hw_io = chip->capt.hw_ready = 0;
-       chip->capt.appl_ptr = 0;
+       memset(&chip->capt.pcm_rec, 0, sizeof(chip->capt.pcm_rec));
+       chip->capt.pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
+       chip->capt.pcm_rec.hw_buffer_size = runtime->period_size * CS46XX_FRAGS << 2;
        snd_cs46xx_set_capture_sample_rate(chip, runtime->rate);
 
        return 0;
@@ -1234,7 +1147,7 @@ static int snd_cs46xx_capture_prepare(snd_pcm_substream_t * substream)
 
 static irqreturn_t snd_cs46xx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-       cs46xx_t *chip = snd_magic_cast(cs46xx_t, dev_id, return IRQ_NONE);
+       cs46xx_t *chip = dev_id;
        u32 status1;
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
        dsp_spos_instance_t * ins = chip->dsp_spos_instance;
@@ -1265,7 +1178,7 @@ static irqreturn_t snd_cs46xx_interrupt(int irq, void *dev_id, struct pt_regs *r
                                        if (ins->pcm_channels[i].active &&
                                            ins->pcm_channels[i].private_data &&
                                            !ins->pcm_channels[i].unlinked) {
-                                               cpcm = snd_magic_cast(cs46xx_pcm_t, ins->pcm_channels[i].private_data, continue);
+                                               cpcm = ins->pcm_channels[i].private_data;
                                                snd_pcm_period_elapsed(cpcm->substream);
                                        }
                                }
@@ -1275,7 +1188,7 @@ static irqreturn_t snd_cs46xx_interrupt(int irq, void *dev_id, struct pt_regs *r
                                if (ins->pcm_channels[i].active && 
                                    ins->pcm_channels[i].private_data &&
                                    !ins->pcm_channels[i].unlinked) {
-                                       cpcm = snd_magic_cast(cs46xx_pcm_t, ins->pcm_channels[i].private_data, continue);
+                                       cpcm = ins->pcm_channels[i].private_data;
                                        snd_pcm_period_elapsed(cpcm->substream);
                                }
                        }
@@ -1302,7 +1215,9 @@ static irqreturn_t snd_cs46xx_interrupt(int irq, void *dev_id, struct pt_regs *r
                        c = snd_cs46xx_peekBA0(chip, BA0_MIDRP);
                        if ((chip->midcr & MIDCR_RIE) == 0)
                                continue;
+                       spin_unlock(&chip->reg_lock);
                        snd_rawmidi_receive(chip->midi_input, &c, 1);
+                       spin_lock(&chip->reg_lock);
                }
                while ((snd_cs46xx_peekBA0(chip, BA0_MIDSR) & MIDSR_TBF) == 0) {
                        if ((chip->midcr & MIDCR_TIE) == 0)
@@ -1370,10 +1285,8 @@ static snd_pcm_hardware_t snd_cs46xx_capture =
 
 static unsigned int period_sizes[] = { 32, 64, 128, 256, 512, 1024, 2048 };
 
-#define PERIOD_SIZES sizeof(period_sizes) / sizeof(period_sizes[0])
-
 static snd_pcm_hw_constraint_list_t hw_constraints_period_sizes = {
-       .count = PERIOD_SIZES,
+       .count = ARRAY_SIZE(period_sizes),
        .list = period_sizes,
        .mask = 0
 };
@@ -1382,10 +1295,8 @@ static snd_pcm_hw_constraint_list_t hw_constraints_period_sizes = {
 
 static void snd_cs46xx_pcm_free_substream(snd_pcm_runtime_t *runtime)
 {
-       cs46xx_pcm_t * cpcm = snd_magic_cast(cs46xx_pcm_t, runtime->private_data, return);
-       
-       if (cpcm)
-               snd_magic_kfree(cpcm);
+       cs46xx_pcm_t * cpcm = runtime->private_data;
+       kfree(cpcm);
 }
 
 static int _cs46xx_playback_open_channel (snd_pcm_substream_t * substream,int pcm_channel_id)
@@ -1394,11 +1305,12 @@ static int _cs46xx_playback_open_channel (snd_pcm_substream_t * substream,int pc
        cs46xx_pcm_t * cpcm;
        snd_pcm_runtime_t *runtime = substream->runtime;
 
-       cpcm = snd_magic_kcalloc(cs46xx_pcm_t, 0, GFP_KERNEL);
+       cpcm = kcalloc(1, sizeof(*cpcm), GFP_KERNEL);
        if (cpcm == NULL)
                return -ENOMEM;
-       if (snd_dma_alloc_pages(&chip->dma_dev, PAGE_SIZE, &cpcm->hw_buf) < 0) {
-               snd_magic_kfree(cpcm);
+       if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
+                               PAGE_SIZE, &cpcm->hw_buf) < 0) {
+               kfree(cpcm);
                return -ENOMEM;
        }
 
@@ -1486,7 +1398,8 @@ static int snd_cs46xx_capture_open(snd_pcm_substream_t * substream)
 {
        cs46xx_t *chip = snd_pcm_substream_chip(substream);
 
-       if (snd_dma_alloc_pages(&chip->dma_dev, PAGE_SIZE, &chip->capt.hw_buf) < 0)
+       if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
+                               PAGE_SIZE, &chip->capt.hw_buf) < 0)
                return -ENOMEM;
        chip->capt.substream = substream;
        substream->runtime->hw = snd_cs46xx_capture;
@@ -1510,7 +1423,7 @@ static int snd_cs46xx_playback_close(snd_pcm_substream_t * substream)
        snd_pcm_runtime_t *runtime = substream->runtime;
        cs46xx_pcm_t * cpcm;
 
-       cpcm = snd_magic_cast(cs46xx_pcm_t, runtime->private_data, return -ENXIO);
+       cpcm = runtime->private_data;
 
        /* when playback_open fails, then cpcm can be NULL */
        if (!cpcm) return -ENXIO;
@@ -1527,7 +1440,7 @@ static int snd_cs46xx_playback_close(snd_pcm_substream_t * substream)
 #endif
 
        cpcm->substream = NULL;
-       snd_dma_free_pages(&chip->dma_dev, &cpcm->hw_buf);
+       snd_dma_free_pages(&cpcm->hw_buf);
        chip->active_ctrl(chip, -1);
 
        return 0;
@@ -1538,7 +1451,7 @@ static int snd_cs46xx_capture_close(snd_pcm_substream_t * substream)
        cs46xx_t *chip = snd_pcm_substream_chip(substream);
 
        chip->capt.substream = NULL;
-       snd_dma_free_pages(&chip->dma_dev, &chip->capt.hw_buf);
+       snd_dma_free_pages(&chip->capt.hw_buf);
        chip->active_ctrl(chip, -1);
 
        return 0;
@@ -1664,7 +1577,7 @@ snd_pcm_ops_t snd_cs46xx_capture_indirect_ops = {
 
 static void snd_cs46xx_pcm_free(snd_pcm_t *pcm)
 {
-       cs46xx_t *chip = snd_magic_cast(cs46xx_t, pcm->private_data, return);
+       cs46xx_t *chip = pcm->private_data;
        chip->pcm = NULL;
        snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1672,21 +1585,21 @@ static void snd_cs46xx_pcm_free(snd_pcm_t *pcm)
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
 static void snd_cs46xx_pcm_rear_free(snd_pcm_t *pcm)
 {
-       cs46xx_t *chip = snd_magic_cast(cs46xx_t, pcm->private_data, return);
+       cs46xx_t *chip = pcm->private_data;
        chip->pcm_rear = NULL;
        snd_pcm_lib_preallocate_free_for_all(pcm);
 }
 
 static void snd_cs46xx_pcm_center_lfe_free(snd_pcm_t *pcm)
 {
-       cs46xx_t *chip = snd_magic_cast(cs46xx_t, pcm->private_data, return);
+       cs46xx_t *chip = pcm->private_data;
        chip->pcm_center_lfe = NULL;
        snd_pcm_lib_preallocate_free_for_all(pcm);
 }
 
 static void snd_cs46xx_pcm_iec958_free(snd_pcm_t *pcm)
 {
-       cs46xx_t *chip = snd_magic_cast(cs46xx_t, pcm->private_data, return);
+       cs46xx_t *chip = pcm->private_data;
        chip->pcm_iec958 = NULL;
        snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1824,14 +1737,14 @@ int __devinit snd_cs46xx_pcm_iec958(cs46xx_t *chip, int device, snd_pcm_t ** rpc
  */
 static void snd_cs46xx_mixer_free_ac97_bus(ac97_bus_t *bus)
 {
-       cs46xx_t *chip = snd_magic_cast(cs46xx_t, bus->private_data, return);
+       cs46xx_t *chip = bus->private_data;
 
        chip->ac97_bus = NULL;
 }
 
 static void snd_cs46xx_mixer_free_ac97(ac97_t *ac97)
 {
-       cs46xx_t *chip = snd_magic_cast(cs46xx_t, ac97->private_data, return);
+       cs46xx_t *chip = ac97->private_data;
 
        snd_assert ((ac97 == chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]) ||
                    (ac97 == chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]),
@@ -2420,7 +2333,7 @@ static void snd_cs46xx_codec_reset (ac97_t * ac97)
 {
        unsigned long end_time;
        int err;
-       cs46xx_t * chip = snd_magic_cast(cs46xx_t,ac97->private_data,return /* -ENXIO */);
+       cs46xx_t * chip = ac97->private_data;
 
        /* reset to defaults */
        snd_ac97_write(ac97, AC97_RESET, 0);    
@@ -2470,39 +2383,38 @@ static void snd_cs46xx_codec_reset (ac97_t * ac97)
 int __devinit snd_cs46xx_mixer(cs46xx_t *chip)
 {
        snd_card_t *card = chip->card;
-       ac97_bus_t bus;
-       ac97_t ac97;
+       ac97_template_t ac97;
        snd_ctl_elem_id_t id;
        int err;
        unsigned int idx;
+       static ac97_bus_ops_t ops = {
+#ifdef CONFIG_SND_CS46XX_NEW_DSP
+               .reset = snd_cs46xx_codec_reset,
+#endif
+               .write = snd_cs46xx_ac97_write,
+               .read = snd_cs46xx_ac97_read,
+       };
 
        /* detect primary codec */
        chip->nr_ac97_codecs = 0;
        snd_printdd("snd_cs46xx: detecting primary codec\n");
-       memset(&bus, 0, sizeof(bus));
-       bus.write = snd_cs46xx_ac97_write;
-       bus.read = snd_cs46xx_ac97_read;
-#ifdef CONFIG_SND_CS46XX_NEW_DSP
-       bus.reset = snd_cs46xx_codec_reset;
-#endif
-       bus.private_data = chip;
-       bus.private_free = snd_cs46xx_mixer_free_ac97_bus;
-       if ((err = snd_ac97_bus(card, &bus, &chip->ac97_bus)) < 0)
+       if ((err = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus)) < 0)
                return err;
+       chip->ac97_bus->private_free = snd_cs46xx_mixer_free_ac97_bus;
 
        memset(&ac97, 0, sizeof(ac97));
        ac97.private_data = chip;
        ac97.private_free = snd_cs46xx_mixer_free_ac97;
-       chip->ac97[CS46XX_PRIMARY_CODEC_INDEX] = &ac97;
 
-       snd_cs46xx_ac97_write(&ac97, AC97_MASTER, 0x8000);
+       snd_cs46xx_codec_write(chip, AC97_MASTER, 0x8000,
+                              CS46XX_PRIMARY_CODEC_INDEX);
        for (idx = 0; idx < 100; ++idx) {
-               if (snd_cs46xx_ac97_read(&ac97, AC97_MASTER) == 0x8000)
+               if (snd_cs46xx_codec_read(chip, AC97_MASTER,
+                                         CS46XX_PRIMARY_CODEC_INDEX) == 0x8000)
                        goto _ok;
                set_current_state(TASK_INTERRUPTIBLE);
                schedule_timeout(HZ/100);
        }
-       chip->ac97[CS46XX_PRIMARY_CODEC_INDEX] = NULL;
        return -ENXIO;
 
  _ok:
@@ -2519,18 +2431,21 @@ int __devinit snd_cs46xx_mixer(cs46xx_t *chip)
        ac97.private_free = snd_cs46xx_mixer_free_ac97;
        ac97.num = CS46XX_SECONDARY_CODEC_INDEX;
 
-       snd_cs46xx_ac97_write(&ac97, AC97_RESET, 0);
+       snd_cs46xx_codec_write(chip, AC97_RESET, 0,
+                              CS46XX_SECONDARY_CODEC_INDEX);
        udelay(10);
 
-       if (snd_cs46xx_ac97_read(&ac97, AC97_RESET) & 0x8000) {
+       if (snd_cs46xx_codec_read(chip, AC97_RESET,
+                                 CS46XX_SECONDARY_CODEC_INDEX) & 0x8000) {
                snd_printdd("snd_cs46xx: seconadry codec not present\n");
                goto _no_sec_codec;
        }
 
-       chip->ac97[CS46XX_SECONDARY_CODEC_INDEX] = &ac97;
-       snd_cs46xx_ac97_write(&ac97, AC97_MASTER, 0x8000);
+       snd_cs46xx_codec_write(chip, AC97_MASTER, 0x8000,
+                              CS46XX_SECONDARY_CODEC_INDEX);
        for (idx = 0; idx < 100; ++idx) {
-               if (snd_cs46xx_ac97_read(&ac97, AC97_MASTER) == 0x8000) {
+               if (snd_cs46xx_codec_read(chip, AC97_MASTER,
+                                         CS46XX_SECONDARY_CODEC_INDEX) == 0x8000) {
                        goto _ok2;
                }
                set_current_state(TASK_INTERRUPTIBLE);
@@ -2540,7 +2455,6 @@ int __devinit snd_cs46xx_mixer(cs46xx_t *chip)
  _no_sec_codec:
        snd_printdd("snd_cs46xx: secondary codec did not respond ...\n");
 
-       chip->ac97[CS46XX_SECONDARY_CODEC_INDEX] = NULL;
        chip->nr_ac97_codecs = 1;
     
        /* well, one codec only ... */
@@ -2605,11 +2519,10 @@ static void snd_cs46xx_midi_reset(cs46xx_t *chip)
 
 static int snd_cs46xx_midi_input_open(snd_rawmidi_substream_t * substream)
 {
-       unsigned long flags;
-       cs46xx_t *chip = snd_magic_cast(cs46xx_t, substream->rmidi->private_data, return -ENXIO);
+       cs46xx_t *chip = substream->rmidi->private_data;
 
        chip->active_ctrl(chip, 1);
-       spin_lock_irqsave(&chip->reg_lock, flags);
+       spin_lock_irq(&chip->reg_lock);
        chip->uartm |= CS46XX_MODE_INPUT;
        chip->midcr |= MIDCR_RXE;
        chip->midi_input = substream;
@@ -2618,16 +2531,15 @@ static int snd_cs46xx_midi_input_open(snd_rawmidi_substream_t * substream)
        } else {
                snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
        }
-       spin_unlock_irqrestore(&chip->reg_lock, flags);
+       spin_unlock_irq(&chip->reg_lock);
        return 0;
 }
 
 static int snd_cs46xx_midi_input_close(snd_rawmidi_substream_t * substream)
 {
-       unsigned long flags;
-       cs46xx_t *chip = snd_magic_cast(cs46xx_t, substream->rmidi->private_data, return -ENXIO);
+       cs46xx_t *chip = substream->rmidi->private_data;
 
-       spin_lock_irqsave(&chip->reg_lock, flags);
+       spin_lock_irq(&chip->reg_lock);
        chip->midcr &= ~(MIDCR_RXE | MIDCR_RIE);
        chip->midi_input = NULL;
        if (!(chip->uartm & CS46XX_MODE_OUTPUT)) {
@@ -2636,19 +2548,18 @@ static int snd_cs46xx_midi_input_close(snd_rawmidi_substream_t * substream)
                snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
        }
        chip->uartm &= ~CS46XX_MODE_INPUT;
-       spin_unlock_irqrestore(&chip->reg_lock, flags);
+       spin_unlock_irq(&chip->reg_lock);
        chip->active_ctrl(chip, -1);
        return 0;
 }
 
 static int snd_cs46xx_midi_output_open(snd_rawmidi_substream_t * substream)
 {
-       unsigned long flags;
-       cs46xx_t *chip = snd_magic_cast(cs46xx_t, substream->rmidi->private_data, return -ENXIO);
+       cs46xx_t *chip = substream->rmidi->private_data;
 
        chip->active_ctrl(chip, 1);
 
-       spin_lock_irqsave(&chip->reg_lock, flags);
+       spin_lock_irq(&chip->reg_lock);
        chip->uartm |= CS46XX_MODE_OUTPUT;
        chip->midcr |= MIDCR_TXE;
        chip->midi_output = substream;
@@ -2657,16 +2568,15 @@ static int snd_cs46xx_midi_output_open(snd_rawmidi_substream_t * substream)
        } else {
                snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
        }
-       spin_unlock_irqrestore(&chip->reg_lock, flags);
+       spin_unlock_irq(&chip->reg_lock);
        return 0;
 }
 
 static int snd_cs46xx_midi_output_close(snd_rawmidi_substream_t * substream)
 {
-       unsigned long flags;
-       cs46xx_t *chip = snd_magic_cast(cs46xx_t, substream->rmidi->private_data, return -ENXIO);
+       cs46xx_t *chip = substream->rmidi->private_data;
 
-       spin_lock_irqsave(&chip->reg_lock, flags);
+       spin_lock_irq(&chip->reg_lock);
        chip->midcr &= ~(MIDCR_TXE | MIDCR_TIE);
        chip->midi_output = NULL;
        if (!(chip->uartm & CS46XX_MODE_INPUT)) {
@@ -2675,7 +2585,7 @@ static int snd_cs46xx_midi_output_close(snd_rawmidi_substream_t * substream)
                snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
        }
        chip->uartm &= ~CS46XX_MODE_OUTPUT;
-       spin_unlock_irqrestore(&chip->reg_lock, flags);
+       spin_unlock_irq(&chip->reg_lock);
        chip->active_ctrl(chip, -1);
        return 0;
 }
@@ -2683,7 +2593,7 @@ static int snd_cs46xx_midi_output_close(snd_rawmidi_substream_t * substream)
 static void snd_cs46xx_midi_input_trigger(snd_rawmidi_substream_t * substream, int up)
 {
        unsigned long flags;
-       cs46xx_t *chip = snd_magic_cast(cs46xx_t, substream->rmidi->private_data, return);
+       cs46xx_t *chip = substream->rmidi->private_data;
 
        spin_lock_irqsave(&chip->reg_lock, flags);
        if (up) {
@@ -2703,7 +2613,7 @@ static void snd_cs46xx_midi_input_trigger(snd_rawmidi_substream_t * substream, i
 static void snd_cs46xx_midi_output_trigger(snd_rawmidi_substream_t * substream, int up)
 {
        unsigned long flags;
-       cs46xx_t *chip = snd_magic_cast(cs46xx_t, substream->rmidi->private_data, return);
+       cs46xx_t *chip = substream->rmidi->private_data;
        unsigned char byte;
 
        spin_lock_irqsave(&chip->reg_lock, flags);
@@ -2781,7 +2691,7 @@ static void snd_cs46xx_gameport_trigger(struct gameport *gameport)
        cs46xx_gameport_t *gp = (cs46xx_gameport_t *)gameport;
        cs46xx_t *chip;
        snd_assert(gp, return);
-       chip = snd_magic_cast(cs46xx_t, gp->chip, return);
+       chip = gp->chip;
        snd_cs46xx_pokeBA0(chip, BA0_JSPT, 0xFF);  //outb(gameport->io, 0xFF);
 }
 
@@ -2790,7 +2700,7 @@ static unsigned char snd_cs46xx_gameport_read(struct gameport *gameport)
        cs46xx_gameport_t *gp = (cs46xx_gameport_t *)gameport;
        cs46xx_t *chip;
        snd_assert(gp, return 0);
-       chip = snd_magic_cast(cs46xx_t, gp->chip, return 0);
+       chip = gp->chip;
        return snd_cs46xx_peekBA0(chip, BA0_JSPT); //inb(gameport->io);
 }
 
@@ -2801,7 +2711,7 @@ static int snd_cs46xx_gameport_cooked_read(struct gameport *gameport, int *axes,
        unsigned js1, js2, jst;
        
        snd_assert(gp, return 0);
-       chip = snd_magic_cast(cs46xx_t, gp->chip, return 0);
+       chip = gp->chip;
 
        js1 = snd_cs46xx_peekBA0(chip, BA0_JSC1);
        js2 = snd_cs46xx_peekBA0(chip, BA0_JSC2);
@@ -3011,13 +2921,13 @@ static int snd_cs46xx_free(cs46xx_t *chip)
        }
 #endif
        
-       snd_magic_kfree(chip);
+       kfree(chip);
        return 0;
 }
 
 static int snd_cs46xx_dev_free(snd_device_t *device)
 {
-       cs46xx_t *chip = snd_magic_cast(cs46xx_t, device->device_data, return -ENXIO);
+       cs46xx_t *chip = device->device_data;
        return snd_cs46xx_free(chip);
 }
 
@@ -3786,7 +3696,7 @@ static struct cs_card_type __devinitdata cards[] = {
 #ifdef CONFIG_PM
 static int snd_cs46xx_suspend(snd_card_t *card, unsigned int state)
 {
-       cs46xx_t *chip = snd_magic_cast(cs46xx_t, card->pm_private_data, return -EINVAL);
+       cs46xx_t *chip = card->pm_private_data;
        int amp_saved;
 
        snd_pcm_suspend_all(chip->pcm);
@@ -3810,7 +3720,7 @@ static int snd_cs46xx_suspend(snd_card_t *card, unsigned int state)
 
 static int snd_cs46xx_resume(snd_card_t *card, unsigned int state)
 {
-       cs46xx_t *chip = snd_magic_cast(cs46xx_t, card->pm_private_data, return -EINVAL);
+       cs46xx_t *chip = card->pm_private_data;
        int amp_saved;
 
        pci_enable_device(chip->pci);
@@ -3869,7 +3779,7 @@ int __devinit snd_cs46xx_create(snd_card_t * card,
        if ((err = pci_enable_device(pci)) < 0)
                return err;
 
-       chip = snd_magic_kcalloc(cs46xx_t, 0, GFP_KERNEL);
+       chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
        if (chip == NULL)
                return -ENOMEM;
        spin_lock_init(&chip->reg_lock);
@@ -3913,10 +3823,6 @@ int __devinit snd_cs46xx_create(snd_card_t * card,
        region->base = chip->ba1_addr + BA1_SP_REG;
        region->size = CS46XX_BA1_REG_SIZE;
 
-       memset(&chip->dma_dev, 0, sizeof(chip->dma_dev));
-       chip->dma_dev.type = SNDRV_DMA_TYPE_DEV;
-       chip->dma_dev.dev = snd_dma_pci_data(pci);
-
        /* set up amp and clkrun hack */
        pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &ss_vendor);
        pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &ss_card);