/*
* Driver for Digigram VX222 V2/Mic soundcards
*
* VX222-specific low-level routines
*
* Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
*
* 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 <linux/delay.h>
#include <linux/device.h>
#include <linux/firmware.h>
#include <linux/mutex.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/tlv.h>
#include <asm/io.h>
#include "vx222.h"
static int vx2_reg_offset[VX_REG_MAX] = {
[VX_ICR] = 0x00,
[VX_CVR] = 0x04,
[VX_ISR] = 0x08,
[VX_IVR] = 0x0c,
[VX_RXH] = 0x14,
[VX_RXM] = 0x18,
[VX_RXL] = 0x1c,
[VX_DMA] = 0x10,
[VX_CDSP] = 0x20,
[VX_CFG] = 0x24,
[VX_RUER] = 0x28,
[VX_DATA] = 0x2c,
[VX_STATUS] = 0x30,
[VX_LOFREQ] = 0x34,
[VX_HIFREQ] = 0x38,
[VX_CSUER] = 0x3c,
[VX_SELMIC] = 0x40,
[VX_COMPOT] = 0x44, // Write: POTENTIOMETER ; Read: COMPRESSION LEVEL activate
[VX_SCOMPR] = 0x48, // Read: COMPRESSION THRESHOLD activate
[VX_GLIMIT] = 0x4c, // Read: LEVEL LIMITATION activate
[VX_INTCSR] = 0x4c, // VX_INTCSR_REGISTER_OFFSET
[VX_CNTRL] = 0x50, // VX_CNTRL_REGISTER_OFFSET
[VX_GPIOC] = 0x54, // VX_GPIOC (new with PLX9030)
};
static int vx2_reg_index[VX_REG_MAX] = {
[VX_ICR] = 1,
[VX_CVR] = 1,
[VX_ISR] = 1,
[VX_IVR] = 1,
[VX_RXH] = 1,
[VX_RXM] = 1,
[VX_RXL] = 1,
[VX_DMA] = 1,
[VX_CDSP] = 1,
[VX_CFG] = 1,
[VX_RUER] = 1,
[VX_DATA] = 1,
[VX_STATUS] = 1,
[VX_LOFREQ] = 1,
[VX_HIFREQ] = 1,
[VX_CSUER] = 1,
[VX_SELMIC] = 1,
[VX_COMPOT] = 1,
[VX_SCOMPR] = 1,
[VX_GLIMIT] = 1,
[VX_INTCSR] = 0, /* on the PLX */
[VX_CNTRL] = 0, /* on the PLX */
[VX_GPIOC] = 0, /* on the PLX */
};
static inline unsigned long vx2_reg_addr(struct vx_core *_chip, int reg)
{
struct snd_vx222 *chip = (struct snd_vx222 *)_chip;
return chip->port[vx2_reg_index[reg]] + vx2_reg_offset[reg];
}
/**
* snd_vx_inb - read a byte from the register
* @offset: register enum
*/
static unsigned char vx2_inb(struct vx_core *chip, int offset)
{
return inb(vx2_reg_addr(chip, offset));
}
/**
* snd_vx_outb - write a byte on the register
* @offset: the register offset
* @val: the value to write
*/
static void vx2_outb(struct vx_core *chip, int offset, unsigned char val)
{
outb(val, vx2_reg_addr(chip, offset));
//printk("outb: %x -> %x\n", val, vx2_reg_addr(chip, offset));
}
/**
* snd_vx_inl - read a 32bit word from the register
* @offset: register enum
*/
static unsigned int vx2_inl(struct vx_core *chip, int offset)
{
return inl(vx2_reg_addr(chip, offset));
}
/**
* snd_vx_outl - write a 32bit word on the register
* @offset: the register enum
* @val: the value to write
*/
static void vx2_outl(struct vx_core *chip, int offset, unsigned int val)
{
// printk("outl: %x -> %x\n", val, vx2_reg_addr(chip, offset));
outl(val, vx2_reg_addr(chip, offset));
}
/*
* redefine macros to call directly
*/
#undef vx_inb
#define vx_inb(chip,reg) vx2_inb((struct vx_core*)(chip), VX_##reg)
#undef vx_outb
#define vx_outb(chip,reg,val) vx2_outb((struct vx_core*)(chip), VX_##reg, val)
#undef vx_inl
#define vx_inl(chip,reg) vx2_inl((struct vx_core*)(chip), VX_##reg)
#undef vx_outl
#define vx_outl(chip,reg,val) vx2_outl((struct vx_core*)(chip), VX_##reg, val)
/*
* vx_reset_dsp - reset the DSP
*/
#define XX_DSP_RESET_WAIT_TIME 2 /* ms */
static void vx2_reset_dsp(struct vx_core *_chip)
{
struct snd_vx