Update of /cvsroot/alsa/alsa-driver/pcmcia/vx
In directory sc8-pr-cvs1:/tmp/cvs-serv4339/pcmcia/vx

Modified Files:
        Makefile d563s3_boot.c vx_entry.c vxp440.c vxpocket.c 
        vxpocket.conf vxpocket.h xilinx_image_vp4.c xilinx_image_vxp.c 
Added Files:
        vxp440.conf vxp_mixer.c vxp_ops.c 
Removed Files:
        vx_cmd.c vx_cmd.h vx_core.c vx_irq.c vx_mixer.c vx_pcm.c 
        vx_uer.c 
Log Message:
[Patch: vx-core-in-driver.dif]

- moved VXpocket/VX222 core part into drivers/vx directory.
- the common header vx_core.h in include directory.
- changed the vx-core entry using ops table.
- added vxp440.conf.



--- NEW FILE: vxp440.conf ---
#
# PCMCIA device driver definitions for Digigram VXpocket440 card
#
# put this file under /etc/pcmcia
#

device "snd-vxp440"
  class "audio" module "snd-vxp440"

#
# card definitions
#

card "Digigram VX-POCKET440"
  manfid 0x01f1, 0x0100
  bind "snd-vxp440"


--- NEW FILE: vxp_mixer.c ---
/* to be in alsa-driver-specific code */
#define __NO_VERSION__

/*
 * Driver for Digigram VXpocket soundcards
 *
 * VX-pocket mixer
 *
 * Copyright (c) 2002 by Takashi Iwai <[EMAIL PROTECTED]>
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 */

#include <sound/driver.h>
#include <sound/core.h>
#include <sound/control.h>
#include "vxpocket.h"

#define chip_t vx_core_t

#define MIC_LEVEL_MIN   0
#define MIC_LEVEL_MAX   8

/*
 * mic level control (for VXPocket)
 */
static int vx_mic_level_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
{
        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
        uinfo->count = 1;
        uinfo->value.integer.min = 0;
        uinfo->value.integer.max = MIC_LEVEL_MAX;
        return 0;
}

static int vx_mic_level_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
{
        vx_core_t *_chip = snd_kcontrol_chip(kcontrol);
        struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
        ucontrol->value.integer.value[0] = chip->mic_level;
        return 0;
}

static int vx_mic_level_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
{
        vx_core_t *_chip = snd_kcontrol_chip(kcontrol);
        struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
        if (chip->mic_level != ucontrol->value.integer.value[0]) {
                vx_set_mic_level(_chip, ucontrol->value.integer.value[0]);
                chip->mic_level = ucontrol->value.integer.value[0];
                return 1;
        }
        return 0;
}

static snd_kcontrol_new_t vx_control_mic_level = {
        .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
        .name =         "Mic Capture Volume",
        .info =         vx_mic_level_info,
        .get =          vx_mic_level_get,
        .put =          vx_mic_level_put,
};

/*
 * mic boost level control (for VXP440)
 */
static int vx_mic_boost_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
{
        uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
        uinfo->count = 1;
        uinfo->value.integer.min = 0;
        uinfo->value.integer.max = 1;
        return 0;
}

static int vx_mic_boost_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
{
        vx_core_t *_chip = snd_kcontrol_chip(kcontrol);
        struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
        ucontrol->value.integer.value[0] = chip->mic_level;
        return 0;
}

static int vx_mic_boost_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
{
        vx_core_t *_chip = snd_kcontrol_chip(kcontrol);
        struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
        if (chip->mic_level != ucontrol->value.integer.value[0]) {
                vx_set_mic_boost(_chip, ucontrol->value.integer.value[0]);
                chip->mic_level = ucontrol->value.integer.value[0];
                return 1;
        }
        return 0;
}

static snd_kcontrol_new_t vx_control_mic_boost = {
        .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
        .name =         "Mic Boost",
        .info =         vx_mic_boost_info,
        .get =          vx_mic_boost_get,
        .put =          vx_mic_boost_put,
};


int vxp_add_mic_controls(vx_core_t *_chip)
{
        struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
        int err;

        /* mute input levels */
        chip->mic_level = 0;
        switch (_chip->type) {
        case VX_TYPE_VXPOCKET:
                vx_set_mic_level(_chip, 0);
                break;
        case VX_TYPE_VXP440:
                vx_set_mic_boost(_chip, 0);
                break;
        }

        /* mic level */
        switch (_chip->type) {
        case VX_TYPE_VXPOCKET:
                if ((err = snd_ctl_add(_chip->card, 
snd_ctl_new1(&vx_control_mic_level, chip))) < 0)
                        return err;
                break;
        case VX_TYPE_VXP440:
                if ((err = snd_ctl_add(_chip->card, 
snd_ctl_new1(&vx_control_mic_boost, chip))) < 0)
                        return err;
                break;
        }

        return 0;
}


--- NEW FILE: vxp_ops.c ---
/* to be in alsa-driver-specific code */
#define __NO_VERSION__

/*
 * Driver for Digigram VXpocket soundcards
 *
 * lowlevel routines for VXpocket soundcards
 *
 * Copyright (c) 2002 by Takashi Iwai <[EMAIL PROTECTED]>
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 */

#include <sound/driver.h>
#include <linux/delay.h>
#include <sound/core.h>
#include <asm/io.h>
#include "vxpocket.h"

#define chip_t vx_core_t


static int vxp_reg_offset[VX_REG_MAX] = {
        [VX_ICR]        = 0x00,         // ICR
        [VX_CVR]        = 0x01,         // CVR
        [VX_ISR]        = 0x02,         // ISR
        [VX_IVR]        = 0x03,         // IVR
        [VX_RXH]        = 0x05,         // RXH
        [VX_RXM]        = 0x06,         // RXM
        [VX_RXL]        = 0x07,         // RXL
        [VX_DMA]        = 0x04,         // DMA
        [VX_CDSP]       = 0x08,         // CDSP
        [VX_LOFREQ]     = 0x09,         // LFREQ
        [VX_HIFREQ]     = 0x0a,         // HFREQ
        [VX_DATA]       = 0x0b,         // DATA
        [VX_MICRO]      = 0x0c,         // MICRO
        [VX_DIALOG]     = 0x0d,         // DIALOG
        [VX_CSUER]      = 0x0e,         // CSUER
        [VX_RUER]       = 0x0f,         // RUER
};


inline static unsigned long vxp_reg_addr(vx_core_t *_chip, int reg)
{
        struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
        return chip->port + vxp_reg_offset[reg];
}

/*
 * snd_vx_inb - read a byte from the register
 * @offset: register offset
 */
static unsigned char vxp_inb(vx_core_t *chip, int offset)
{
        return inb(vxp_reg_addr(chip, offset));
}

/*
 * snd_vx_outb - write a byte on the register
 * @offset: the register offset
 * @val: the value to write
 */
static void vxp_outb(vx_core_t *chip, int offset, unsigned char val)
{
        outb(val, vxp_reg_addr(chip, offset));
}

/*
 * redefine macros to call directly
 */
#undef vx_inb
#define vx_inb(chip,reg)        vxp_inb((vx_core_t*)(chip), VX_##reg)
#undef vx_outb
#define vx_outb(chip,reg,val)   vxp_outb((vx_core_t*)(chip), VX_##reg,val)


/*
 * vx_check_magic - check the magic word on xilinx
 *
 * returns zero if a magic word is detected, or a negative error code.
 */
static int vx_check_magic(vx_core_t *chip)
{
        long end_time = jiffies + HZ / 5;
        int c;
        do {
                c = vx_inb(chip, CDSP);
                if (c == CDSP_MAGIC)
                        return 0;
                snd_vx_delay(chip, 10);
        } while (time_after_eq(end_time, jiffies));
        snd_printk(KERN_ERR "cannot find xilinx magic word (%x)\n", c);
        return -EIO;
}


/*
 * vx_test_xilinx - check whether the xilinx is initialized
 *
 * returns zero if xilinx was already initialized, or a negative error code.
 */
static int vxp_test_xilinx(vx_core_t *chip)
{
        chip->xilinx_tested = 1; /* always ok */
        return 0;
}


/*
 * vx_reset_dsp - reset the DSP
 */

#define XX_DSP_RESET_WAIT_TIME          2       /* ms */

static void vxp_reset_dsp(vx_core_t *_chip)
{
        struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;

        /* set the reset dsp bit to 1 */
        vx_outb(chip, CDSP, chip->regCDSP | VXP_CDSP_DSP_RESET_MASK);
        mdelay(XX_DSP_RESET_WAIT_TIME);
        /* reset the bit */
        chip->regCDSP &= ~VXP_CDSP_DSP_RESET_MASK;
        vx_outb(chip, CDSP, chip->regCDSP);
        mdelay(XX_DSP_RESET_WAIT_TIME);
}

/*
 * reset codec bit
 */
static void vxp_reset_codec(vx_core_t *_chip)
{
        struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;

        /* Set the reset CODEC bit to 1. */
        vx_outb(chip, CDSP, chip->regCDSP | VXP_CDSP_CODEC_RESET_MASK);
        snd_vx_delay(_chip, 10);
        /* Set the reset CODEC bit to 0. */
        chip->regCDSP &= ~VXP_CDSP_CODEC_RESET_MASK;
        vx_outb(chip, CDSP, chip->regCDSP);
        snd_vx_delay(_chip, 1);
}

/*
 * vx_load_xilinx_binary - load the xilinx binary image
 * the binary image is the binary array converted from the bitstream file.
 */
static int vxp_load_xilinx_binary(vx_core_t *_chip)
{
        struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
        const struct snd_vx_image *xilinx = &_chip->hw->xilinx;
        int i, c, err;
        int regCSUER, regRUER;

        if ((err = vx_check_magic(_chip)) < 0)
                return err;

        if ((err = snd_vx_load_boot_image(_chip, &_chip->hw->boot)) < 0)
                return err;

        snd_printdd(KERN_DEBUG "loading xilinx: size = %d\n", xilinx->length);
        /* Switch to programmation mode */
        chip->regDIALOG |= VXP_DLG_XILINX_REPROG_MASK;
        vx_outb(chip, DIALOG, chip->regDIALOG);

        /* Save register CSUER and RUER */
        regCSUER = vx_inb(chip, CSUER);
        regRUER = vx_inb(chip, RUER);

        /* reset HF0 and HF1 */
        vx_outb(chip, ICR, 0);

        /* Wait for answer HF2 equal to 1 */
        snd_printdd(KERN_DEBUG "check ISR_HF2\n");
        if (vx_check_isr(_chip, ISR_HF2, ISR_HF2, 20) < 0)
                goto _error;

        /* set HF1 for loading xilinx binary */
        vx_outb(chip, ICR, ICR_HF1);
        for (i = 0; i < xilinx->length; i++) {
                if (vx_wait_isr_bit(_chip, ISR_TX_EMPTY) < 0)
                        goto _error;
                vx_outb(chip, TXL, xilinx->image[i]);

                /* wait for reading */
                if (vx_wait_for_rx_full(_chip) < 0)
                        goto _error;
                c = vx_inb(chip, RXL);
                if (c != xilinx->image[i])
                        snd_printk(KERN_ERR "vxpocket: load xilinx mismatch at %d: 
0x%x != 0x%x\n", i, c, xilinx->image[i]);
        }

        /* reset HF1 */
        vx_outb(chip, ICR, 0);

        /* wait for HF3 */
        if (vx_check_isr(_chip, ISR_HF3, ISR_HF3, 20) < 0)
                goto _error;

        /* read the number of bytes received */
        if (vx_wait_for_rx_full(_chip) < 0)
                goto _error;

        c = (int)vx_inb(chip, RXH) << 16;
        c |= (int)vx_inb(chip, RXM) << 8;
        c |= vx_inb(chip, RXL);

        snd_printdd(KERN_DEBUG "xilinx: dsp size received 0x%x, orig 0x%x\n", c, 
xilinx->length);

        vx_outb(chip, ICR, ICR_HF0);

        /* TEMPO 250ms : wait until Xilinx is downloaded */
        snd_vx_delay(_chip, 300);

        /* test magical word */
        if (vx_check_magic(_chip) < 0)
                goto _error;

        /* Restore register 0x0E and 0x0F (thus replacing COR and FCSR) */
        vx_outb(chip, CSUER, regCSUER);
        vx_outb(chip, RUER, regRUER);

        /* Reset the Xilinx's signal enabling IO access */
        chip->regDIALOG |= VXP_DLG_XILINX_REPROG_MASK;
        vx_outb(chip, DIALOG, chip->regDIALOG);
        snd_vx_delay(_chip, 10);
        chip->regDIALOG &= ~VXP_DLG_XILINX_REPROG_MASK;
        vx_outb(chip, DIALOG, chip->regDIALOG);

        /* Reset of the Codec */
        vxp_reset_codec(_chip);
        vx_reset_dsp(_chip);

        return 0;

 _error:
        vx_outb(chip, CSUER, regCSUER);
        vx_outb(chip, RUER, regRUER);
        chip->regDIALOG &= ~VXP_DLG_XILINX_REPROG_MASK;
        vx_outb(chip, DIALOG, chip->regDIALOG);
        return -EIO;
}


/*
 * vx_test_and_ack - test and acknowledge interrupt
 *
 * called from irq hander, too
 *
 * spinlock held!
 */
static int vxp_test_and_ack(vx_core_t *_chip)
{
        struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;

        /* not booted yet? */
        if (! _chip->xilinx_tested)
                return -ENXIO;

        if (! (vx_inb(chip, DIALOG) & VXP_DLG_MEMIRQ_MASK))
                return -EIO;
        
        /* ok, interrupts generated, now ack it */
        /* set ACQUIT bit up and down */
        vx_outb(chip, DIALOG, chip->regDIALOG | VXP_DLG_ACK_MEMIRQ_MASK);
        /* useless read just to spend some time and maintain
         * the ACQUIT signal up for a while ( a bus cycle )
         */
        vx_inb(chip, DIALOG);
        vx_outb(chip, DIALOG, chip->regDIALOG & ~VXP_DLG_ACK_MEMIRQ_MASK);

        return 0;
}


/*
 * vx_validate_irq - enable/disable IRQ
 */
static void vxp_validate_irq(vx_core_t *_chip, int enable)
{
        struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;

        /* Set the interrupt enable bit to 1 in CDSP register */
        if (enable)
                chip->regCDSP |= VXP_CDSP_VALID_IRQ_MASK;
        else
                chip->regCDSP &= ~VXP_CDSP_VALID_IRQ_MASK;
        vx_outb(chip, CDSP, chip->regCDSP);
}

/*
 * vx_setup_pseudo_dma - set up the pseudo dma read/write mode.
 * @do_write: 0 = read, 1 = set up for DMA write
 */
static void vx_setup_pseudo_dma(vx_core_t *_chip, int do_write)
{
        struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;

        /* Interrupt mode and HREQ pin enabled for host transmit / receive data 
transfers */
        vx_outb(chip, ICR, do_write ? ICR_TREQ : ICR_RREQ);
        /* Reset the pseudo-dma register */
        vx_inb(chip, ISR);
        vx_outb(chip, ISR, 0);

        /* Select DMA in read/write transfer mode and in 16-bit accesses */
        chip->regDIALOG |= VXP_DLG_DMA16_SEL_MASK;
        chip->regDIALOG |= do_write ? VXP_DLG_DMAWRITE_SEL_MASK : 
VXP_DLG_DMAREAD_SEL_MASK;
        vx_outb(chip, DIALOG, chip->regDIALOG);

}

/*
 * vx_release_pseudo_dma - disable the pseudo-DMA mode
 */
static void vx_release_pseudo_dma(vx_core_t *_chip)
{
        struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;

        /* Disable DMA and 16-bit accesses */
        chip->regDIALOG &= ~(VXP_DLG_DMAWRITE_SEL_MASK|
                             VXP_DLG_DMAREAD_SEL_MASK|
                             VXP_DLG_DMA16_SEL_MASK);
        vx_outb(chip, DIALOG, chip->regDIALOG);
        /* HREQ pin disabled. */
        vx_outb(chip, ICR, 0);
}

/*
 * vx_pseudo_dma_write - write bulk data on pseudo-DMA mode
 * @count: data length to transfer in bytes
 *
 * data size must be aligned to 6 bytes to ensure the 24bit alignment on DSP.
 * NB: call with a certain lock!
 */
static void vxp_dma_write(vx_core_t *chip, snd_pcm_runtime_t *runtime,
                          vx_pipe_t *pipe, int count)
{
        long port = vxp_reg_addr(chip, VX_DMA);
        int offset = frames_to_bytes(runtime, pipe->hw_ptr);
        unsigned short *addr = (unsigned short *)(runtime->dma_area + offset);

        vx_setup_pseudo_dma(chip, 1);
        if (offset + count > pipe->buffer_bytes) {
                int length = pipe->buffer_bytes - offset;
                count -= length;
                length >>= 1; /* in 16bit words */
                /* Transfer using pseudo-dma. */
                while (length-- > 0) {
                        outw(cpu_to_le16(*addr), port);
                        addr++;
                }
                addr = (unsigned short *)runtime->dma_area;
                pipe->hw_ptr = 0;
        }
        pipe->hw_ptr += bytes_to_frames(runtime, count);
        count >>= 1; /* in 16bit words */
        /* Transfer using pseudo-dma. */
        while (count-- > 0) {
                outw(cpu_to_le16(*addr), port);
                addr++;
        }
        vx_release_pseudo_dma(chip);
}


/*
 * vx_pseudo_dma_read - read bulk data on pseudo DMA mode
 * @offset: buffer offset in bytes
 * @count: data length to transfer in bytes
 *
 * the read length must be aligned to 6 bytes, as well as write.
 * NB: call with a certain lock!
 */
static void vxp_dma_read(vx_core_t *chip, snd_pcm_runtime_t *runtime,
                         vx_pipe_t *pipe, int count)
{
        struct snd_vxpocket *pchip = (struct snd_vxpocket *)chip;
        long port = vxp_reg_addr(chip, VX_DMA);
        int offset = frames_to_bytes(runtime, pipe->hw_ptr);
        unsigned short *addr = (unsigned short *)(runtime->dma_area + offset);

        snd_assert(count % 6 == 0, return);
        vx_setup_pseudo_dma(chip, 0);
        if (offset + count > pipe->buffer_bytes) {
                int length = pipe->buffer_bytes - offset;
                count -= length;
                length >>= 1; /* in 16bit words */
                /* Transfer using pseudo-dma. */
                while (length-- > 0)
                        *addr++ = le16_to_cpu(inw(port));
                addr = (unsigned short *)runtime->dma_area;
                pipe->hw_ptr = 0;
        }
        pipe->hw_ptr += bytes_to_frames(runtime, count);
        count >>= 1; /* in 16bit words */
        /* Transfer using pseudo-dma. */
        while (count-- > 1)
                *addr++ = le16_to_cpu(inw(port));
        /* Disable DMA */
        pchip->regDIALOG &= ~VXP_DLG_DMAREAD_SEL_MASK;
        vx_outb(chip, DIALOG, pchip->regDIALOG);
        /* Read the last word (16 bits) */
        *addr = le16_to_cpu(inw(port));
        /* Disable 16-bit accesses */
        pchip->regDIALOG &= ~VXP_DLG_DMA16_SEL_MASK;
        vx_outb(chip, DIALOG, pchip->regDIALOG);
        /* HREQ pin disabled. */
        vx_outb(chip, ICR, 0);
}


/*
 * write a codec data (24bit)
 */
static void vxp_write_codec_reg(vx_core_t *chip, int codec, unsigned int data)
{
        int i;

        /* Activate access to the corresponding codec register */
        if (! codec)
                vx_inb(chip, LOFREQ);
        else
                vx_inb(chip, CODEC2);
                
        /* We have to send 24 bits (3 x 8 bits). Start with most signif. Bit */
        for (i = 0; i < 24; i++, data <<= 1)
                vx_outb(chip, DATA, ((data & 0x800000) ? VX_DATA_CODEC_MASK : 0));
        
        /* Terminate access to codec registers */
        vx_inb(chip, HIFREQ);
}


/*
 * vx_set_mic_boost - set mic boost level (on vxp440 only)
 * @boost: 0 = 20dB, 1 = +38dB
 */
void vx_set_mic_boost(vx_core_t *chip, int boost)
{
        struct snd_vxpocket *pchip = (struct snd_vxpocket *)chip;
        unsigned long flags;

        if (chip->is_stale)
                return;

        spin_lock_irqsave(&chip->lock, flags);
        if (pchip->regCDSP & P24_CDSP_MICS_SEL_MASK) {
                if (boost) {
                        /* boost: 38 dB */
                        pchip->regCDSP &= ~P24_CDSP_MIC20_SEL_MASK;
                        pchip->regCDSP |=  P24_CDSP_MIC38_SEL_MASK;
                } else {
                        /* minimum value: 20 dB */
                        pchip->regCDSP |=  P24_CDSP_MIC20_SEL_MASK;
                        pchip->regCDSP &= ~P24_CDSP_MIC38_SEL_MASK;
                }
                vx_outb(chip, CDSP, pchip->regCDSP);
        }
        spin_unlock_irqrestore(&chip->lock, flags);
}

/*
 * remap the linear value (0-8) to the actual value (0-15)
 */
static int vx_compute_mic_level(int level)
{
        switch (level) {
        case 5: level = 6 ; break;
        case 6: level = 8 ; break;
        case 7: level = 11; break;
        case 8: level = 15; break;
        default: break ;
        }
        return level;
}

/*
 * vx_set_mic_level - set mic level (on vxpocket only)
 * @level: the mic level = 0 - 8 (max)
 */
void vx_set_mic_level(vx_core_t *chip, int level)
{
        struct snd_vxpocket *pchip = (struct snd_vxpocket *)chip;
        unsigned long flags;

        if (chip->is_stale)
                return;

        spin_lock_irqsave(&chip->lock, flags);
        if (pchip->regCDSP & VXP_CDSP_MIC_SEL_MASK) {
                level = vx_compute_mic_level(level);
                vx_outb(chip, MICRO, level);
        }
        spin_unlock_irqrestore(&chip->lock, flags);
}


/*
 * change the input audio source
 */
static void vxp_change_audio_source(vx_core_t *_chip, int src)
{
        struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;

        switch (src) {
        case VX_AUDIO_SRC_DIGITAL:
                chip->regCDSP |= VXP_CDSP_DATAIN_SEL_MASK;
                vx_outb(chip, CDSP, chip->regCDSP);
                break;
        case VX_AUDIO_SRC_LINE:
                chip->regCDSP &= ~VXP_CDSP_DATAIN_SEL_MASK;
                if (_chip->type == VX_TYPE_VXP440)
                        chip->regCDSP &= ~P24_CDSP_MICS_SEL_MASK;
                else
                        chip->regCDSP &= ~VXP_CDSP_MIC_SEL_MASK;
                vx_outb(chip, CDSP, chip->regCDSP);
                break;
        case VX_AUDIO_SRC_MIC:
                chip->regCDSP &= ~VXP_CDSP_DATAIN_SEL_MASK;
                /* reset mic levels */
                if (_chip->type == VX_TYPE_VXP440) {
                        chip->regCDSP &= ~P24_CDSP_MICS_SEL_MASK;
                        if (chip->mic_level)
                                chip->regCDSP |=  P24_CDSP_MIC38_SEL_MASK;
                        else
                                chip->regCDSP |= P24_CDSP_MIC20_SEL_MASK;
                        vx_outb(chip, CDSP, chip->regCDSP);
                } else {
                        chip->regCDSP |= VXP_CDSP_MIC_SEL_MASK;
                        vx_outb(chip, CDSP, chip->regCDSP);
                        vx_outb(chip, MICRO, vx_compute_mic_level(chip->mic_level));
                }
                break;
        }
}

/*
 * change the clock source
 * source = INTERNAL_QUARTZ or UER_SYNC
 */
static void vxp_set_clock_source(vx_core_t *_chip, int source)
{
        struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;

        if (source == INTERNAL_QUARTZ)
                chip->regCDSP &= ~VXP_CDSP_CLOCKIN_SEL_MASK;
        else
                chip->regCDSP |= VXP_CDSP_CLOCKIN_SEL_MASK;
        vx_outb(chip, CDSP, chip->regCDSP);
}


/*
 * reset the board
 */
static void vxp_reset_board(vx_core_t *_chip)
{
        struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;

        chip->regCDSP = 0;
        chip->regDIALOG = 0;
}


/*
 * callbacks
 */
/* exported */
struct snd_vx_ops snd_vxpocket_ops = {
        .in8 = vxp_inb,
        .out8 = vxp_outb,
        .test_and_ack = vxp_test_and_ack,
        .validate_irq = vxp_validate_irq,
        .write_codec = vxp_write_codec_reg,
        .reset_codec = vxp_reset_codec,
        .change_audio_source = vxp_change_audio_source,
        .set_clock_source = vxp_set_clock_source,
        .test_xilinx = vxp_test_xilinx,
        .load_xilinx = vxp_load_xilinx_binary,
        .reset_dsp = vxp_reset_dsp,
        .reset_board = vxp_reset_board,
        .dma_write = vxp_dma_write,
        .dma_read = vxp_dma_read,
};

Index: Makefile
===================================================================
RCS file: /cvsroot/alsa/alsa-driver/pcmcia/vx/Makefile,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- Makefile    30 Oct 2002 16:44:23 -0000      1.1
+++ Makefile    9 Jan 2003 16:13:16 -0000       1.2
@@ -1,8 +1,5 @@
 TOPDIR = ../..
 
-CONFIG_SND_VXPOCKET=m
-CONFIG_SND_VXP440=m
-
 include $(TOPDIR)/toplevel.config
 include $(TOPDIR)/Makefile.conf
 
@@ -12,19 +9,12 @@
 
 TOPDIR = $(MAINSRCDIR)
 
-export-objs := vx_core.o
-
-# vx_entry.o is included in each card module to avoid the dependency
-# of snd-vxp-lib to pcmcia stuff
-
-snd-vxpocket-objs := vxpocket.o vx_entry.o
-snd-vxp440-objs := vxp440.o vx_entry.o
-snd-vxp-lib-objs := vx_core.o vx_pcm.o vx_mixer.o vx_cmd.o vx_irq.o vx_uer.o
+# export-objs := vx_entry.o
+# snd-vxpocket-lib-objs := vx_entry.o vxp_ops.o vxp_mixer.o
+snd-vxpocket-objs := vxpocket.o vx_entry.o vxp_ops.o vxp_mixer.o
+snd-vxp440-objs := vxp440.o vx_entry.o vxp_ops.o vxp_mixer.o
 
-obj-$(CONFIG_SND_VXPOCKET) += snd-vxpocket.o snd-vxp-lib.o
-obj-$(CONFIG_SND_VXP440) += snd-vxp440.o snd-vxp-lib.o
+obj-$(CONFIG_SND_VXPOCKET) += snd-vxpocket.o
+obj-$(CONFIG_SND_VXP440) += snd-vxp440.o
 
 include $(TOPDIR)/Rules.make
-
-
-

Index: d563s3_boot.c
===================================================================
RCS file: /cvsroot/alsa/alsa-driver/pcmcia/vx/d563s3_boot.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- d563s3_boot.c       30 Oct 2002 16:44:23 -0000      1.1
+++ d563s3_boot.c       9 Jan 2003 16:13:18 -0000       1.2
@@ -1,66 +1,66 @@
-/*
- * Driver for Digigram VXpocket soundcards
- *
- * Xilinx boot image for VXpocket 440.
- *
- * Copyright (c) 2002 by Digigram S.A.
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- */
-
-static unsigned char d563s3_boot[504] = {
-       0x00, 0x00, 0xa6, 0x00, 0x00, 0x00, 0x0d, 0x10, 0xc0, 0x00, 0x00, 0x3d,
-       0x0a, 0x82, 0x23, 0x25, 0x00, 0x00, 0x0c, 0xc3, 0x00, 0x00, 0x00, 0x00,
-       0x08, 0x47, 0x06, 0x20, 0xf0, 0x00, 0x05, 0xf4, 0x20, 0xff, 0xff, 0xff,
-       0x0c, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x08, 0x47, 0x06, 0x20, 0xe6, 0x00,
-       0x0c, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x08, 0x47, 0x06, 0x0c, 0xc7, 0xa3,
-       0x00, 0x00, 0x09, 0x0c, 0xc7, 0xa0, 0x00, 0x00, 0x0d, 0x0c, 0xc7, 0xa1,
-       0x00, 0x00, 0x12, 0x0c, 0xc7, 0xa2, 0x00, 0x00, 0x17, 0x05, 0x0c, 0x42,
-       0x06, 0xc6, 0x10, 0x00, 0x00, 0x04, 0x0c, 0xc3, 0x00, 0x00, 0x00, 0x00,
-       0x08, 0x47, 0x06, 0x05, 0x0f, 0xc5, 0x06, 0xc6, 0x10, 0x00, 0x00, 0x05,
-       0x0c, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x08, 0x47, 0x06, 0x47, 0x58, 0x00,
-       0x05, 0x0f, 0x9e, 0x06, 0xc6, 0x10, 0x00, 0x00, 0x05, 0x0c, 0xc3, 0x00,
-       0x00, 0x00, 0x00, 0x08, 0x47, 0x06, 0x4f, 0x58, 0x00, 0x05, 0x0f, 0x97,
-       0x0a, 0xc5, 0x60, 0x05, 0x84, 0x04, 0x22, 0x11, 0x00, 0x05, 0xf4, 0x21,
-       0xff, 0xff, 0xff, 0x06, 0xc6, 0x10, 0x00, 0x00, 0x06, 0x0c, 0xc3, 0x00,
-       0x00, 0x00, 0x00, 0x08, 0x47, 0x06, 0x07, 0x58, 0x87, 0x00, 0x00, 0x00,
-       0x05, 0x0f, 0x8a, 0x00, 0x03, 0xf8, 0x0a, 0xe1, 0x80, 0x00, 0x00, 0x84,
-       0x20, 0x00, 0x13, 0x08, 0xf4, 0xb9, 0x00, 0x04, 0x39, 0x08, 0xf4, 0xb8,
-       0x00, 0x04, 0x21, 0x0a, 0xfa, 0x6e, 0x08, 0xf4, 0xbd, 0x34, 0x00, 0x08,
-       0x08, 0xf4, 0xbb, 0x01, 0x20, 0x21, 0x08, 0xf4, 0x84, 0x00, 0x10, 0x18,
-       0x0a, 0x84, 0x26, 0x04, 0xcc, 0xdf, 0x07, 0xf4, 0x35, 0x20, 0x10, 0x00,
-       0x07, 0xf4, 0x36, 0x03, 0x30, 0x00, 0x07, 0xf4, 0x34, 0x00, 0xff, 0xff,
-       0x07, 0xf4, 0x33, 0x00, 0xff, 0xff, 0x07, 0xf4, 0x32, 0x00, 0xff, 0xff,
-       0x07, 0xf4, 0x31, 0x00, 0xff, 0xff, 0x07, 0xf4, 0x3d, 0x00, 0x00, 0x00,
-       0x07, 0xf4, 0x3e, 0x00, 0x00, 0x00, 0x07, 0xf4, 0x3f, 0x00, 0x00, 0x3c,
-       0x04, 0xcc, 0xdc, 0x04, 0xcc, 0xcf, 0x07, 0xf4, 0x25, 0x20, 0x10, 0x00,
-       0x07, 0xf4, 0x26, 0x03, 0x30, 0x00, 0x07, 0xf4, 0x24, 0x00, 0xff, 0xff,
-       0x07, 0xf4, 0x23, 0x00, 0xff, 0xff, 0x07, 0xf4, 0x22, 0x00, 0xff, 0xff,
-       0x07, 0xf4, 0x21, 0x00, 0xff, 0xff, 0x07, 0xf4, 0x2d, 0x00, 0x00, 0x01,
-       0x07, 0xf4, 0x2e, 0x00, 0x00, 0x01, 0x07, 0xf4, 0x2f, 0x00, 0x00, 0x3c,
-       0x04, 0xcc, 0xcc, 0x07, 0xf4, 0x1d, 0x00, 0x00, 0x02, 0x07, 0xf4, 0x1e,
-       0x00, 0x00, 0x00, 0x07, 0xf4, 0x1f, 0x00, 0x00, 0x05, 0x07, 0xf4, 0x1b,
-       0x00, 0xc0, 0x00, 0x07, 0xf4, 0x1c, 0x00, 0x01, 0x00, 0x04, 0xcc, 0x83,
-       0x07, 0xf4, 0x0b, 0x00, 0x08, 0x00, 0x07, 0xf4, 0x07, 0x00, 0x08, 0x00,
-       0x05, 0xf4, 0x20, 0xff, 0xff, 0xff, 0x04, 0x64, 0xa0, 0x30, 0x00, 0x00,
-       0x34, 0x00, 0x00, 0x45, 0xf4, 0x00, 0x01, 0x00, 0x00, 0x44, 0xf4, 0x13,
-       0xff, 0xff, 0xff, 0x20, 0x86, 0x00, 0x06, 0xc5, 0x10, 0x00, 0x00, 0x02,
-       0xb0, 0x18, 0x32, 0x0a, 0xbe, 0x20, 0x00, 0x00, 0x00, 0x0a, 0xbe, 0x01,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x82, 0x22, 0x00, 0xfc, 0xb8,
-       0x60, 0xf4, 0x00, 0x00, 0x00, 0x02, 0x05, 0xf4, 0x20, 0xff, 0xff, 0xff,
-       0x61, 0xf4, 0x00, 0x01, 0x00, 0x00, 0x04, 0x61, 0xa0, 0x44, 0xf4, 0x00,
-       0x00, 0x00, 0x3b, 0x06, 0xc4, 0x10, 0x00, 0x00, 0x04, 0x07, 0xd8, 0x84,
-       0x07, 0x59, 0x84, 0x00, 0x00, 0x00, 0x0a, 0xf0, 0x80, 0x01, 0x00, 0x00,
-};
+/*
+ * Driver for Digigram VXpocket soundcards
+ *
+ * Xilinx boot image for VXpocket V2 and 440.
+ *
+ * Copyright (c) 2002 by Digigram S.A.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+static unsigned char d563s3_boot[504] = {
+       0x00, 0x00, 0xa6, 0x00, 0x00, 0x00, 0x0d, 0x10, 0xc0, 0x00, 0x00, 0x3d,
+       0x0a, 0x82, 0x23, 0x25, 0x00, 0x00, 0x0c, 0xc3, 0x00, 0x00, 0x00, 0x00,
+       0x08, 0x47, 0x06, 0x20, 0xf0, 0x00, 0x05, 0xf4, 0x20, 0xff, 0xff, 0xff,
+       0x0c, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x08, 0x47, 0x06, 0x20, 0xe6, 0x00,
+       0x0c, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x08, 0x47, 0x06, 0x0c, 0xc7, 0xa3,
+       0x00, 0x00, 0x09, 0x0c, 0xc7, 0xa0, 0x00, 0x00, 0x0d, 0x0c, 0xc7, 0xa1,
+       0x00, 0x00, 0x12, 0x0c, 0xc7, 0xa2, 0x00, 0x00, 0x17, 0x05, 0x0c, 0x42,
+       0x06, 0xc6, 0x10, 0x00, 0x00, 0x04, 0x0c, 0xc3, 0x00, 0x00, 0x00, 0x00,
+       0x08, 0x47, 0x06, 0x05, 0x0f, 0xc5, 0x06, 0xc6, 0x10, 0x00, 0x00, 0x05,
+       0x0c, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x08, 0x47, 0x06, 0x47, 0x58, 0x00,
+       0x05, 0x0f, 0x9e, 0x06, 0xc6, 0x10, 0x00, 0x00, 0x05, 0x0c, 0xc3, 0x00,
+       0x00, 0x00, 0x00, 0x08, 0x47, 0x06, 0x4f, 0x58, 0x00, 0x05, 0x0f, 0x97,
+       0x0a, 0xc5, 0x60, 0x05, 0x84, 0x04, 0x22, 0x11, 0x00, 0x05, 0xf4, 0x21,
+       0xff, 0xff, 0xff, 0x06, 0xc6, 0x10, 0x00, 0x00, 0x06, 0x0c, 0xc3, 0x00,
+       0x00, 0x00, 0x00, 0x08, 0x47, 0x06, 0x07, 0x58, 0x87, 0x00, 0x00, 0x00,
+       0x05, 0x0f, 0x8a, 0x00, 0x03, 0xf8, 0x0a, 0xe1, 0x80, 0x00, 0x00, 0x84,
+       0x20, 0x00, 0x13, 0x08, 0xf4, 0xb9, 0x00, 0x04, 0x39, 0x08, 0xf4, 0xb8,
+       0x00, 0x04, 0x21, 0x0a, 0xfa, 0x6e, 0x08, 0xf4, 0xbd, 0x34, 0x00, 0x08,
+       0x08, 0xf4, 0xbb, 0x01, 0x20, 0x21, 0x08, 0xf4, 0x84, 0x00, 0x10, 0x18,
+       0x0a, 0x84, 0x26, 0x04, 0xcc, 0xdf, 0x07, 0xf4, 0x35, 0x20, 0x10, 0x00,
+       0x07, 0xf4, 0x36, 0x03, 0x30, 0x00, 0x07, 0xf4, 0x34, 0x00, 0xff, 0xff,
+       0x07, 0xf4, 0x33, 0x00, 0xff, 0xff, 0x07, 0xf4, 0x32, 0x00, 0xff, 0xff,
+       0x07, 0xf4, 0x31, 0x00, 0xff, 0xff, 0x07, 0xf4, 0x3d, 0x00, 0x00, 0x00,
+       0x07, 0xf4, 0x3e, 0x00, 0x00, 0x00, 0x07, 0xf4, 0x3f, 0x00, 0x00, 0x3c,
+       0x04, 0xcc, 0xdc, 0x04, 0xcc, 0xcf, 0x07, 0xf4, 0x25, 0x20, 0x10, 0x00,
+       0x07, 0xf4, 0x26, 0x03, 0x30, 0x00, 0x07, 0xf4, 0x24, 0x00, 0xff, 0xff,
+       0x07, 0xf4, 0x23, 0x00, 0xff, 0xff, 0x07, 0xf4, 0x22, 0x00, 0xff, 0xff,
+       0x07, 0xf4, 0x21, 0x00, 0xff, 0xff, 0x07, 0xf4, 0x2d, 0x00, 0x00, 0x01,
+       0x07, 0xf4, 0x2e, 0x00, 0x00, 0x01, 0x07, 0xf4, 0x2f, 0x00, 0x00, 0x3c,
+       0x04, 0xcc, 0xcc, 0x07, 0xf4, 0x1d, 0x00, 0x00, 0x02, 0x07, 0xf4, 0x1e,
+       0x00, 0x00, 0x00, 0x07, 0xf4, 0x1f, 0x00, 0x00, 0x05, 0x07, 0xf4, 0x1b,
+       0x00, 0xc0, 0x00, 0x07, 0xf4, 0x1c, 0x00, 0x01, 0x00, 0x04, 0xcc, 0x83,
+       0x07, 0xf4, 0x0b, 0x00, 0x08, 0x00, 0x07, 0xf4, 0x07, 0x00, 0x08, 0x00,
+       0x05, 0xf4, 0x20, 0xff, 0xff, 0xff, 0x04, 0x64, 0xa0, 0x30, 0x00, 0x00,
+       0x34, 0x00, 0x00, 0x45, 0xf4, 0x00, 0x01, 0x00, 0x00, 0x44, 0xf4, 0x13,
+       0xff, 0xff, 0xff, 0x20, 0x86, 0x00, 0x06, 0xc5, 0x10, 0x00, 0x00, 0x02,
+       0xb0, 0x18, 0x32, 0x0a, 0xbe, 0x20, 0x00, 0x00, 0x00, 0x0a, 0xbe, 0x01,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x82, 0x22, 0x00, 0xfc, 0xb8,
+       0x60, 0xf4, 0x00, 0x00, 0x00, 0x02, 0x05, 0xf4, 0x20, 0xff, 0xff, 0xff,
+       0x61, 0xf4, 0x00, 0x01, 0x00, 0x00, 0x04, 0x61, 0xa0, 0x44, 0xf4, 0x00,
+       0x00, 0x00, 0x3b, 0x06, 0xc4, 0x10, 0x00, 0x00, 0x04, 0x07, 0xd8, 0x84,
+       0x07, 0x59, 0x84, 0x00, 0x00, 0x00, 0x0a, 0xf0, 0x80, 0x01, 0x00, 0x00,
+};

Index: vx_entry.c
===================================================================
RCS file: /cvsroot/alsa/alsa-driver/pcmcia/vx/vx_entry.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- vx_entry.c  11 Dec 2002 15:36:33 -0000      1.3
+++ vx_entry.c  9 Jan 2003 16:13:27 -0000       1.4
@@ -1,3 +1,6 @@
+/* to be in alsa-driver-specific code */
+#define __NO_VERSION__
+
 /*
  * Driver for Digigram VXpocket soundcards
  *
@@ -31,33 +34,60 @@
  * prototypes
  */
 static void vxpocket_config(dev_link_t *link);
-static void vxpocket_release(u_long arg);
 static int vxpocket_event(event_t event, int priority, event_callback_args_t *args);
-static void vx_card_free_callback(snd_card_t *card);
 
 
 /*
- * flush the stale links.
- * the last instances might be left unreleased, so we release now before
- * creating a new one.
+ * print the error message related with cs
  */
-static void flush_stale_links(struct snd_vxp_entry *hw)
+static void cs_error(client_handle_t handle, int func, int ret)
 {
-       dev_link_t *link, *next;
-       for (link = hw->dev_list; link; link = next) {
-               next = link->next;
-               if (link->state & DEV_STALE_LINK)
-                       snd_vxpocket_detach(hw ,link);
+       error_info_t err = { func, ret };
+       CardServices(ReportError, handle, &err);
+}
+
+static void vxpocket_release(u_long arg)
+{
+       dev_link_t *link = (dev_link_t *)arg;
+       
+       if (link->state & DEV_CONFIG) {
+               /* release cs resources */
+               CardServices(ReleaseConfiguration, link->handle);
+               CardServices(ReleaseIO, link->handle, &link->io);
+               CardServices(ReleaseIRQ, link->handle, &link->irq);
+               link->state &= ~DEV_CONFIG;
        }
 }
 
 /*
- * print the error message related with cs
+ * destructor
  */
-static void cs_error(client_handle_t handle, int func, int ret)
+static int snd_vxpocket_free(vx_core_t *chip)
 {
-       error_info_t err = { func, ret };
-       CardServices(ReportError, handle, &err);
+       struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip;
+       struct snd_vxp_entry *hw;
+       dev_link_t *link = &vxp->link;
+
+       vxpocket_release((u_long)link);
+
+       /* Break the link with Card Services */
+       if (link->handle)
+               CardServices(DeregisterClient, link->handle);
+
+       chip->initialized = 0;
+       hw = vxp->hw_entry;
+       if (hw)
+               hw->card_list[vxp->index] = NULL;
+       chip->card = NULL;
+
+       snd_magic_kfree(chip);
+       return 0;
+}
+
+static int snd_vxpocket_dev_free(snd_device_t *device)
+{
+       vx_core_t *chip = snd_magic_cast(vx_core_t, device->device_data, return 
+-ENXIO);
+       return snd_vxpocket_free(chip);
 }
 
 /*
@@ -69,20 +99,51 @@
        client_reg_t client_reg;        /* Register with cardmgr */
        dev_link_t *link;               /* Info for cardmgr */
        int i, ret;
-       vxpocket_t *chip;
+       vx_core_t *chip;
+       struct snd_vxpocket *vxp;
+       snd_card_t *card;
+       static snd_device_ops_t ops = {
+               .dev_free =     snd_vxpocket_dev_free,
+       };
+
+       snd_printdd(KERN_DEBUG "vxpocket_attach called\n");
+       /* find an empty slot from the card list */
+       for (i = 0; i < SNDRV_CARDS; i++) {
+               if (! hw->card_list[i])
+                       break;
+       }
+       if (i >= SNDRV_CARDS) {
+               snd_printk(KERN_ERR "vxpocket: too many cards found\n");
+               return NULL;
+       }
+       if (! hw->enable_table[i])
+               return NULL; /* disabled explicitly */
 
-       flush_stale_links(hw);
+       /* ok, create a card instance */
+       card = snd_card_new(hw->index_table[i], hw->id_table[i], THIS_MODULE, 0);
+       if (card == NULL) {
+               snd_printk(KERN_ERR "vxpocket: cannot create a card instance\n");
+               return NULL;
+       }
 
-       chip = snd_vxpocket_create_chip(hw);
+       chip = snd_vx_create(card, hw->hardware, hw->ops,
+                            sizeof(struct snd_vxpocket) - sizeof(vx_core_t));
        if (! chip)
                return NULL;
-       chip->card->private_free = vx_card_free_callback;
 
-       link = &chip->link;
-       link->priv = chip;
+       if (snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops) < 0) {
+               snd_magic_kfree(chip);
+               snd_card_free(card);
+               return NULL;
+       }
 
-       link->release.function = &vxpocket_release;
-       link->release.data = (u_long)link;
+       vxp = (struct snd_vxpocket *)chip;
+       vxp->index = i;
+       vxp->hw_entry = hw;
+       hw->card_list[i] = chip;
+
+       link = &vxp->link;
+       link->priv = chip;
 
        link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
        link->io.NumPorts1 = 16;
@@ -99,6 +160,9 @@
        link->irq.Handler = &snd_vx_irq_handler;
        link->irq.Instance = chip;
 
+       link->release.function = &vxpocket_release;
+       link->release.data = (u_long)link;
+
        link->conf.Attributes = CONF_ENABLE_IRQ;
        link->conf.Vcc = 50;
        link->conf.IntType = INT_MEMORY_AND_IO;
@@ -113,9 +177,12 @@
        client_reg.dev_info = hw->dev_info;
        client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
        client_reg.EventMask = 
-               CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-               CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
-               CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
+               CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL
+#ifdef CONFIG_PM
+               | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET
+               | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME
+#endif
+               ;
        client_reg.event_handler = &vxpocket_event;
        client_reg.Version = 0x0210;
        client_reg.event_callback_args.client_data = link;
@@ -131,44 +198,73 @@
 }
 
 
-/*
+/**
+ * snd_vxpocket_assign_resources - initialize the hardware and card instance.
+ * @port: i/o port for the card
+ * @irq: irq number for the card
+ *
+ * this function assigns the specified port and irq, boot the card,
+ * create pcm and control instances, and initialize the rest hardware.
+ *
+ * returns 0 if successful, or a negative error code.
  */
-static void vx_card_free_callback(snd_card_t *card)
+static int snd_vxpocket_assign_resources(vx_core_t *chip, int port, int irq)
 {
-       vxpocket_t *chip = snd_magic_cast(vxpocket_t, card->private_data, return);
+       int err;
+       snd_card_t *card = chip->card;
+       struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip;
 
-       if (chip->link.state & DEV_CONFIG)
-               vxpocket_release((u_long) &chip->link);
-       snd_vxpocket_free_chip(chip);
-       snd_magic_kfree(chip);
+       snd_printdd(KERN_DEBUG "vxpocket assign resources: port = 0x%x, irq = %d\n", 
+port, irq);
+       vxp->port = port;
+
+       sprintf(card->shortname, "Digigram %s", card->driver);
+       sprintf(card->longname, "%s at 0x%x, irq %i",
+               card->shortname, port, irq);
+
+       if ((err = snd_vx_init(chip)) < 0)
+               return err;
+
+       chip->irq = irq;
+
+       if ((err = snd_vx_pcm_new(chip)) < 0)
+               return err;
+
+       if ((err = snd_vx_mixer_new(chip)) < 0)
+               return err;
+       if ((err = vxp_add_mic_controls(chip)) < 0)
+               return err;
+
+       chip->initialized = 1;
+
+       if ((err = snd_card_register(chip->card)) < 0)
+               return err;
+
+       return 0;
 }
 
+
 /*
  * snd_vxpocket_detach - detach callback for cs
  * @hw: the hardware information
  */
 void snd_vxpocket_detach(struct snd_vxp_entry *hw, dev_link_t *link)
 {
-       dev_link_t **linkp;
-       vxpocket_t *chip = snd_magic_cast(vxpocket_t, link->priv, return);
-
-       /* Locate device structure */
-       for (linkp = &hw->dev_list; *linkp; linkp = &(*linkp)->next)
-               if (*linkp == link)
-                       break;
-       if (*linkp == NULL)
-               return;
+       vx_core_t *chip = snd_magic_cast(vx_core_t, link->priv, return);
 
        del_timer(&link->release);
 
-       /* Break the link with Card Services */
-       if (link->handle)
-               CardServices(DeregisterClient, link->handle);
-    
+       snd_printdd(KERN_DEBUG "vxpocket_detach called\n");
        /* Remove the interface data from the linked list */
-       *linkp = link->next;
-
-       chip->is_stale = 1;
+       if (hw) {
+               dev_link_t **linkp;
+               /* Locate device structure */
+               for (linkp = &hw->dev_list; *linkp; linkp = &(*linkp)->next)
+                       if (*linkp == link)
+                               break;
+               if (*linkp)
+                       *linkp = link->next;
+       }
+       chip->is_stale = 1; /* to be sure */
        snd_card_disconnect(chip->card);
        snd_card_free_in_thread(chip->card);
 }
@@ -182,7 +278,6 @@
                snd_vxpocket_detach(hw, hw->dev_list);
 }
 
-
 /*
  * configuration callback
  */
@@ -193,12 +288,14 @@
 static void vxpocket_config(dev_link_t *link)
 {
        client_handle_t handle = link->handle;
-       vxpocket_t *chip = snd_magic_cast(vxpocket_t, link->priv, return);
+       vx_core_t *chip = snd_magic_cast(vx_core_t, link->priv, return);
+       struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip;
        tuple_t tuple;
        cisparse_t parse;
        u_short buf[32];
        int last_fn, last_ret;
 
+       snd_printdd(KERN_DEBUG "vxpocket_config called\n");
        tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
        tuple.Attributes = 0;
        tuple.TupleData = (cisdata_t *)buf;
@@ -222,29 +319,16 @@
        if (snd_vxpocket_assign_resources(chip, link->io.BasePort1, 
link->irq.AssignedIRQ) < 0)
                goto failed;
 
-       link->dev = &chip->node;
+       link->dev = &vxp->node;
        link->state &= ~DEV_CONFIG_PENDING;
        return;
 
 cs_failed:
        cs_error(link->handle, last_fn, last_ret);
 failed:
-       vxpocket_release((u_long)link);
-}
-
-
-/*
- * release callback
- */
-static void vxpocket_release(u_long arg)
-{
-       dev_link_t *link = (dev_link_t *)arg;
-
        CardServices(ReleaseConfiguration, link->handle);
        CardServices(ReleaseIO, link->handle, &link->io);
        CardServices(ReleaseIRQ, link->handle, &link->irq);
-
-       link->state &= ~DEV_CONFIG;
 }
 
 
@@ -254,44 +338,67 @@
 static int vxpocket_event(event_t event, int priority, event_callback_args_t *args)
 {
        dev_link_t *link = args->client_data;
-       vxpocket_t *chip = link->priv;
+       vx_core_t *chip = link->priv;
 
        switch (event) {
        case CS_EVENT_CARD_REMOVAL:
+               snd_printdd(KERN_DEBUG "CARD_REMOVAL..\n");
                link->state &= ~DEV_PRESENT;
                if (link->state & DEV_CONFIG) {
                        mod_timer(&link->release, jiffies + HZ/20);
-                       if (chip) {
-                               chip->is_stale = 1;
-                               snd_card_disconnect(chip->card);
-                               snd_card_free_in_thread(chip->card);
-                       }
+                       chip->is_stale = 1;
                }
                break;
        case CS_EVENT_CARD_INSERTION:
+               snd_printdd(KERN_DEBUG "CARD_INSERTION..\n");
                link->state |= DEV_PRESENT;
                vxpocket_config(link);
                break;
+#ifdef CONFIG_PM
        case CS_EVENT_PM_SUSPEND:
+               snd_printdd(KERN_DEBUG "SUSPEND\n");
                link->state |= DEV_SUSPEND;
-               if (chip)
-                       chip->in_suspend = 1;
+               if (chip) {
+                       snd_printdd(KERN_DEBUG "snd_vx_suspend calling\n");
+                       snd_vx_suspend(chip);
+               }
                /* Fall through... */
        case CS_EVENT_RESET_PHYSICAL:
+               snd_printdd(KERN_DEBUG "RESET_PHYSICAL\n");
                if (link->state & DEV_CONFIG)
                        CardServices(ReleaseConfiguration, link->handle);
                break;
        case CS_EVENT_PM_RESUME:
+               snd_printdd(KERN_DEBUG "RESUME\n");
                link->state &= ~DEV_SUSPEND;
                /* Fall through... */
        case CS_EVENT_CARD_RESET:
-               if (DEV_OK(link))
+               snd_printdd(KERN_DEBUG "CARD_RESET\n");
+               if (DEV_OK(link)) {
+                       //struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip;
+                       snd_printdd(KERN_DEBUG "requestconfig...\n");
                        CardServices(RequestConfiguration, link->handle, &link->conf);
-               if (chip) {
-                       /* FIXME: call resume... */
-                       chip->in_suspend = 0;
+                       if (chip) {
+                               snd_printdd(KERN_DEBUG "calling snd_vx_resume\n");
+                               snd_vx_resume(chip);
+                       }
                }
+               snd_printdd(KERN_DEBUG "resume done!\n");
                break;
+#endif
        }
        return 0;
 }
+
+/* we link this module statically with the card modules
+ * due to the pcmcia symbol problems...
+ */
+#if 0
+/*
+ * exported stuffs
+ */
+EXPORT_SYMBOL(snd_vxpocket_ops);
+EXPORT_SYMBOL(snd_vxpocket_attach);
+EXPORT_SYMBOL(snd_vxpocket_detach);
+EXPORT_SYMBOL(snd_vxpocket_detach_all);
+#endif

Index: vxp440.c
===================================================================
RCS file: /cvsroot/alsa/alsa-driver/pcmcia/vx/vxp440.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- vxp440.c    5 Nov 2002 17:11:40 -0000       1.2
+++ vxp440.c    9 Jan 2003 16:13:40 -0000       1.3
@@ -1,153 +1,14 @@
-/*
- * Driver for Digigram VXpocket 440 soundcard
- *
- * Copyright (c) 2002 by Takashi Iwai <[EMAIL PROTECTED]>
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- */
+#define COMPILE_VXP440
 
 /*
- * please add the following as /etc/pcmcia/vxpocket.conf:
- *
+ add the following as /etc/pcmcia/vxp440.conf:
 
-  device "snd-vxpocket"
-     class "audio" module "snd-vxpocket"
+  device "snd-vxp440"
+    class "audio" module "snd-vxp440"
 
   card "Digigram VX-POCKET440"
     manfid 0x01f1, 0x0100
     bind "snd-vxp440"
+*/
 
- */
-
-#include <sound/driver.h>
-#include <sound/core.h>
-#include <pcmcia/version.h>
-#include "vxpocket.h"
-#define SNDRV_GET_ID
-#include <sound/initval.h>
-
-
-/*
- */
-
-MODULE_AUTHOR("Takashi Iwai <[EMAIL PROTECTED]>");
-MODULE_DESCRIPTION("Digigram VXpocket440");
-MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Digigram,VXpocket440}}");
-
-static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;     /* Index 0-MAX */
-static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;      /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;     /* Enable switches */
-static unsigned int irq_mask = 0xffff;
-static int irq_list[4] = { -1 };
-
-MODULE_PARM(index, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
-MODULE_PARM_DESC(index, "Index value for VXPocket440 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
-MODULE_PARM(id, "1-" __MODULE_STRING(SNDRV_CARDS) "s");
-MODULE_PARM_DESC(id, "ID string for VXPocket440 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
-MODULE_PARM(enable, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
-MODULE_PARM_DESC(enable, "Enable VXPocket440 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
-MODULE_PARM(irq_mask, "i");
-MODULE_PARM_DESC(irq_mask, "IRQ bitmask for VXPocket440 soundcard.");
-MODULE_PARM(irq_list, "1-4i");
-MODULE_PARM_DESC(irq_list, "List of Available interrupts for VXPocket440 soundcard.");
- 
-
-/*
- */
-
-#include "xilinx_boot_vp4.c"
-#include "xilinx_image_vp4.c"
-#include "d563s3_boot.c"
-#include "dsp_image_vp4.c"
-
-static dev_info_t dev_info = "snd-vxp440";
-
-static struct snd_vxp_entry hw_entry = {
-       .name = "VXPocket440",
-       .type = VXP_TYPE_VXP440,
-       .dev_info = &dev_info,
-
-       /* module parameters */
-       .index_table = index,
-       .id_table = id,
-       .enable_table = enable,
-       .irq_mask_p = &irq_mask,
-       .irq_list = irq_list,
-
-       /* images */
-       .boot = { xilinx_boot_vxp440, sizeof(xilinx_boot_vxp440) },
-       .xilinx = { xilinx_image_vxp440, sizeof(xilinx_image_vxp440) },
-       .dsp_boot = { d563s3_boot, sizeof(d563s3_boot) },
-       .dsp = { dsp_image_vxp440, sizeof(dsp_image_vxp440) },
-
-       /* hardware specs */
-       /* 1 DSP, 1 sync UER, 1 sync World Clock (NIY) */
-       /* SMPTE (NIY) */
-       /* 2 stereo analog input (line/micro) */
-       /* 2 stereo analog output */
-       /* Only output levels can be modified */
-       /* UER, but only for the first two inputs and outputs. */
-       .num_codecs = 2,
-       .num_ins = 2,
-       .num_outs = 2,
-       
-};
-
-/*
- */
-static dev_link_t *vxp_attach(void)
-{
-       return snd_vxpocket_attach(&hw_entry);
-}
-
-static void vxp_detach(dev_link_t *link)
-{
-       snd_vxpocket_detach(&hw_entry, link);
-}
-
-
-/*
- * Module entry points
- */
-
-static int __init init_vxp440(void)
-{
-       servinfo_t serv;
-
-       CardServices(GetCardServicesInfo, &serv);
-       if (serv.Revision != CS_RELEASE_CODE) {
-               printk(KERN_WARNING "init_vxp440: Card Services release does not 
match!\n");
-               return -1;
-       }
-       register_pccard_driver(&dev_info, vxp_attach, vxp_detach);
-       return 0;
-}
-
-static void __exit exit_vxp440(void)
-{
-        unregister_pccard_driver(&dev_info);
-        snd_vxpocket_detach_all(&hw_entry);
-}
-
-module_init(init_vxp440);
-module_exit(exit_vxp440);
-
-
-EXPORT_NO_SYMBOLS; /* FIXME: for old kernels */
+#include "vxpocket.c"

Index: vxpocket.c
===================================================================
RCS file: /cvsroot/alsa/alsa-driver/pcmcia/vx/vxpocket.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- vxpocket.c  30 Oct 2002 16:44:23 -0000      1.1
+++ vxpocket.c  9 Jan 2003 16:13:46 -0000       1.2
@@ -1,5 +1,5 @@
 /*
- * Driver for Digigram VXpocket soundcard
+ * Driver for Digigram VXpocket V2/440 soundcards
  *
  * Copyright (c) 2002 by Takashi Iwai <[EMAIL PROTECTED]>
  *
@@ -19,9 +19,8 @@
  */
 
 /*
- * please add the following as /etc/pcmcia/vxpocket.conf:
- *
-
+ please add the following as /etc/pcmcia/vxpocket.conf:
+ 
   device "snd-vxpocket"
      class "audio" module "snd-vxpocket"
 
@@ -41,11 +40,17 @@
 /*
  */
 
+#ifdef COMPILE_VXP440
+#define CARD_NAME      "VXPocket440"
+#else
+#define CARD_NAME      "VXPocket"
+#endif
+
 MODULE_AUTHOR("Takashi Iwai <[EMAIL PROTECTED]>");
-MODULE_DESCRIPTION("Digigram VXpocket");
+MODULE_DESCRIPTION("Digigram " CARD_NAME);
 MODULE_LICENSE("GPL");
 MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Digigram,VXpocket}}");
+MODULE_DEVICES("{{Digigram," CARD_NAME "}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;     /* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;      /* ID for this card */
@@ -54,16 +59,16 @@
 static int irq_list[4] = { -1 };
 
 MODULE_PARM(index, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
-MODULE_PARM_DESC(index, "Index value for VXPocket soundcard.");
+MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");
 MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 MODULE_PARM(id, "1-" __MODULE_STRING(SNDRV_CARDS) "s");
-MODULE_PARM_DESC(id, "ID string for VXPocket soundcard.");
+MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard.");
 MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 MODULE_PARM(enable, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
-MODULE_PARM_DESC(enable, "Enable VXPocket soundcard.");
+MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard.");
 MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 MODULE_PARM(irq_mask, "i");
-MODULE_PARM_DESC(irq_mask, "IRQ bitmask for VXPocket soundcard.");
+MODULE_PARM_DESC(irq_mask, "IRQ bitmask for " CARD_NAME " soundcard.");
 MODULE_PARM(irq_list, "1-4i");
 MODULE_PARM_DESC(irq_list, "List of Available interrupts for VXPocket soundcard.");
  
@@ -71,16 +76,70 @@
 /*
  */
 
+#ifdef COMPILE_VXP440
+/*
+ * VXpocket 440
+ */
+#include "xilinx_boot_vp4.c"
+#include "xilinx_image_vp4.c"
+#include "d563s3_boot.c"
+#include "dsp_image_vp4.c"
+static dev_info_t dev_info = "snd-vxp440";
+
+/* 1 DSP, 1 sync UER, 1 sync World Clock (NIY) */
+/* SMPTE (NIY) */
+/* 2 stereo analog input (line/micro) */
+/* 2 stereo analog output */
+/* Only output levels can be modified */
+/* UER, but only for the first two inputs and outputs. */
+
+#define NUM_CODECS     2
+#define CARD_TYPE      VX_TYPE_VXP440
+
+#else
+/*
+ * VXpocket V2
+ */
 #include "xilinx_boot_vxp.c"
 #include "xilinx_image_vxp.c"
 #include "d563s3_boot.c"
 #include "dsp_image_vxp.c"
-
 static dev_info_t dev_info = "snd-vxpocket";
 
+/* 1 DSP, 1 sync UER */
+/* 1 programmable clock (NIY) */
+/* 1 stereo analog input (line/micro) */
+/* 1 stereo analog output */
+/* Only output levels can be modified */
+
+#define NUM_CODECS     1
+#define CARD_TYPE      VX_TYPE_VXPOCKET
+#endif
+
+
+static struct snd_vx_hardware vxp_hw = {
+       .name = CARD_NAME,
+       .type = CARD_TYPE,
+
+       /* images */
+#ifdef COMPILE_VXP440
+       .boot = { xilinx_boot_vxp440, sizeof(xilinx_boot_vxp440) },
+       .xilinx = { xilinx_image_vxp440, sizeof(xilinx_image_vxp440) },
+       .dsp_boot = { d563s3_boot, sizeof(d563s3_boot) },
+       .dsp = { dsp_image_vxp440, sizeof(dsp_image_vxp440) },
+#else
+       .boot = { xilinx_boot_vxpocket, sizeof(xilinx_boot_vxpocket) },
+       .xilinx = { xilinx_image_vxpocket, sizeof(xilinx_image_vxpocket) },
+       .dsp_boot = { d563s3_boot, sizeof(d563s3_boot) },
+       .dsp = { dsp_image_vxpocket, sizeof(dsp_image_vxpocket) },
+#endif
+       /* hardware specs */
+       .num_codecs = NUM_CODECS,
+       .num_ins = NUM_CODECS,
+       .num_outs = NUM_CODECS,
+};     
+
 static struct snd_vxp_entry hw_entry = {
-       .name = "VXPocket",
-       .type = VXP_TYPE_VXPOCKET,
        .dev_info = &dev_info,
 
        /* module parameters */
@@ -90,22 +149,9 @@
        .irq_mask_p = &irq_mask,
        .irq_list = irq_list,
 
-       /* images */
-       .boot = { xilinx_boot_vxpocket, sizeof(xilinx_boot_vxpocket) },
-       .xilinx = { xilinx_image_vxpocket, sizeof(xilinx_image_vxpocket) },
-       .dsp_boot = { d563s3_boot, sizeof(d563s3_boot) },
-       .dsp = { dsp_image_vxpocket, sizeof(dsp_image_vxpocket) },
-
-       /* hardware specs */
-       /* 1 DSP, 1 sync UER */
-       /* 1 programmable clock (NIY) */
-       /* 1 stereo analog input (line/micro) */
-       /* 1 stereo analog output */
-       /* Only output levels can be modified */
-       .num_codecs = 1,
-       .num_ins = 1,
-       .num_outs = 1,
-       
+       /* h/w config */
+       .hardware = &vxp_hw,
+       .ops = &snd_vxpocket_ops,
 };
 
 /*

Index: vxpocket.conf
===================================================================
RCS file: /cvsroot/alsa/alsa-driver/pcmcia/vx/vxpocket.conf,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- vxpocket.conf       5 Nov 2002 17:11:39 -0000       1.2
+++ vxpocket.conf       9 Jan 2003 16:13:46 -0000       1.3
@@ -15,7 +15,3 @@
   manfid 0x01f1, 0x0100
   bind "snd-vxpocket"
 
-card "Digigram VX-POCKET440"
-  manfid 0x01f1, 0x0100
-  bind "snd-vxp440"
-

Index: vxpocket.h
===================================================================
RCS file: /cvsroot/alsa/alsa-driver/pcmcia/vx/vxpocket.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- vxpocket.h  11 Dec 2002 15:36:33 -0000      1.4
+++ vxpocket.h  9 Jan 2003 16:13:47 -0000       1.5
@@ -21,25 +21,14 @@
 #ifndef __VXPOCKET_H
 #define __VXPOCKET_H
 
+#include "vx_core.h"
+
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
-typedef struct snd_vxpocket vxpocket_t;
-typedef struct vx_pipe vx_pipe_t;
-
-#define vxpocket_t_magic       0xa15a4101
-#define vx_pipe_t_magic                0xa15a4102
-
-struct snd_vxp_image {
-       unsigned char *image;
-       unsigned int length;
-};
-
 struct snd_vxp_entry {
-       const char *name;
-       int type;       /* VXP_TYPE_XXX */
        dev_info_t *dev_info;
 
        /* module parameters */
@@ -49,127 +38,38 @@
        unsigned int *irq_mask_p;
        int *irq_list;
 
-       /* images */
-       struct snd_vxp_image boot;
-       struct snd_vxp_image xilinx;
-       struct snd_vxp_image dsp_boot;
-       struct snd_vxp_image dsp;
-
-       /* hardware specs */
-       int num_codecs;
-       int num_ins;
-       int num_outs;
+       /* h/w config */
+       struct snd_vx_hardware *hardware;
+       struct snd_vx_ops *ops;
 
        /* slots */
-       vxpocket_t *card_list[SNDRV_CARDS];
+       vx_core_t *card_list[SNDRV_CARDS];
        dev_link_t *dev_list;           /* Linked list of devices */
 };
 
-/*
- */
-#define SIZE_MAX_CMD    0x10
-#define SIZE_MAX_STATUS 0x10
-
-struct vx_rmh {
-       u16     LgCmd;          /* length of the command to send (WORDs) */
-       u16     LgStat;         /* length of the status received (WORDs) */
-       u32     Cmd[SIZE_MAX_CMD];
-       u32     Stat[SIZE_MAX_STATUS];
-       u16     DspStat;        /* status type, RMP_SSIZE_XXX */
-};
-       
-typedef u64 pcx_time_t;
+struct snd_vxpocket {
 
-#define VXP_MAX_PIPES  16
-#define VXP_MAX_CODECS 2
+       vx_core_t core;
 
-#define VXP_MAX_PERIODS        32
+       unsigned long port;
 
-struct vx_ibl_info {
-       int size;       /* the current IBL size (0 = query) in bytes */
-       int max_size;   /* max. IBL size in bytes */
-       int min_size;   /* min. IBL size in bytes */
-       int granularity;        /* granularity */
-};
+       int mic_level;  /* analog mic level (or boost) */
 
-struct vx_pipe {
-       int number;
-       unsigned int is_capture: 1;
-       unsigned int data_mode: 1;
-       unsigned int running: 1;
-       unsigned int prepared: 1;
-       int channels;
-       unsigned int differed_type;
-       pcx_time_t pcx_time;
-       snd_pcm_substream_t *substream;
-
-       int hbuf_size;          /* H-buffer size in bytes */
-       int buffer_bytes;       /* the ALSA pcm buffer size in bytes */
-       int hw_ptr;             /* the current hardware pointer in frames */
-       int position;           /* the current position in frames (playback only) */
-       int transferred;        /* the transferred size (per period) in frames */
-       int chunk_transferred;  /* the transferred size (per period) in frames */
-       int align;              /* size of alignment */
-       u64 cur_count;          /* current sample position (for playback) */
+       unsigned int regCDSP;   /* current CDSP register */
+       unsigned int regDIALOG; /* current DIALOG register */
 
-       struct tasklet_struct start_tq;
-};
+       int index;
+       struct snd_vxp_entry *hw_entry;
 
-struct snd_vxpocket {
        /* pcmcia stuff */
        dev_link_t link;
        dev_node_t node;
+};
 
-       /* board-speicific entry */
-       struct snd_vxp_entry *hw;
-
-       /* ALSA stuff */
-       snd_card_t *card;
-       snd_pcm_t *pcm[VXP_MAX_CODECS];
-       snd_info_entry_t *proc_entry;
-
-       int index;
-       unsigned long port;
-       int irq;
+extern struct snd_vx_ops snd_vxpocket_ops;
 
-       spinlock_t lock;
-       spinlock_t irq_lock;
-       struct tasklet_struct tq;
-
-       unsigned int initialized: 1;
-       unsigned int in_suspend: 1;
-       unsigned int xilinx_tested: 1;
-       unsigned int is_stale: 1;
-
-       unsigned int pcm_running;
-
-       int regCDSP;    /* current CDSP register */
-       int regDIALOG;  /* current DIALOG register */
-
-       struct vx_rmh irq_rmh;  /* RMH used in interrupts */
-
-       unsigned int audio_info; /* see VX_AUDIO_INFO */
-       int audio_ins;
-       int audio_outs;
-       struct vx_pipe **playback_pipes;
-       struct vx_pipe **capture_pipes;
-
-       int output_level[VXP_MAX_CODECS][2];    /* analog output level */
-       int mic_level;                          /* analog mic level (or boost) */
-       int audio_gain[2][4];                   /* digital audio level 
(playback/capture) */
-       unsigned char audio_active[4];          /* mute/unmute on digital playback */
-       int audio_monitor[4];                   /* playback hw-monitor level */
-       unsigned char audio_monitor_active[4];  /* playback hw-monitor mute/unmute */
-
-       int audio_source;       /* current audio input source */
-       int audio_source_target;
-       int clock_source;       /* current clock source (INTERNAL_QUARTZ or UER_SYNC) 
*/
-       int freq;               /* current frequency */
-       int freq_detected;      /* detected frequency from digital in */
-       int uer_detected;       /* VXP_UER_MODE_XXX */
-       unsigned int uer_bits;  /* IEC958 status bits */
-       struct vx_ibl_info ibl; /* IBL information */
-};
+void vx_set_mic_boost(vx_core_t *chip, int boost);
+void vx_set_mic_level(vx_core_t *chip, int level);
 
 /*
  * pcmcia stuff
@@ -178,183 +78,8 @@
 void snd_vxpocket_detach(struct snd_vxp_entry *hw, dev_link_t *link);
 void snd_vxpocket_detach_all(struct snd_vxp_entry *hw);
 
-/*
- * core constructor/destructor, exported
- */
-vxpocket_t *snd_vxpocket_create_chip(struct snd_vxp_entry *hw);
-void snd_vxpocket_free_chip(vxpocket_t *chip);
-int snd_vxpocket_assign_resources(vxpocket_t *chip, int port, int irq);
-
-/*
- * mixer
- */
-int snd_vxpocket_mixer_new(vxpocket_t *chip);
-
-/*
- * pcm stuff
- */
-int snd_vxpocket_pcm_new(vxpocket_t *chip);
-void vx_pcm_playback_update(vxpocket_t *chip, snd_pcm_substream_t *subs, vx_pipe_t 
*pipe);
-void vx_pcm_playback_update_buffer(vxpocket_t *chip, snd_pcm_substream_t *subs, 
vx_pipe_t *pipe);
-void vx_pcm_capture_update(vxpocket_t *chip, snd_pcm_substream_t *subs, vx_pipe_t 
*pipe);
-
-/*
- * interrupt handler
- */
-void snd_vx_irq_handler(int irq, void *dev, struct pt_regs *regs); /* exported */
-int vx_test_and_ack(vxpocket_t *chip);
-void vx_validate_irq(vxpocket_t *chip, int enable);
-void vx_interrupt(unsigned long private_data);
+int vxp_add_mic_controls(vx_core_t *chip);
 
-/*
- * lowlevel functions
- */
-void vx_delay(vxpocket_t *chip, int msec);
-int snd_vx_inb(vxpocket_t *chip, int offset);
-void snd_vx_outb(vxpocket_t *chip, int offset, int val);
-#define vx_inb(chip,reg)       snd_vx_inb(chip, VXP_##reg)
-#define vx_outb(chip,reg,val)  snd_vx_outb(chip, VXP_##reg, val)
-
-int vx_send_msg(vxpocket_t *chip, struct vx_rmh *rmh);
-int vx_send_msg_nolock(vxpocket_t *chip, struct vx_rmh *rmh);
-int vx_send_rih(vxpocket_t *chip, int cmd);
-int vx_send_rih_nolock(vxpocket_t *chip, int cmd);
-
-void vx_reset_codec(vxpocket_t *chip);
-void vx_toggle_dac_mute(vxpocket_t *chip, int mute);
-int vx_sync_audio_source(vxpocket_t *chip);
-void vx_reset_audio_levels(vxpocket_t *chip);
-
-void vx_set_iec958_status(vxpocket_t *chip, unsigned int bits);
-int vx_set_clock(vxpocket_t *chip, int freq);
-void vx_set_internal_clock(vxpocket_t *chip, int freq);
-
-int vx_change_frequency(vxpocket_t *chip);
-
-
-/* error with hardware code,
- * the return value is -(VXP_ERR_MASK | actual-hw-error-code)
- */
-#define VXP_ERR_MASK   0x1000000
-#define vx_get_error(err)      (-(err) & ~VXP_ERR_MASK)
-
-
-/*
- * hardware constants
- */
-
-/* hardware type */
-enum {
-       VXP_TYPE_VXPOCKET,
-       VXP_TYPE_VXP440,
-};
-
-/* audio input source */
-enum {
-       VXP_AUDIO_SRC_LINE = 0x00,
-       VXP_AUDIO_SRC_MIC = 0x01,
-       VXP_AUDIO_SRC_DIGITAL = 0x02,
-};
-
-/* clock source */
-enum {
-       INTERNAL_QUARTZ,
-       UER_SYNC
-};
-
-/* SPDIF/UER type */
-enum {
-       VXP_UER_MODE_CONSUMER,
-       VXP_UER_MODE_PROFESSIONAL,
-       VXP_UER_MODE_NOT_PRESENT,
-};
-
-/* register offsets */
-enum {
-       VXP_ICR         = 0x00,
-       VXP_CVR         = 0x01,
-       VXP_ISR         = 0x02,
-       VXP_IVR         = 0x03,
-       VXP_DMA         = 0x04,
-       VXP_RXH         = 0x05,
-       VXP_RXM         = 0x06,
-       VXP_RXL         = 0x07,
-       VXP_TXH         = 0x05,
-       VXP_TXM         = 0x06,
-       VXP_TXL         = 0x07,
-       VXP_CDSP        = 0x08,
-       VXP_LOFREQ      = 0x09,
-       VXP_HIFREQ      = 0x0a,
-       VXP_DATA        = 0x0b,
-       VXP_MICRO       = 0x0c,
-       VXP_CODEC2      = VXP_MICRO,    /* 2nd codec, VXP440 only */
-       VXP_DIALOG      = 0x0d,
-       VXP_CSUER       = 0x0e,
-       VXP_RUER        = 0x0f,
-};
-
-/* RMH status type */
-enum {
-       RMH_SSIZE_FIXED = 0,    /* status size given by the driver (in LgStat) */
-       RMH_SSIZE_ARG = 1,      /* status size given in the LSB byte */
-       RMH_SSIZE_MASK = 2,     /* status size given in bitmask */
-};
-
-
-/* bits for ICR register */
-#define ICR_HF1                0x10
-#define ICR_HF0                0x08
-#define ICR_TREQ       0x02    /* Interrupt mode + HREQ set on for transfer (->DSP) 
request */
-#define ICR_RREQ       0x01    /* Interrupt mode + RREQ set on for transfer (->PC) 
request */
-
-/* bits for CVR register */
-#define CVR_HC         0x80
-
-/* bits for ISR register */
-#define ISR_HF3                0x10
-#define ISR_HF2                0x08
-#define ISR_CHK                0x10
-#define ISR_ERR                0x08
-#define ISR_TX_READY   0x04
-#define ISR_TX_EMPTY   0x02
-#define ISR_RX_FULL    0x01
-
-/* bits for audio_info */
-#define VX_AUDIO_INFO_REAL_TIME        (1<<0)  /* real-time processing available */
-#define VX_AUDIO_INFO_OFFLINE  (1<<1)  /* offline processing available */
-#define VX_AUDIO_INFO_MPEG1    (1<<5)
-#define VX_AUDIO_INFO_MPEG2    (1<<6)
-#define VX_AUDIO_INFO_LINEAR_8 (1<<7)
-#define VX_AUDIO_INFO_LINEAR_16        (1<<8)
-#define VX_AUDIO_INFO_LINEAR_24        (1<<9)
-
-/* Constants used to access the Codec */
-#define XX_CODEC_SELECTOR               0x20
-/* codec commands */
-#define XX_CODEC_ADC_CONTROL_REGISTER   0x01
-#define XX_CODEC_DAC_CONTROL_REGISTER   0x02
-#define XX_CODEC_LEVEL_LEFT_REGISTER    0x03
-#define XX_CODEC_LEVEL_RIGHT_REGISTER   0x04
-#define XX_CODEC_PORT_MODE_REGISTER     0x05
-#define XX_CODEC_STATUS_REPORT_REGISTER 0x06
-#define XX_CODEC_CLOCK_CONTROL_REGISTER 0x07
-
-/* DSP Interrupt Request values */
-/* add 0x40 offset for vxpocket */
-#define VXP_IRQ_OFFSET         0x40
-/* call with vx_send_irq_dsp() */
-#define IRQ_MESS_WRITE_END          0x30
-#define IRQ_MESS_WRITE_NEXT         0x32
-#define IRQ_MESS_READ_NEXT          0x34
-#define IRQ_MESS_READ_END           0x36
-#define IRQ_MESSAGE                 0x38
-#define IRQ_RESET_CHK               0x3A
-#define IRQ_CONNECT_STREAM_NEXT     0x26
-#define IRQ_CONNECT_STREAM_END      0x28
-#define IRQ_PAUSE_START_CONNECT     0x2A
-#define IRQ_END_CONNECTION          0x2C
-
-/* VXPOCKET */
 /* Constants used to access the CDSP register (0x08). */
 #define CDSP_MAGIC     0xA7    /* magic value (for read) */
 /* for write */
@@ -377,14 +102,6 @@
 #define P44_MEMIRQ_WCLK_OUT_IN_SEL_MASK  0x02 /* Not used */
 #define P44_MEMIRQ_WCLK_UER_SEL_MASK     0x01 /* Not used */
 
-/* Constants used to access the LOFREQ and HIFREQ registers (0x09 et 0x0A). */
-#define VXP_LOFREQ_VAL(v)      ((v) & 0x0000ff)
-#define VXP_HIFREQ_VAL(v)      (((v) & 0x000f00)>>8)
-
-/* Constants used to access the DATA register (0x0B). */
-#define VXP_DATA_CODEC_MASK    0x80
-#define VXP_DATA_XICOR_MASK    0x80
-
 /* Micro levels (0x0C) */
 
 /* Constants used to access the DIALOG register (0x0D). */
@@ -398,62 +115,6 @@
 #define VXP_DLG_MEMIRQ_MASK            0x02    /* R */
 #define VXP_DLG_DMA16_SEL_MASK         0x02    /* W */
 #define VXP_DLG_ACK_MEMIRQ_MASK                0x01    /* R/W */
-
-/* Constants used to access the CSUER register (0x0E) */
-#define VXP_SUER_FREQ_MASK             0x0C
-#define VXP_SUER_FREQ_32KHz_MASK       0x0C
-#define VXP_SUER_FREQ_44KHz_MASK       0x00
-#define VXP_SUER_FREQ_48KHz_MASK       0x04
-#define VXP_SUER_DATA_PRESENT_MASK     0x02
-#define VXP_SUER_CLOCK_PRESENT_MASK    0x01
-
-#define VXP_CUER_HH_BITC_SEL_MASK      0x00000008    // then read data in RUER
-#define VXP_CUER_MH_BITC_SEL_MASK      0x00000004    // then read data in RUER
-#define VXP_CUER_ML_BITC_SEL_MASK      0x00000002    // then read data in RUER
-#define VXP_CUER_LL_BITC_SEL_MASK      0x00000001    // then read data in RUER
-
-#define XX_UER_CBITS_OFFSET_MASK       0x1F
-
-
-/* Is there async. events pending ( IT Source Test ) */
-#define ASYNC_EVENTS_PENDING            0x008000
-#define HBUFFER_EVENTS_PENDING          0x004000   // Not always accurate
-#define NOTIF_EVENTS_PENDING            0x002000
-#define TIME_CODE_EVENT_PENDING         0x001000
-#define FREQUENCY_CHANGE_EVENT_PENDING  0x000800
-#define END_OF_BUFFER_EVENTS_PENDING    0x000400
-#define FATAL_DSP_ERROR                 0xff0000
-
-/* Stream Format Header Defines */ 
-#define HEADER_FMT_BASE                        0xFED00000
-#define HEADER_FMT_MONO                        0x000000C0
-#define HEADER_FMT_INTEL               0x00008000
-#define HEADER_FMT_16BITS              0x00002000
-#define HEADER_FMT_24BITS              0x00004000
-#define HEADER_FMT_UPTO11              0x00000200      /* frequency is less or equ. 
to 11k.*/
-#define HEADER_FMT_UPTO32              0x00000100      /* frequency is over 11k and 
less then 32k.*/
-
-
-/*
- * Audio-level control values
- */
-#define CVAL_M110DB            0x000   /* -110dB */
-#define CVAL_M99DB             0x02C
-#define CVAL_M21DB             0x163
-#define CVAL_M18DB             0x16F
-#define CVAL_M10DB             0x18F
-#define CVAL_0DB               0x1B7
-#define CVAL_18DB              0x1FF   /* +18dB */
-#define CVAL_MAX               0x1FF
-
-#define AUDIO_IO_HAS_MUTE_LEVEL                        0x400000
-#define AUDIO_IO_HAS_MUTE_MONITORING_1         0x200000
-#define AUDIO_IO_HAS_MUTE_MONITORING_2         0x100000
-#define VALID_AUDIO_IO_DIGITAL_LEVEL           0x01
-#define VALID_AUDIO_IO_MONITORING_LEVEL                0x02
-#define VALID_AUDIO_IO_MUTE_LEVEL              0x04
-#define VALID_AUDIO_IO_MUTE_MONITORING_1       0x08
-#define VALID_AUDIO_IO_MUTE_MONITORING_2       0x10
 
 
 #endif /* __VXPOCKET_H */

Index: xilinx_image_vp4.c
===================================================================
RCS file: /cvsroot/alsa/alsa-driver/pcmcia/vx/xilinx_image_vp4.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- xilinx_image_vp4.c  30 Oct 2002 16:44:23 -0000      1.1
+++ xilinx_image_vp4.c  9 Jan 2003 16:13:49 -0000       1.2
@@ -20,6 +20,52 @@
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
+#if 0
+/*
+ * this file was converted from the xilinx bit-stream file
+ * x1_1_vp4.rbt.
+ */
+
+#include <stdio.h>
+
+int main()
+{
+       static char buf[256];
+       int data, c, idx;
+       char *p;
+
+       c = 0;
+       data = 0;
+       idx = 0;
+       while (fgets(buf, sizeof(buf), stdin)) {
+               if (buf[0] != '0' && buf[1] != '1') {
+                       fprintf(stderr, "skipping %s", buf);
+                       continue;
+               }
+               for (p = buf; *p == '0' || *p == '1'; p++) {
+                       data |= (*p - '0') << c;
+                       c++;
+                       if (c >= 8) {
+                               printf("0x%02x,", data);
+                               if (idx % 16 == 15)
+                                       printf("\n");
+                               data = 0;
+                               c = 0;
+                               idx++;
+                       }
+               }
+       }
+       if (c) {
+               printf("0x%02x,", data);
+               idx++;
+       }
+       if (idx % 16)
+               printf("\n");
+       fprintf(stderr, "counts = %d\n", idx);
+       return 0;
+}
+#endif
+
 static unsigned char xilinx_image_vxp440[22395] = {
 0xff,0x04,0xd4,0xbd,0xf8,0xda,0xbf,0xfe,0x7a,0x7f,0xd7,0x9f,0x7e,0xfd,0x7d,0xa7,
 0xdf,0x7f,0xdd,0xdd,0xdd,0xd6,0xda,0xed,0xa7,0x5f,0xd7,0xfd,0xed,0xad,0xdf,0x77,

Index: xilinx_image_vxp.c
===================================================================
RCS file: /cvsroot/alsa/alsa-driver/pcmcia/vx/xilinx_image_vxp.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- xilinx_image_vxp.c  30 Oct 2002 16:44:23 -0000      1.1
+++ xilinx_image_vxp.c  9 Jan 2003 16:13:52 -0000       1.2
@@ -20,6 +20,52 @@
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
+#if 0
+/*
+ * this file was converted from the xilinx bit-stream file
+ * x1_1_vxp.rbt.
+ */
+
+#include <stdio.h>
+
+int main()
+{
+       static char buf[256];
+       int data, c, idx;
+       char *p;
+
+       c = 0;
+       data = 0;
+       idx = 0;
+       while (fgets(buf, sizeof(buf), stdin)) {
+               if (buf[0] != '0' && buf[1] != '1') {
+                       fprintf(stderr, "skipping %s", buf);
+                       continue;
+               }
+               for (p = buf; *p == '0' || *p == '1'; p++) {
+                       data |= (*p - '0') << c;
+                       c++;
+                       if (c >= 8) {
+                               printf("0x%02x,", data);
+                               if (idx % 16 == 15)
+                                       printf("\n");
+                               data = 0;
+                               c = 0;
+                               idx++;
+                       }
+               }
+       }
+       if (c) {
+               printf("0x%02x,", data);
+               idx++;
+       }
+       if (idx % 16)
+               printf("\n");
+       fprintf(stderr, "counts = %d\n", idx);
+       return 0;
+}
+#endif
+
 static unsigned char xilinx_image_vxpocket[22395] = {
 0xff,0x04,0xd4,0xbd,0xf8,0xda,0xbf,0xdf,0x5a,0x7f,0xd7,0x75,0x7f,0x5d,0x7f,0xa7,
 0xdf,0x5f,0xfd,0xdd,0x5d,0xd7,0xfa,0xed,0xa7,0x77,0xd7,0xfd,0xed,0xad,0xdf,0x7e,

--- vx_cmd.c DELETED ---

--- vx_cmd.h DELETED ---

--- vx_core.c DELETED ---

--- vx_irq.c DELETED ---

--- vx_mixer.c DELETED ---

--- vx_pcm.c DELETED ---

--- vx_uer.c DELETED ---



-------------------------------------------------------
This SF.NET email is sponsored by:
SourceForge Enterprise Edition + IBM + LinuxWorld = Something 2 See!
http://www.vasoftware.com
_______________________________________________
Alsa-cvslog mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/alsa-cvslog

Reply via email to